зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to mozilla-autoland. r=merge a=merge on a CLOSED TREE
This commit is contained in:
Коммит
f51f922391
|
@ -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}"
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -121,7 +121,6 @@ EXPORTS += [
|
|||
'MediaMetadataManager.h',
|
||||
'MediaMIMETypes.h',
|
||||
'MediaPrefs.h',
|
||||
'MediaPromiseDefs.h',
|
||||
'MediaQueue.h',
|
||||
'MediaRecorder.h',
|
||||
'MediaResource.h',
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
Cache-Control: no-store
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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>
|
|
@ -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>
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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') {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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': {
|
||||
|
|
|
@ -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'},
|
||||
|
||||
],
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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))
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче