@xhw...@chromium.org, sorry for too many files but this change is mostly about plumbing to pass the enum value for the failure reason on CreateCdm.
@fra...@microsoft.com, sorry for the delay of this work. This will give us better debuggability when CreateCdm failed.
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
+tmathmeyer for review as well, who's our expert on error status reporting in media/.
CC jrummell FYI.
media::CreateCdmFailureReason::kCrOsMultipleInstancesNotAllowed;nit: Shall we try to match the ChromeOS CdmFactory::CreateCdmStatus naming?
CreateCdmFailureReason failure_reason)>;+tmathmeyer: Do you think this API can benefit from media::TypedStatus? The line number information might be very helpful in debugging.
kFuchsiaCdmeClosed, // Fuchsia: CDM closed prior to beingtypo?
kCrOsVerifiedAccessDisabled, // CrOs: Verified Access is disabled.
kCrOsRemoteFactoryCreationFailed, // CrOs: Remote factory creation failed.
kAndroidCdmCreationAborted, // Android: CDM creation aborted.
kFuchsiaCdmeClosed, // Fuchsia: CDM closed prior to beingReading this list, I am debating between how granularized this list should be. For example:
The concern is that if we do that then we are more likely needing to expand this list overtime with new code added, which will be more maintenance cost, and the marginal benefit is getting lower.
With that, does it make sense to group errors into logical enums? e.g.
If we find that one UMA is reported heavily and we want to know more, we can always expand the list at that time. WDYT?
kInvalidKeySystem, // Invalid key system.This is only reported twice, one after NOTREACHED_IN_MIGRATION and one in test code. So it might not worth having an entry. Can we just use kUnsupportedKeySystem?
enum class CreateCdmFailureReason {Can we move this list to cdm_factory.h since it's related to CDM creation?
enum class CreateCdmFailureReason {optional nit: It's slightly hard to read when kSuccess is also a failure reason. It could be CreateCdmStatus. But this is optional.
// Reasons for CDM creation failure.Add a comment that these are reported to UMA so values should not be reused or deleted etc. You can find examples in the code base.
Can we DCHECK that if we have a CDM the reason is not success?
media::CreateCdmFailureReason::kEmeUseNotAllowedOnUniqueOrigins);The name is a bit long and hard to read. How about kNotAllowedOnUniqueOrigin?
Media.EME.MediaFoundationCdm.Widevine.HardwareSecure.Initialize."/>Enums should not be specific to any particular key system...
The failure reason when the CDM instance is not created successfully for
{KeySystem}. Reported each time a CDM instance creation is attempted,This is confusing since we also report kSuccess when a CDM is created successfully.
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
Added some thoughts on using MediaStatus. It seems like it is probably a good fit, but I don't quite remember what the situation with moving these across mojo is anymore. It might be already totally hooked up and just require importing media_types.mojom, but it might require some copying of what I did here: https://chromium-review.googlesource.com/c/chromium/src/+/3132055
failure_reason =
media::CreateCdmFailureReason::kCrOsMultipleInstancesNotAllowed;just call the callback here and return, rather than assigning to a temp variable.
failure_reason =
media::CreateCdmFailureReason::kCrOsInsufficientGpuMemoryAvailable;
break;ditto
LOG_IF(ERROR, !cdm) << static_cast<int>(failure_reason);If you go with typed status, you can dump information about it using
```
::media::MediaSerialize(status);
```
CreateCdmFailureReason failure_reason)>;+tmathmeyer: Do you think this API can benefit from media::TypedStatus? The line number information might be very helpful in debugging.
yes, definitely. It also makes the callback easier to use IMO. If CreateCdmFailureReason became something like
```
CdmStatus = TypedStatus<CdmStatusTraits...>;
```
you could define this callback to be
```
using CdmCreateCb = base::OnceCallback<void(CdmStatus::Or<scoped_refptr<ContentDecryptionModule>>);
```
which means you can just call it with either the error code or the pointer, but you don't have to provide success code for successful results, or a nullptr for error results.
enum class CreateCdmFailureReason {optional nit: It's slightly hard to read when kSuccess is also a failure reason. It could be CreateCdmStatus. But this is optional.
If you chose to go with the typed status method, you'd declare this as:
```
struct CdmStatusTraits {
enum Codes {
kLoadCdmFailed, // Failed to load the CDM.
kCreateCdmFuncNotAvailable, // CreateCdmFunc not available.
...
};
static constexpr StatusGroupType Group() { return "CdmStatus"; }
};
using CdmStatus = TypedStatus<CdmStatusTraits>;
```
And then access the codes like:
```
if (is_ok) {
std::move(cdm_created_cb_).Run(cdm_ptr);
} else {
std::move(cdm_created_cb_).Run(CdmStatus::Codes::kLoadCdmFailed);
}
```
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
@xhw...@chromium.org, @tmath...@chromium.org thanks for the suggestion of using media status but I'd like to try it if we think we need it after seeing the new UMA data. All other code review feedback got addressed. PTAL
failure_reason =
media::CreateCdmFailureReason::kCrOsMultipleInstancesNotAllowed;just call the callback here and return, rather than assigning to a temp variable.
Done
media::CreateCdmFailureReason::kCrOsMultipleInstancesNotAllowed;nit: Shall we try to match the ChromeOS CdmFactory::CreateCdmStatus naming?
Done
failure_reason =
media::CreateCdmFailureReason::kCrOsInsufficientGpuMemoryAvailable;
break;Sangbaek Parkditto
Done
LOG_IF(ERROR, !cdm) << static_cast<int>(failure_reason);If you go with typed status, you can dump information about it using
```
::media::MediaSerialize(status);
```
Thanks for the suggestion! I see some benefits including line number etc but I'd try this in the future once we see we can't narrow down the top error reasons.
CreateCdmFailureReason failure_reason)>;Ted (Chromium) Meyer+tmathmeyer: Do you think this API can benefit from media::TypedStatus? The line number information might be very helpful in debugging.
yes, definitely. It also makes the callback easier to use IMO. If CreateCdmFailureReason became something like
```
CdmStatus = TypedStatus<CdmStatusTraits...>;
```
you could define this callback to be
```
using CdmCreateCb = base::OnceCallback<void(CdmStatus::Or<scoped_refptr<ContentDecryptionModule>>);
```which means you can just call it with either the error code or the pointer, but you don't have to provide success code for successful results, or a nullptr for error results.
Thanks, I'd try this in the future once we see we can't narrow down the top error reasons.
kCrOsVerifiedAccessDisabled, // CrOs: Verified Access is disabled.
kCrOsRemoteFactoryCreationFailed, // CrOs: Remote factory creation failed.
kAndroidCdmCreationAborted, // Android: CDM creation aborted.
kFuchsiaCdmeClosed, // Fuchsia: CDM closed prior to beingReading this list, I am debating between how granularized this list should be. For example:
- Do we want each failure point to report a different enum? (In other words, do we expect to be able to find the exact failure point when we see an enum reported?
- Do we need to report different enums for the same type of error on different platforms (e.g. Android vs Fuchsia)?
The concern is that if we do that then we are more likely needing to expand this list overtime with new code added, which will be more maintenance cost, and the marginal benefit is getting lower.
With that, does it make sense to group errors into logical enums? e.g.
- kDisconnectionError and kMojoCallDropped
- kInitCdmFailed and kMediaFoundationInitCdmFailed
- kAndroidCdmCreationAborted and kMediaDrmBridgeCreationAborted, and maybe kFuchsiaCdmeClosed
- kCdmFactoryCreationFailed and kUnableToFindCdmFactory
- ...
If we find that one UMA is reported heavily and we want to know more, we can always expand the list at that time. WDYT?
I initially started smaller # of entries but ended up adding more due to other platforms' cases so I was debating the same concern. Consolidating / flattening sounds reasonable.
kFuchsiaCdmeClosed, // Fuchsia: CDM closed prior to beingSangbaek Parktypo?
Done
This is only reported twice, one after NOTREACHED_IN_MIGRATION and one in test code. So it might not worth having an entry. Can we just use kUnsupportedKeySystem?
Done
enum class CreateCdmFailureReason {Ted (Chromium) Meyeroptional nit: It's slightly hard to read when kSuccess is also a failure reason. It could be CreateCdmStatus. But this is optional.
If you chose to go with the typed status method, you'd declare this as:
```
struct CdmStatusTraits {
enum Codes {
kLoadCdmFailed, // Failed to load the CDM.
kCreateCdmFuncNotAvailable, // CreateCdmFunc not available.
...
};
static constexpr StatusGroupType Group() { return "CdmStatus"; }
};
using CdmStatus = TypedStatus<CdmStatusTraits>;
```And then access the codes like:
```
if (is_ok) {
std::move(cdm_created_cb_).Run(cdm_ptr);
} else {
std::move(cdm_created_cb_).Run(CdmStatus::Codes::kLoadCdmFailed);
}
```
optional nit: It's slightly hard to read when kSuccess is also a failure reason. It could be CreateCdmStatus. But this is optional.
Renamed to `CreateCdmStatus`.
If you chose to go with the typed status method, you'd declare this as:
I'd try this in the future once we see we can't narrow down the top error reasons.
Can we move this list to cdm_factory.h since it's related to CDM creation?
Moved to `cdm_factory.h`
Add a comment that these are reported to UMA so values should not be reused or deleted etc. You can find examples in the code base.
Added
```
// These are reported to UMA server. Do not renumber or reuse values.
```
Can we DCHECK that if we have a CDM the reason is not success?
Tried to add DCHECK here and realized some tests are expecting failures so I can't add DCHECK here.
media::CreateCdmFailureReason::kEmeUseNotAllowedOnUniqueOrigins);The name is a bit long and hard to read. How about kNotAllowedOnUniqueOrigin?
Done
Media.EME.MediaFoundationCdm.Widevine.HardwareSecure.Initialize."/>Enums should not be specific to any particular key system...
Generalized / consolidated `kMediaFoundationInitCdmFailed` into `kInitCdmFailed`.
The failure reason when the CDM instance is not created successfully for
{KeySystem}. Reported each time a CDM instance creation is attempted,This is confusing since we also report kSuccess when a CDM is created successfully.
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
lg with a few more comments. Using media::Status in a follow-up CL is fine.
kUnknownError, // Unknown error.This is a generic one; move this to be after kSuccess?
kCdmCreationAborted, // CDM creation aborted.Move this up so it's before the platform specific ones?
kMojoCdmServiceCreationAborted, // Mojo CDM Service creation aborted.drop this and use `kDisconnectionError`.
FWIW, if a callback doesn't run (WrapCallbackWithDefaultInvokeIfNotRun() ) it's mostly a disconnection error.
// callback (e.g. in case of crash, or CDM
// loading/initialization failure).CDM loading or init failure are covered by other enums?
kMojoCdmNotSupported, // Mojo CDM not supported.This is only used once and it's mostly a code issues instead of a runtime error. Maybe drop and just use kCdmNotSupported?
// state. MediaDrmBridge requires hardware-secure codecs.nit: format
kCdmFactoryCreationFailed, // CDM Factory creation failed.Can we merge this and kUnableToFindCdmFactory? Seems the cause is similar and it's hard to reason about when to use one vs the other.
std::move(ready_cb_).Run(false, CreateCdmStatus::kCdmCreationAborted);Should this be kConnectionError?
CreateCdmStatus failure_reason) {here and throughout the CL, s/failure_reason/status
#include "media/base/cdm_factory.h"nit: This is not necessary as the header file already includes this file.
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
Thanks for the quick review! I'll consider using media::Status in a follow-up CL.
LOG_IF(ERROR, !cdm) << static_cast<int>(failure_reason);Sangbaek ParkIf you go with typed status, you can dump information about it using
```
::media::MediaSerialize(status);
```
Thanks for the suggestion! I see some benefits including line number etc but I'd try this in the future once we see we can't narrow down the top error reasons.
I'll consider this in the future CL.
This is a generic one; move this to be after kSuccess?
Done
Move this up so it's before the platform specific ones?
Done
kMojoCdmServiceCreationAborted, // Mojo CDM Service creation aborted.drop this and use `kDisconnectionError`.
FWIW, if a callback doesn't run (WrapCallbackWithDefaultInvokeIfNotRun() ) it's mostly a disconnection error.
Done
// callback (e.g. in case of crash, or CDM
// loading/initialization failure).CDM loading or init failure are covered by other enums?
Removed since it will be covered by other enums. Carried over from the previous comment.
This is only used once and it's mostly a code issues instead of a runtime error. Maybe drop and just use kCdmNotSupported?
Done
// state. MediaDrmBridge requires hardware-secure codecs.Sangbaek Parknit: format
Fixed. My clang format in VSCode somehow is very slow or doesn't work sometime.
kCdmFactoryCreationFailed, // CDM Factory creation failed.Can we merge this and kUnableToFindCdmFactory? Seems the cause is similar and it's hard to reason about when to use one vs the other.
Merged `kUnableToFindCdmFactory` into `kCdmFactoryCreationFailed`
CreateCdmFailureReason failure_reason)>;Ted (Chromium) Meyer+tmathmeyer: Do you think this API can benefit from media::TypedStatus? The line number information might be very helpful in debugging.
Sangbaek Parkyes, definitely. It also makes the callback easier to use IMO. If CreateCdmFailureReason became something like
```
CdmStatus = TypedStatus<CdmStatusTraits...>;
```
you could define this callback to be
```
using CdmCreateCb = base::OnceCallback<void(CdmStatus::Or<scoped_refptr<ContentDecryptionModule>>);
```which means you can just call it with either the error code or the pointer, but you don't have to provide success code for successful results, or a nullptr for error results.
Thanks, I'd try this in the future once we see we can't narrow down the top error reasons.
I'll consider this in the future CL.
enum class CreateCdmFailureReason {Ted (Chromium) Meyeroptional nit: It's slightly hard to read when kSuccess is also a failure reason. It could be CreateCdmStatus. But this is optional.
Sangbaek ParkIf you chose to go with the typed status method, you'd declare this as:
```
struct CdmStatusTraits {
enum Codes {
kLoadCdmFailed, // Failed to load the CDM.
kCreateCdmFuncNotAvailable, // CreateCdmFunc not available.
...
};
static constexpr StatusGroupType Group() { return "CdmStatus"; }
};
using CdmStatus = TypedStatus<CdmStatusTraits>;
```And then access the codes like:
```
if (is_ok) {
std::move(cdm_created_cb_).Run(cdm_ptr);
} else {
std::move(cdm_created_cb_).Run(CdmStatus::Codes::kLoadCdmFailed);
}
```
optional nit: It's slightly hard to read when kSuccess is also a failure reason. It could be CreateCdmStatus. But this is optional.
Renamed to `CreateCdmStatus`.
If you chose to go with the typed status method, you'd declare this as:
I'd try this in the future once we see we can't narrow down the top error reasons.
I'll consider this in the future CL.
std::move(ready_cb_).Run(false, CreateCdmStatus::kCdmCreationAborted);Sangbaek ParkShould this be kConnectionError?
Changed to `kConnectionError` and added example `e.g. in case of crash or aborted operation.`
here and throughout the CL, s/failure_reason/status
Done
nit: This is not necessary as the header file already includes this file.
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Code-Review | +1 |
lgtm % nits
CreateCdmStatus createcdm_status)>;create_cdm_status?
Actually, just "status" is probably cleaner without ambiguity...
// callback. e.g. in case of crash or aborted operation.Noticed that you removed kCdmCreationAborted. Crash and abortion are actually different, the latter happens during normal destruction without crash...
// callback. e.g. in case of crash or aborted operation.alignment
// MediaDrmBridge requires hardware-secure codecs.This is inaccurate. MediaDrmBridge supports L3...
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
create_cdm_status?
Actually, just "status" is probably cleaner without ambiguity...
Renamed to `status`
// callback. e.g. in case of crash or aborted operation.Sangbaek Parkalignment
PRESUBMIT warns me + cl format rolls back my correction. I'll leave as is for now.
// callback. e.g. in case of crash or aborted operation.Noticed that you removed kCdmCreationAborted. Crash and abortion are actually different, the latter happens during normal destruction without crash...
Revived `kCdmCreationAborted`. You mentioned to use `kConnectionError` instead of `kCdmCreationAborted` for Fuchisa aborted case but confused you wanted to use `kDisconnectionError`. Keeping `kCdmCreationAborted` sounds more reasonable since the abortion operation can happen during normal destruction.
This is inaccurate. MediaDrmBridge supports L3...
Removed. It was a bit confusing since this was for the specific case as below:
```
} else if (!cdm_config.use_hw_secure_codecs) {
// Assume other key systems require hardware-secure codecs and thus do not
// support full compositing.
auto error_message =
cdm_config.key_system +
" may require use_video_overlay_for_embedded_encrypted_video";
NOTREACHED_IN_MIGRATION() << error_message;
```
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
@chrome-ip...@google.com for Mojo review.
@ev...@google.com for media UMA.
@kma...@chromium.org for chromecast.
@dalec...@chromium.org for webcodecs.
PTAL, thanks!
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
From googleclient/chrome/chromium_gwsq/ipc/config.gwsq:
IPC: book...@chromium.org
📎 It looks like you’re making a possibly security-sensitive change! 📎 IPC security review isn’t a rubberstamp, so your friendly security reviewer will need a fair amount of context to review your CL effectively. Please review your CL description and code comments to make sure they provide context for someone unfamiliar with your project/area. Pay special attention to where data comes from and which processes it flows between (and their privilege levels). Feel free to point your security reviewer at design docs, bugs, or other links if you can’t reasonably make a self-contained CL description. (Also see https://cbea.ms/git-commit/).
IPC reviewer(s): book...@chromium.org
Reviewer source(s):
book...@chromium.org is from context(googleclient/chrome/chromium_gwsq/ipc/config.gwsq)
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Code-Review | +1 |
| Code-Review | +1 |
| Code-Review | +1 |
// Callback used when CDM is created. |status| only used if
// ContentDecryptionModule is null (i.e. CDM can't be created).This is a bit confusing as we do return kSuccess when the CDM is non-null.
// Callback used when CDM is created. |status| only used if
// ContentDecryptionModule is null (i.e. CDM can't be created).This is a bit confusing as we do return kSuccess when the CDM is non-null.
Rephrased to
```
|status| tells the detailed reason why CDM can't be created if ContentDecryptionModule is null.
```
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Code-Review | +1 |
| Commit-Queue | +2 |
media: Report failure reason when creating CDM failed
Used to report a boolean value for the result of creating a CDM
instance. The existing UMA for CreateCdm:
`Media.EME.{KeySystem}.{Robustness}.CreateCdm`
This limited information (only success or failure without a reason)
has been discouraging developers to investigate the root cause and
improve the user experience.
Now this change improves the debuggability by providing the detailed
failure reason when failed to create a CDM instance:
`Media.EME.{KeySystem}.{Robustness}.CreateCdmStatus`
Other chromium-based browsers can receive the debugging benefits with
different key systems.
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |