Commit a98a8fa4 authored by Xiaohan Wang's avatar Xiaohan Wang Committed by Commit Bot

media: Trigger Infobar on Mac ARM on EME query failure

CDM on Mac ARM is not ready yet. When requestMediaKeySystemAccess()
fails on Mac ARM, we reject the promise with "Unsupported platform" and
trigger an infobar to notify user. The infobar will be triggered at most
once per render process.

Since the infobar can only be triggered in the browser process, a new
mojo service CdmInfobarService is added. Note that even though there
already exists KeySystemSupport service, which is also implemented in
the browser process, we cannot trigger the infobar there, because the
infobar requires a WebContents context, while the KeySystemSupport
service is bound to a render process instead of a render frame.

Change-Id: Ia85a1f2b097b0c2d26d12cc3e9363c34a25691a3
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2404716Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarElly Fong-Jones <ellyjones@chromium.org>
Reviewed-by: default avatarJohn Rummell <jrummell@chromium.org>
Commit-Queue: Xiaohan Wang <xhwang@chromium.org>
Cr-Commit-Position: refs/heads/master@{#807631}
parent 8c2b401e
...@@ -208,6 +208,14 @@ ...@@ -208,6 +208,14 @@
#include "extensions/common/api/mime_handler.mojom.h" // nogncheck #include "extensions/common/api/mime_handler.mojom.h" // nogncheck
#endif #endif
#if defined(OS_MAC) && defined(ARCH_CPU_ARM_FAMILY)
#include "chrome/browser/infobars/infobar_service.h"
#include "chrome/browser/ui/startup/mac_system_infobar_delegate.h"
#include "content/public/browser/frame_service_base.h"
#include "media/mojo/mojom/cdm_infobar_service.mojom.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#endif
namespace chrome { namespace chrome {
namespace internal { namespace internal {
...@@ -418,6 +426,39 @@ void BindCaptionContextHandler( ...@@ -418,6 +426,39 @@ void BindCaptionContextHandler(
} }
#endif #endif
#if defined(OS_MAC) && defined(ARCH_CPU_ARM_FAMILY)
class CdmInfobarServiceImpl final
: public content::FrameServiceBase<media::mojom::CdmInfobarService> {
public:
CdmInfobarServiceImpl(
content::RenderFrameHost* frame_host,
mojo::PendingReceiver<media::mojom::CdmInfobarService> receiver)
: FrameServiceBase(frame_host, std::move(receiver)) {}
CdmInfobarServiceImpl(const CdmInfobarServiceImpl&) = delete;
CdmInfobarServiceImpl& operator=(const CdmInfobarServiceImpl&) = delete;
private:
void NotifyUnsupportedPlatform() final {
auto* web_contents =
content::WebContents::FromRenderFrameHost(render_frame_host());
if (!web_contents)
return;
MacSystemInfoBarDelegate::Create(
InfoBarService::FromWebContents(web_contents));
}
};
void BindCdmInfobarServiceReceiver(
content::RenderFrameHost* frame_host,
mojo::PendingReceiver<media::mojom::CdmInfobarService> receiver) {
// CdmInfobarServiceImpl owns itself. It will self-destruct when a mojo
// interface error occurs, the render frame host is deleted, or the render
// frame host navigates to a new document.
new CdmInfobarServiceImpl(frame_host, std::move(receiver));
}
#endif
void PopulateChromeFrameBinders( void PopulateChromeFrameBinders(
mojo::BinderMapWithContext<content::RenderFrameHost*>* map) { mojo::BinderMapWithContext<content::RenderFrameHost*>* map) {
map->Add<image_annotation::mojom::Annotator>( map->Add<image_annotation::mojom::Annotator>(
...@@ -517,6 +558,11 @@ void PopulateChromeFrameBinders( ...@@ -517,6 +558,11 @@ void PopulateChromeFrameBinders(
map->Add<chrome::mojom::CaptionHost>( map->Add<chrome::mojom::CaptionHost>(
base::BindRepeating(&BindCaptionContextHandler)); base::BindRepeating(&BindCaptionContextHandler));
#endif #endif
#if defined(OS_MAC) && defined(ARCH_CPU_ARM_FAMILY)
map->Add<media::mojom::CdmInfobarService>(
base::BindRepeating(&BindCdmInfobarServiceReceiver));
#endif
} }
void PopulateChromeWebUIFrameBinders( void PopulateChromeWebUIFrameBinders(
......
...@@ -56,15 +56,28 @@ const char kVideoMP4MimeType[] = "video/mp4"; ...@@ -56,15 +56,28 @@ const char kVideoMP4MimeType[] = "video/mp4";
// These are the expected titles set by checkKeySystemWithMediaMimeType() // These are the expected titles set by checkKeySystemWithMediaMimeType()
// in test_key_system_instantiation.html. Other titles are possible, but // in test_key_system_instantiation.html. Other titles are possible, but
// they are unexpected and will be logged with the failure. kUnsupportedResult // they are unexpected and will be logged with the failure. kUnsupportedResult
// is the actual message generated by navigator.requestMediaKeySystemAccess(), // and kUnsupportedPlatformResult are the actual messages generated by
// and will need to be updated if that code is modified. // navigator.requestMediaKeySystemAccess(), and will need to be updated if that
// code is modified.
const char kSuccessResult[] = "success"; const char kSuccessResult[] = "success";
const char kUnsupportedResult[] = const char kUnsupportedResult[] =
"Unsupported keySystem or supportedConfigurations."; "Unsupported keySystem or supportedConfigurations.";
const char kUnsupportedPlatformResult[] = "Unsupported platform.";
const char kUnexpectedResult[] = "unexpected result"; const char kUnexpectedResult[] = "unexpected result";
#define EXPECT_SUCCESS(test) EXPECT_EQ(kSuccessResult, test) #define EXPECT_SUCCESS(test) EXPECT_EQ(kSuccessResult, test)
// TODO(crbug.com/1111381): Remove this when MacOS ARM64 CDM is checked in.
#if defined(OS_MAC) && defined(ARCH_CPU_ARM_FAMILY)
#define EXPECT_UNSUPPORTED(test) \
do { \
auto result = test; \
EXPECT_TRUE(result == kUnsupportedResult || \
result == kUnsupportedPlatformResult); \
} while (0)
#else
#define EXPECT_UNSUPPORTED(test) EXPECT_EQ(kUnsupportedResult, test) #define EXPECT_UNSUPPORTED(test) EXPECT_EQ(kUnsupportedResult, test)
#endif
// Any support is acceptable. This can be used around new CDM check-in time // Any support is acceptable. This can be used around new CDM check-in time
// where test expectations can change based on the new CDM's capability. // where test expectations can change based on the new CDM's capability.
...@@ -274,6 +287,8 @@ class EncryptedMediaSupportedTypesTest : public InProcessBrowserTest { ...@@ -274,6 +287,8 @@ class EncryptedMediaSupportedTypesTest : public InProcessBrowserTest {
content::TitleWatcher title_watcher(contents, content::TitleWatcher title_watcher(contents,
base::ASCIIToUTF16(kSuccessResult)); base::ASCIIToUTF16(kSuccessResult));
title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16(kUnsupportedResult)); title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16(kUnsupportedResult));
title_watcher.AlsoWaitForTitle(
base::ASCIIToUTF16(kUnsupportedPlatformResult));
title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16(kUnexpectedResult)); title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16(kUnexpectedResult));
EXPECT_TRUE(content::ExecuteScript(contents, command)); EXPECT_TRUE(content::ExecuteScript(contents, command));
base::string16 result = title_watcher.WaitAndGetTitle(); base::string16 result = title_watcher.WaitAndGetTitle();
......
...@@ -115,6 +115,10 @@ bool MediaPermissionDispatcher::IsEncryptedMediaEnabled() { ...@@ -115,6 +115,10 @@ bool MediaPermissionDispatcher::IsEncryptedMediaEnabled() {
return render_frame_->GetRendererPreferences().enable_encrypted_media; return render_frame_->GetRendererPreferences().enable_encrypted_media;
} }
void MediaPermissionDispatcher::NotifyUnsupportedPlatform() {
GetCdmInfobarService()->NotifyUnsupportedPlatform();
}
uint32_t MediaPermissionDispatcher::RegisterCallback( uint32_t MediaPermissionDispatcher::RegisterCallback(
PermissionStatusCB permission_status_cb) { PermissionStatusCB permission_status_cb) {
DCHECK(task_runner_->RunsTasksInCurrentSequence()); DCHECK(task_runner_->RunsTasksInCurrentSequence());
...@@ -138,6 +142,16 @@ MediaPermissionDispatcher::GetPermissionService() { ...@@ -138,6 +142,16 @@ MediaPermissionDispatcher::GetPermissionService() {
return permission_service_.get(); return permission_service_.get();
} }
media::mojom::CdmInfobarService*
MediaPermissionDispatcher::GetCdmInfobarService() {
if (!cdm_infobar_service_) {
render_frame_->GetBrowserInterfaceBroker()->GetInterface(
cdm_infobar_service_.BindNewPipeAndPassReceiver());
}
return cdm_infobar_service_.get();
}
void MediaPermissionDispatcher::OnPermissionStatus( void MediaPermissionDispatcher::OnPermissionStatus(
uint32_t request_id, uint32_t request_id,
blink::mojom::PermissionStatus status) { blink::mojom::PermissionStatus status) {
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "content/common/content_export.h" #include "content/common/content_export.h"
#include "content/renderer/render_frame_impl.h" #include "content/renderer/render_frame_impl.h"
#include "media/base/media_permission.h" #include "media/base/media_permission.h"
#include "media/mojo/mojom/cdm_infobar_service.mojom.h"
#include "mojo/public/cpp/bindings/remote.h" #include "mojo/public/cpp/bindings/remote.h"
#include "third_party/blink/public/mojom/permissions/permission.mojom.h" #include "third_party/blink/public/mojom/permissions/permission.mojom.h"
...@@ -42,6 +43,7 @@ class CONTENT_EXPORT MediaPermissionDispatcher : public media::MediaPermission { ...@@ -42,6 +43,7 @@ class CONTENT_EXPORT MediaPermissionDispatcher : public media::MediaPermission {
void RequestPermission(Type type, void RequestPermission(Type type,
PermissionStatusCB permission_status_cb) override; PermissionStatusCB permission_status_cb) override;
bool IsEncryptedMediaEnabled() override; bool IsEncryptedMediaEnabled() override;
void NotifyUnsupportedPlatform() override;
private: private:
// Map of request IDs and pending PermissionStatusCBs. // Map of request IDs and pending PermissionStatusCBs.
...@@ -54,6 +56,9 @@ class CONTENT_EXPORT MediaPermissionDispatcher : public media::MediaPermission { ...@@ -54,6 +56,9 @@ class CONTENT_EXPORT MediaPermissionDispatcher : public media::MediaPermission {
// Ensure there is a connection to the permission service and return it. // Ensure there is a connection to the permission service and return it.
blink::mojom::PermissionService* GetPermissionService(); blink::mojom::PermissionService* GetPermissionService();
// Ensure there is a connection to the CdmInfobarService and return it.
media::mojom::CdmInfobarService* GetCdmInfobarService();
// Callback for |permission_service_| calls. // Callback for |permission_service_| calls.
void OnPermissionStatus(uint32_t request_id, void OnPermissionStatus(uint32_t request_id,
blink::mojom::PermissionStatus status); blink::mojom::PermissionStatus status);
...@@ -66,6 +71,8 @@ class CONTENT_EXPORT MediaPermissionDispatcher : public media::MediaPermission { ...@@ -66,6 +71,8 @@ class CONTENT_EXPORT MediaPermissionDispatcher : public media::MediaPermission {
RequestMap requests_; RequestMap requests_;
mojo::Remote<blink::mojom::PermissionService> permission_service_; mojo::Remote<blink::mojom::PermissionService> permission_service_;
mojo::Remote<media::mojom::CdmInfobarService> cdm_infobar_service_;
// The |RenderFrameImpl| that owns this MediaPermissionDispatcher. It's okay // The |RenderFrameImpl| that owns this MediaPermissionDispatcher. It's okay
// to hold a raw pointer here because the lifetime of this object is bounded // to hold a raw pointer here because the lifetime of this object is bounded
// by the render frame's life (the latter holds a unique pointer to this). // by the render frame's life (the latter holds a unique pointer to this).
......
...@@ -10,4 +10,6 @@ MediaPermission::MediaPermission() = default; ...@@ -10,4 +10,6 @@ MediaPermission::MediaPermission() = default;
MediaPermission::~MediaPermission() = default; MediaPermission::~MediaPermission() = default;
void MediaPermission::NotifyUnsupportedPlatform() {}
} // namespace media } // namespace media
...@@ -41,6 +41,8 @@ class MEDIA_EXPORT MediaPermission { ...@@ -41,6 +41,8 @@ class MEDIA_EXPORT MediaPermission {
// the spec. // the spec.
virtual bool IsEncryptedMediaEnabled() = 0; virtual bool IsEncryptedMediaEnabled() = 0;
virtual void NotifyUnsupportedPlatform();
private: private:
DISALLOW_COPY_AND_ASSIGN(MediaPermission); DISALLOW_COPY_AND_ASSIGN(MediaPermission);
}; };
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "base/metrics/histogram_macros.h" #include "base/metrics/histogram_macros.h"
#include "base/strings/string_util.h" #include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "media/base/cdm_config.h" #include "media/base/cdm_config.h"
#include "media/base/key_system_names.h" #include "media/base/key_system_names.h"
#include "media/base/key_systems.h" #include "media/base/key_systems.h"
...@@ -909,7 +910,18 @@ void KeySystemConfigSelector::SelectConfig( ...@@ -909,7 +910,18 @@ void KeySystemConfigSelector::SelectConfig(
std::string key_system_ascii = key_system.Ascii(); std::string key_system_ascii = key_system.Ascii();
if (!key_systems_->IsSupportedKeySystem(key_system_ascii)) { if (!key_systems_->IsSupportedKeySystem(key_system_ascii)) {
#if defined(OS_MAC) && defined(ARCH_CPU_ARM_FAMILY)
// CDM support on Mac ARM is known not ready yet. We only notify once per
// render process.
static bool s_has_notified_unsupported_platform = false;
if (!s_has_notified_unsupported_platform) {
s_has_notified_unsupported_platform = true;
media_permission_->NotifyUnsupportedPlatform();
}
std::move(cb).Run(Status::kUnsupportedPlatform, nullptr, nullptr);
#else
std::move(cb).Run(Status::kUnsupportedKeySystem, nullptr, nullptr); std::move(cb).Run(Status::kUnsupportedKeySystem, nullptr, nullptr);
#endif
return; return;
} }
......
...@@ -17,6 +17,7 @@ mojom("mojom") { ...@@ -17,6 +17,7 @@ mojom("mojom") {
"audio_logging.mojom", "audio_logging.mojom",
"audio_output_stream.mojom", "audio_output_stream.mojom",
"audio_parameters.mojom", "audio_parameters.mojom",
"cdm_infobar_service.mojom",
"cdm_service.mojom", "cdm_service.mojom",
"cdm_storage.mojom", "cdm_storage.mojom",
"content_decryption_module.mojom", "content_decryption_module.mojom",
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
module media.mojom;
// Service to trigger info bar for CDM related events.
interface CdmInfobarService {
// Notifies that the platform is not supported.
NotifyUnsupportedPlatform();
};
\ No newline at end of file
...@@ -5,7 +5,8 @@ ...@@ -5,7 +5,8 @@
// of the result. // of the result.
function setResultInTitle(title) { function setResultInTitle(title) {
if (title == "" || title == "success" || title == "TypeError" || if (title == "" || title == "success" || title == "TypeError" ||
title == "Unsupported keySystem or supportedConfigurations.") { title == "Unsupported keySystem or supportedConfigurations." ||
title == "Unsupported platform.") {
document.title = title; document.title = title;
} else { } else {
console.log("Unexpected result: " + title); console.log("Unexpected result: " + title);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment