Bug 1395922 - [P1] Refactor code and move them into specific functions. r=cpearce

MozReview-Commit-ID: 9lwRH66Wllp

--HG--
extra : rebase_source : 8202008d996adb19547a46f051427053c1d48193
This commit is contained in:
Kilik Kuo 2017-11-03 14:35:32 +08:00
Родитель b954c1f10b
Коммит 87d6236019
2 изменённых файлов: 169 добавлений и 70 удалений

Просмотреть файл

@ -1485,6 +1485,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLMediaElement, nsGenericHTM
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAudioTrackList) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAudioTrackList)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVideoTrackList) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVideoTrackList)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaKeys) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaKeys)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIncomingMediaKeys)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSelectedVideoStreamTrack) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSelectedVideoStreamTrack)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPendingPlayPromises) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPendingPlayPromises)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSeekDOMPromise) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSeekDOMPromise)
@ -1514,6 +1515,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLMediaElement, nsGenericHTMLE
NS_IMPL_CYCLE_COLLECTION_UNLINK(mAudioTrackList) NS_IMPL_CYCLE_COLLECTION_UNLINK(mAudioTrackList)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mVideoTrackList) NS_IMPL_CYCLE_COLLECTION_UNLINK(mVideoTrackList)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mMediaKeys) NS_IMPL_CYCLE_COLLECTION_UNLINK(mMediaKeys)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mIncomingMediaKeys)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSelectedVideoStreamTrack) NS_IMPL_CYCLE_COLLECTION_UNLINK(mSelectedVideoStreamTrack)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPendingPlayPromises) NS_IMPL_CYCLE_COLLECTION_UNLINK(mPendingPlayPromises)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSeekDOMPromise) NS_IMPL_CYCLE_COLLECTION_UNLINK(mSeekDOMPromise)
@ -3985,6 +3987,7 @@ HTMLMediaElement::HTMLMediaElement(already_AddRefed<mozilla::dom::NodeInfo>& aNo
mPlaybackRate(1.0), mPlaybackRate(1.0),
mPreservesPitch(true), mPreservesPitch(true),
mPlayed(new TimeRanges(ToSupports(OwnerDoc()))), mPlayed(new TimeRanges(ToSupports(OwnerDoc()))),
mAttachingMediaKey(false),
mCurrentPlayRangeStart(-1.0), mCurrentPlayRangeStart(-1.0),
mLoadedDataFired(false), mLoadedDataFired(false),
mAutoplaying(true), mAutoplaying(true),
@ -7015,6 +7018,142 @@ HTMLMediaElement::ContainsRestrictedContent()
return GetMediaKeys() != nullptr; return GetMediaKeys() != nullptr;
} }
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(DetailedPromise* aPromise)
{
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) {
// 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.
aPromise->MaybeReject(
NS_ERROR_DOM_INVALID_STATE_ERR,
NS_LITERAL_CSTRING(
"Can't change MediaKeys on HTMLMediaElement after load has started"));
return false;
}
RemoveMediaKeys();
// 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.
return true;
}
bool
HTMLMediaElement::DetachExistingMediaKeys(DetailedPromise* aPromise)
{
LOG(LogLevel::Debug, ("%s", __func__));
// 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()) {
aPromise->MaybeReject(
NS_ERROR_DOM_QUOTA_EXCEEDED_ERR,
NS_LITERAL_CSTRING(
"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(aPromise);
}
return true;
}
void
HTMLMediaElement::MakeAssociationWithCDMResolved(DetailedPromise* aPromise)
{
LOG(LogLevel::Debug, ("%s", __func__));
// 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.
aPromise->MaybeResolveWithUndefined();
}
bool
HTMLMediaElement::TryMakeAssociationWithCDM(CDMProxy* aProxy)
{
MOZ_ASSERT(aProxy);
LOG(LogLevel::Debug, ("%s", __func__));
// 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(aProxy);
}
return true;
}
bool
HTMLMediaElement::AttachNewMediaKeys(DetailedPromise* aPromise)
{
LOG(LogLevel::Debug,
("%s incoming MediaKeys(%p)", __func__, mIncomingMediaKeys.get()));
// 5.3. If mediaKeys is not null, run the following steps:
if (mIncomingMediaKeys) {
auto cdmProxy = mIncomingMediaKeys->GetCDMProxy();
if (!cdmProxy) {
aPromise->MaybeReject(
NS_ERROR_DOM_INVALID_STATE_ERR,
NS_LITERAL_CSTRING(
"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.
ResetSetMediaKeysTempVariables();
// 5.3.2.3 Reject promise with a new DOMException whose name is
// the appropriate error name.
aPromise->MaybeReject(
NS_ERROR_DOM_INVALID_STATE_ERR,
NS_LITERAL_CSTRING(
"Failed to bind MediaKeys object to HTMLMediaElement"));
return false;
}
return TryMakeAssociationWithCDM(cdmProxy);
}
return true;
}
void
HTMLMediaElement::ResetSetMediaKeysTempVariables()
{
mAttachingMediaKey = false;
mIncomingMediaKeys = nullptr;
}
already_AddRefed<Promise> already_AddRefed<Promise>
HTMLMediaElement::SetMediaKeys(mozilla::dom::MediaKeys* aMediaKeys, HTMLMediaElement::SetMediaKeys(mozilla::dom::MediaKeys* aMediaKeys,
ErrorResult& aRv) ErrorResult& aRv)
@ -7050,85 +7189,34 @@ HTMLMediaElement::SetMediaKeys(mozilla::dom::MediaKeys* aMediaKeys,
// 2. If this object's attaching media keys value is true, return a // 2. If this object's attaching media keys value is true, return a
// promise rejected with a new DOMException whose name is InvalidStateError. // promise rejected with a new DOMException whose name is InvalidStateError.
// 3. Let this object's attaching media keys value be true. if (mAttachingMediaKey) {
// 4. Let promise be a new promise. promise->MaybeReject(
// 5. Run the following steps in parallel: NS_ERROR_DOM_INVALID_STATE_ERR,
NS_LITERAL_CSTRING("A MediaKeys object is in attaching operation."));
// 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(); return promise.forget();
} }
// 5.2 If the mediaKeys attribute is not null, run the following steps: // 3. Let this object's attaching media keys value be true.
if (mMediaKeys) { mAttachingMediaKey = true;
// 5.2.1 If the user agent or CDM do not support removing the association, mIncomingMediaKeys = aMediaKeys;
// 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 // 4. Let promise be a new promise.
// attaching media keys value be false and reject promise with a new // 5. Run the following steps in parallel:
// 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 // 5.1 & 5.2
// to decrypt media data and remove the association with the media element. if (!DetachExistingMediaKeys(promise)) {
mMediaKeys->Unbind(); ResetSetMediaKeysTempVariables();
mMediaKeys = nullptr; return promise.forget();
// 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: // 5.3
if (aMediaKeys) { if (!AttachNewMediaKeys(promise)) {
if (!aMediaKeys->GetCDMProxy()) { ResetSetMediaKeysTempVariables();
promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR, return promise.forget();
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. // 5.4, 5.5, 5.6
mMediaKeys = aMediaKeys; MakeAssociationWithCDMResolved(promise);
// 5.5 Let this object's attaching media keys value be false.
// 5.6 Resolve promise.
promise->MaybeResolveWithUndefined();
// 6. Return promise. // 6. Return promise.
return promise.forget(); return promise.forget();

Просмотреть файл

@ -1332,6 +1332,14 @@ protected:
const nsAttrValueOrString& aValue, const nsAttrValueOrString& aValue,
bool aNotify) override; bool aNotify) override;
bool DetachExistingMediaKeys(DetailedPromise* aPromise);
bool TryRemoveMediaKeysAssociation(DetailedPromise* aPromise);
void RemoveMediaKeys();
bool AttachNewMediaKeys(DetailedPromise* aPromise);
bool TryMakeAssociationWithCDM(CDMProxy* aProxy);
void MakeAssociationWithCDMResolved(DetailedPromise* aPromise);
void ResetSetMediaKeysTempVariables();
// The current decoder. Load() has been called on this decoder. // The current decoder. Load() has been called on this decoder.
// At most one of mDecoder and mSrcStream can be non-null. // At most one of mDecoder and mSrcStream can be non-null.
RefPtr<MediaDecoder> mDecoder; RefPtr<MediaDecoder> mDecoder;
@ -1534,6 +1542,9 @@ protected:
// Encrypted Media Extension media keys. // Encrypted Media Extension media keys.
RefPtr<MediaKeys> mMediaKeys; RefPtr<MediaKeys> mMediaKeys;
RefPtr<MediaKeys> mIncomingMediaKeys;
// Used to indicate if the MediaKeys attaching operation is on-going or not.
bool mAttachingMediaKey;
// Stores the time at the start of the current 'played' range. // Stores the time at the start of the current 'played' range.
double mCurrentPlayRangeStart; double mCurrentPlayRangeStart;