Merge mozilla-central to mozilla-autoland. r=merge a=merge on a CLOSED TREE

This commit is contained in:
Csoregi Natalia 2017-11-06 12:49:03 +02:00
commit f51f922391
36 changed files with 445 additions and 911 deletions

View File

@ -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}"

View File

@ -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<mozilla::dom::NodeInfo>& 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<HTMLMediaElement> 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<HTMLMediaElement> 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<Promise>
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();

View File

@ -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<MediaDecoder> mDecoder;
@ -1544,12 +1534,6 @@ protected:
// Encrypted Media Extension media keys.
RefPtr<MediaKeys> mMediaKeys;
RefPtr<MediaKeys> mIncomingMediaKeys;
// The dom promise is used for HTMLMediaElement::SetMediaKeys.
RefPtr<DetailedPromise> mSetMediaKeysDOMPromise;
// Used to indicate if the MediaKeys attaching operation is on-going or not.
bool mAttachingMediaKey;
MozPromiseRequestHolder<SetCDMPromise> mSetCDMRequest;
// Stores the time at the start of the current 'played' range.
double mCurrentPlayRangeStart;

View File

@ -1423,15 +1423,18 @@ MediaDecoder::CanPlayThrough()
return val;
}
RefPtr<SetCDMPromise>
void
MediaDecoder::SetCDMProxy(CDMProxy* aProxy)
{
MOZ_ASSERT(NS_IsMainThread());
return InvokeAsync<RefPtr<CDMProxy>>(mReader->OwnerThread(),
mReader.get(),
__func__,
&MediaFormatReader::SetCDMProxy,
aProxy);
RefPtr<CDMProxy> proxy = aProxy;
RefPtr<MediaFormatReader> reader = mReader;
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(
"MediaFormatReader::SetCDMProxy",
[reader, proxy]() {
reader->SetCDMProxy(proxy);
});
mReader->OwnerThread()->Dispatch(r.forget());
}
bool

View File

@ -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<SetCDMPromise> SetCDMProxy(CDMProxy* aProxy);
void SetCDMProxy(CDMProxy* aProxy);
void EnsureTelemetryReported();

View File

@ -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<SetCDMPromise>
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<SetCDMPromise> p = mSetCDMPromise.Ensure(__func__);
return p;
RefPtr<CDMProxy> proxy = aProxy;
RefPtr<MediaFormatReader> self = this;
nsCOMPtr<nsIRunnable> 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;
}

View File

@ -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<bool, MediaResult, IsExclusive> NotifyDataArrivedPromise;
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaFormatReader)
public:
@ -194,7 +194,7 @@ public:
// cases like MSE.
bool UseBufferingHeuristics() const { return mTrackDemuxersMayBlock; }
RefPtr<SetCDMPromise> 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<SetCDMPromise> mSetCDMPromise;
TrackSet mSetCDMForTracks{};
bool IsDecoderWaitingForCDM(TrackType aTrack);
};
} // namespace mozilla

View File

@ -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<bool /* aIgnored */, MediaResult, /* IsExclusive */ true>;
} // namespace mozilla
#endif

View File

@ -121,7 +121,6 @@ EXPORTS += [
'MediaMetadataManager.h',
'MediaMIMETypes.h',
'MediaPrefs.h',
'MediaPromiseDefs.h',
'MediaQueue.h',
'MediaRecorder.h',
'MediaResource.h',

View File

@ -929,7 +929,7 @@ D3D11DXVA2Manager::CopyToImage(IMFSample* aVideoSample,
NS_ENSURE_TRUE(client, E_FAIL);
RefPtr<IDXGIKeyedMutex> mutex;
HRESULT hr;
HRESULT hr = S_OK;
RefPtr<ID3D11Texture2D> 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);

View File

@ -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

View File

@ -1 +0,0 @@
Cache-Control: no-store

View File

@ -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

View File

@ -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)

View File

@ -1,144 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test Encrypted Media Extensions</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script type="text/javascript" src="manifest.js"></script>
<script type="text/javascript" src="http://test1.mochi.test:8888/tests/dom/media/test/eme.js"></script>
</head>
<body>
<pre id="test">
<video id="v" controls></video>
<script class="testbody" type="text/javascript">
var manager = new MediaTestManager;
var EMEmanifest = [
{
name:"bipbop 10s",
tracks: [
{
name:"video",
type:"video/mp4; codecs=\"avc1.4d4015\"",
fragments:[ "bipbop-cenc-video-10s.mp4",
]
}
],
keys: {
"7e571d037e571d037e571d037e571d11" : "7e5733337e5733337e5733337e573311",
},
sessionType:"temporary",
sessionCount:1,
duration:10.01
},
];
function sleep(time) {
return new Promise((resolve) => setTimeout(resolve, time));
}
// To check if playback can be blocked and resumed correctly after
// detaching original mediakeys and reattach it back.
function startTest(test, token)
{
manager.started(token);
var mk_ori;
let finish = new EMEPromise;
let v = document.getElementById("v");
let sessions = [];
function onSessionCreated(session) {
sessions.push(session);
}
function closeSessions() {
let p = new EMEPromise;
Promise.all(sessions.map(s => s.close()))
.then(p.resolve, p.reject);
return p.promise;
}
function setMediaKeysToElement(mk, solve, reject) {
v.setMediaKeys(mk).then(solve, reject);
}
function ReattachOriMediaKeys() {
function onOriMediaKeysSetOK() {
ok(true, TimeStamp(token) + " (ENCRYPTED) Set original MediaKeys back OK!");
}
function onOriMediaKeysSetFailed() {
ok(false, " Failed to set original mediakeys back.");
}
function onCanPlayAgain(ev) {
Promise.all([closeSessions()])
.then(() => {
ok(true, " (ENCRYPTED) Playback can be resumed.");
manager.finished(token);
}, () => {
ok(false, TimeStamp(token) + " Sessions are closed incorrectly.");
manager.finished(token);
});
}
once(v, "canplay", onCanPlayAgain);
setMediaKeysToElement(mk_ori, onOriMediaKeysSetOK, onOriMediaKeysSetFailed)
}
function triggerSeek() {
v.currentTime = v.duration / 2;
}
function onCanPlay(ev) {
function onSetMediaKeysToNullOK() {
ok(true, TimeStamp(token) + " Set MediaKeys to null. OK!");
triggerSeek();
SimpleTest.requestFlakyTimeout("To reattach mediakeys back again in 5s.");
sleep(5000).then(ReattachOriMediaKeys);
}
function onSetMediaKeysToNullFailed() {
ok(false, TimeStamp(token) + " Set MediaKeys to null. FAILED!");
}
SimpleTest.requestFlakyTimeout("To detach mediakeys after receiving 'canplay' event in 2s");
sleep(2000).then(() => {
setMediaKeysToElement(null, onSetMediaKeysToNullOK, onSetMediaKeysToNullFailed);
});
}
once(v, "canplay", onCanPlay);
var p1 = LoadInitData(v, test, token);
var p2 = CreateAndSetMediaKeys(v, test, token);
var p3 = LoadTest(test, v, token);
Promise.all([p1, p2, p3])
.then(values => {
let initData = values[0];
// stash the mediakeys
mk_ori = v.mediaKeys;
initData.map(ev => {
let session = v.mediaKeys.createSession();
onSessionCreated(session);
MakeRequest(test, token, ev, session);
});
})
.then(() => {
return finish.promise;
})
.catch(reason => ok(false, reason))
}
function beginTest() {
manager.runTests(EMEmanifest, startTest);
}
SimpleTest.waitForExplicitFinish();
SetupEMEPref(beginTest);
</script>
</pre>
</body>
</html>

View File

@ -1,117 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test Encrypted Media Extensions</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script type="text/javascript" src="manifest.js"></script>
<script type="text/javascript" src="http://test1.mochi.test:8888/tests/dom/media/test/eme.js"></script>
</head>
<body>
<pre id="test">
<script class="testbody" type="text/javascript">
var manager = new MediaTestManager;
// Test that if we can capture a video frame while playing clear content after
// removing the MediaKeys object which was used for a previous encrypted content
// playback on the same video element
function startTest(test, token)
{
manager.started(token);
var sessions = [];
function onSessionCreated(session) {
sessions.push(session);
}
function closeSessions() {
let p = new EMEPromise;
Promise.all(sessions.map(s => s.close()))
.then(p.resolve, p.reject);
return p.promise;
}
let v = document.createElement("video");
document.body.appendChild(v);
let finish = new EMEPromise;
function onVideoEnded(ev) {
ok(true, TimeStamp(token) + " (ENCRYPTED) content playback ended.");
v.removeEventListener("ended", onVideoEnded);
function playClearVideo() {
var p1 = once(v, 'ended', (e) => {
ok(true, TimeStamp(token) + " (CLEAR) content playback ended.");
console.log(" bipbop.mp4 playback ended !!");
});
var p2 = once(v, 'loadeddata', (e) => {
ok(true, TimeStamp(token) + " Receiving event 'loadeddata' for (CLEAR) content.");
canvasElem = document.createElement('canvas');
document.body.appendChild(canvasElem);
ctx2d = canvasElem.getContext('2d');
var gotTypeError = false;
try {
ctx2d.drawImage(v, 0, 0);
} catch (e) {
if (e instanceof TypeError) {
gotTypeError = true;
}
}
ok(!gotTypeError, TimeStamp(token) + " Canvas2D context drawImage succeed.")
});
v.src = 'bipbop_225w_175kbps.mp4';
v.play();
Promise.all([p1, p2, closeSessions()]).then(() => {
manager.finished(token);
}, () => {
ok(false, TimeStamp(token) + " Something wrong.");
manager.finished(token);
});
}
Promise.all(sessions.map(s => s.close()))
.then(() => {
v.setMediaKeys(null)
.then(() => {
ok(true, TimeStamp(token) + " Setting MediaKeys to null.");
playClearVideo();
}, () => {
ok(false, TimeStamp(token) + " Setting MediaKeys to null.");
});;
});
}
v.addEventListener("ended", onVideoEnded);
// Create a MediaKeys object and set to HTMLMediaElement then start the playback.
Promise.all([
LoadInitData(v, test, token),
CreateAndSetMediaKeys(v, test, token),
LoadTest(test, v, token)])
.then(values => {
let initData = values[0];
v.play();
initData.map(ev => {
let session = v.mediaKeys.createSession();
onSessionCreated(session);
MakeRequest(test, token, ev, session);
});
})
.then(() => {
return finish.promise;
})
.catch(reason => ok(false, reason))
}
function beginTest() {
manager.runTests(gEMETests, startTest);
}
SimpleTest.waitForExplicitFinish();
SetupEMEPref(beginTest);
</script>
</pre>
</body>
</html>

View File

@ -28,14 +28,15 @@ public:
static already_AddRefed<SyncObjectHost> 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<SyncObjectClient> 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;

View File

@ -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<ID3D11DeviceContext> ctx;
@ -1799,6 +1809,8 @@ SyncObjectD3D11Client::Synchronize()
}
mSyncedTextures.clear();
return true;
}
uint32_t

View File

@ -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<ID3D11Device> mDevice;

View File

@ -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<ChunkPool> emptyChunks_;
// Chunks which have had some, but not all, of their arenas allocated live

View File

@ -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

View File

@ -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);

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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:

View File

@ -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') {

View File

@ -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<ValueObserver> 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<nsIObserver*>(observer),
/* isPriority */ true);
PREF_RegisterCallback(
aPref, NotifyObserver, static_cast<nsIObserver*>(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<ValueObserver> 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<uint32_t, Order>* aCache,
data->mCacheLocation = aCache;
data->mDefaultValueUint = aDefault;
CacheDataAppendElement(data);
RegisterPriorityCallback(AtomicUintVarChanged<Order>, aPref, data);
RegisterVarCacheCallback(AtomicUintVarChanged<Order>, 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;
}

View File

@ -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);

View File

@ -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:

View File

@ -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:

View File

@ -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': {

View File

@ -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'},
],
}

View File

@ -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

View File

@ -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",

View File

@ -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))