Commit 70a8fdcb authored by Jeffrey Kardatzke's avatar Jeffrey Kardatzke Committed by Commit Bot

Add CdmStorage mojo interface for CdmFactoryDaemon

This is the mojo interface and implementation to adapt CdmStorage
requests from the Chrome OS daemon to the CdmStorage mojo interface in
Chrome. This will be passed into the CreateCdm mojo call in the
CdmFactory to provide origin specific storage for the Chrome OS CDM.

The implementation of the media::CdmFactory and
media::ContentDecryptionModule interfaces that us this will live
in the GPU process, which is why this component has the '_gpu'
suffix on it.

BUG=b:153111783
TEST=Unit test passes

Change-Id: I20e175e22f462a96a3c09facf06df7233484dc6a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2252684
Commit-Queue: J Kardatzke <jkardatzke@chromium.org>
Reviewed-by: default avatarDominick Ng <dominickn@chromium.org>
Reviewed-by: default avatarXiaohan Wang <xhwang@chromium.org>
Reviewed-by: default avatarSteven Bennetts <stevenjb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#780103}
parent af7ad19b
......@@ -16,6 +16,7 @@ test("chromeos_components_unittests") {
"//base/test:test_support",
"//chromeos:chromeos_buildflags",
"//chromeos/components/account_manager:unit_tests",
"//chromeos/components/cdm_factory_daemon:unit_tests",
"//chromeos/components/drivefs:unit_tests",
"//chromeos/components/mojo_bootstrap:unit_tests",
"//chromeos/components/multidevice:unit_tests",
......
......@@ -18,3 +18,34 @@ component("cdm_factory_daemon_browser") {
]
defines = [ "IS_CDM_FACTORY_DAEMON_IMPL" ]
}
component("cdm_factory_daemon_gpu") {
sources = [
"cdm_storage_adapter.cc",
"cdm_storage_adapter.h",
]
public_deps = [
"//chromeos/components/cdm_factory_daemon/mojom",
"//media/mojo/mojom",
]
deps = [
"//base",
"//mojo/public/cpp/bindings",
]
defines = [ "IS_CDM_FACTORY_DAEMON_IMPL" ]
}
source_set("unit_tests") {
testonly = true
sources = [ "cdm_storage_adapter_unittest.cc" ]
deps = [
":cdm_factory_daemon_gpu",
"//base",
"//base/test:test_support",
"//chromeos/components/cdm_factory_daemon/mojom",
"//mojo/public/cpp/bindings",
"//testing/gmock",
"//testing/gtest",
]
}
include_rules = [
"+components/arc/mojom",
"+content/public/browser",
"+media/mojo/mojom",
]
\ No newline at end of file
......@@ -31,11 +31,12 @@ class COMPONENT_EXPORT(CDM_FACTORY_DAEMON) CdmFactoryDaemonProxy
typedef base::OnceCallback<void(bool connected)> ValidateDaemonConnectionCB;
CdmFactoryDaemonProxy();
~CdmFactoryDaemonProxy() override;
CdmFactoryDaemonProxy(const CdmFactoryDaemonProxy&) = delete;
CdmFactoryDaemonProxy& operator=(const CdmFactoryDaemonProxy&) = delete;
~CdmFactoryDaemonProxy() override;
static void Create(mojo::PendingReceiver<CdmFactoryDaemon> receiver);
static CdmFactoryDaemonProxy& GetInstance();
......
// 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.
#include "chromeos/components/cdm_factory_daemon/cdm_storage_adapter.h"
#include <utility>
#include "base/bind.h"
#include "mojo/public/cpp/bindings/callback_helpers.h"
namespace chromeos {
namespace {
// Helper function to adapt Exists using Read since CdmStorage doesn't have an
// Exists implementation. We test it by seeing if the file is non-empty.
void ReadToExists(cdm::mojom::CdmStorage::ExistsCallback callback,
bool success,
const std::vector<uint8_t>& data) {
std::move(callback).Run(success && !data.empty());
}
// Helper function to adapt GetSize using Read since CdmFile doesn't have a
// GetSize implementation. We get the size by reading the file contents and
// determining the length. These files will be small in size and are accessed
// infrequently, so this isn't that much of a penalty to pay.
void ReadToGetSize(cdm::mojom::CdmStorage::GetSizeCallback callback,
bool success,
const std::vector<uint8_t>& data) {
std::move(callback).Run(success, data.size());
}
} // namespace
CdmStorageAdapter::CdmStorageAdapter(
media::mojom::FrameInterfaceFactory* frame_interfaces,
mojo::PendingAssociatedReceiver<chromeos::cdm::mojom::CdmStorage> receiver)
: receiver_(this, std::move(receiver)) {
CHECK(frame_interfaces);
frame_interfaces->CreateCdmStorage(
cdm_storage_remote_.BindNewPipeAndPassReceiver());
}
CdmStorageAdapter::~CdmStorageAdapter() = default;
void CdmStorageAdapter::Read(const std::string& file_name,
ReadCallback callback) {
DVLOG(1) << "Read " << file_name;
CHECK(!cdm_file_);
auto wrapped_callback = mojo::WrapCallbackWithDefaultInvokeIfNotRun(
std::move(callback), false, std::vector<uint8_t>());
cdm_storage_remote_->Open(
file_name,
base::BindOnce(&CdmStorageAdapter::OnOpenForRead,
weak_factory_.GetWeakPtr(), std::move(wrapped_callback)));
}
void CdmStorageAdapter::OnOpenForRead(
ReadCallback callback,
media::mojom::CdmStorage::Status status,
mojo::PendingAssociatedRemote<media::mojom::CdmFile> cdm_file) {
if (status != media::mojom::CdmStorage::Status::kSuccess) {
std::move(callback).Run(false, {});
return;
}
cdm_file_.Bind(std::move(cdm_file));
cdm_file_->Read(base::BindOnce(&CdmStorageAdapter::OnReadComplete,
weak_factory_.GetWeakPtr(),
std::move(callback)));
}
void CdmStorageAdapter::OnReadComplete(ReadCallback callback,
media::mojom::CdmFile::Status status,
const std::vector<uint8_t>& data) {
cdm_file_.reset();
if (status != media::mojom::CdmFile::Status::kSuccess) {
std::move(callback).Run(false, {});
return;
}
std::move(callback).Run(true, data);
}
void CdmStorageAdapter::Write(const std::string& file_name,
const std::vector<uint8_t>& data,
WriteCallback callback) {
DVLOG(1) << "Write " << file_name;
CHECK(!cdm_file_);
auto wrapped_callback =
mojo::WrapCallbackWithDefaultInvokeIfNotRun(std::move(callback), false);
cdm_storage_remote_->Open(file_name,
base::BindOnce(&CdmStorageAdapter::OnOpenForWrite,
weak_factory_.GetWeakPtr(), data,
std::move(wrapped_callback)));
}
void CdmStorageAdapter::OnOpenForWrite(
const std::vector<uint8_t>& data,
WriteCallback callback,
media::mojom::CdmStorage::Status status,
mojo::PendingAssociatedRemote<media::mojom::CdmFile> cdm_file) {
if (status != media::mojom::CdmStorage::Status::kSuccess) {
std::move(callback).Run(false);
return;
}
cdm_file_.Bind(std::move(cdm_file));
cdm_file_->Write(
data, base::BindOnce(&CdmStorageAdapter::OnWriteComplete,
weak_factory_.GetWeakPtr(), std::move(callback)));
}
void CdmStorageAdapter::OnWriteComplete(WriteCallback callback,
media::mojom::CdmFile::Status status) {
cdm_file_.reset();
std::move(callback).Run(status == media::mojom::CdmFile::Status::kSuccess);
}
void CdmStorageAdapter::Exists(const std::string& file_name,
ExistsCallback callback) {
DVLOG(1) << "Exists " << file_name;
Read(file_name, base::BindOnce(&ReadToExists, std::move(callback)));
}
void CdmStorageAdapter::GetSize(const std::string& file_name,
GetSizeCallback callback) {
DVLOG(1) << "GetSize " << file_name;
Read(file_name, base::BindOnce(&ReadToGetSize, std::move(callback)));
}
void CdmStorageAdapter::Remove(const std::string& file_name,
RemoveCallback callback) {
DVLOG(1) << "Remove " << file_name;
// Writing a zero length array to the file removes it.
Write(file_name, {}, std::move(callback));
}
} // namespace chromeos
\ No newline at end of file
// 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.
#ifndef CHROMEOS_COMPONENTS_CDM_FACTORY_DAEMON_CDM_STORAGE_ADAPTER_H_
#define CHROMEOS_COMPONENTS_CDM_FACTORY_DAEMON_CDM_STORAGE_ADAPTER_H_
#include <memory>
#include <string>
#include "base/component_export.h"
#include "base/memory/weak_ptr.h"
#include "chromeos/components/cdm_factory_daemon/mojom/cdm_storage.mojom.h"
#include "media/mojo/mojom/cdm_storage.mojom.h"
#include "media/mojo/mojom/frame_interface_factory.mojom.h"
#include "mojo/public/cpp/bindings/associated_receiver.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
namespace chromeos {
// This class adapts the chromeos::cdm::mojom::CdmStorage interface to the
// media::mojom::CdmStorage and media::mojom::CdmFile interfaces. The incoming
// chromeos::cdm::mojom::CdmStorage interface has all methods marked Sync which
// means we will never receive simultaneous calls.
class COMPONENT_EXPORT(CDM_FACTORY_DAEMON) CdmStorageAdapter
: public cdm::mojom::CdmStorage {
public:
CdmStorageAdapter(
media::mojom::FrameInterfaceFactory* frame_interfaces,
mojo::PendingAssociatedReceiver<cdm::mojom::CdmStorage> receiver);
CdmStorageAdapter(const CdmStorageAdapter&) = delete;
CdmStorageAdapter& operator=(const CdmStorageAdapter&) = delete;
~CdmStorageAdapter() override;
// chromeos::cdm::mojom::CdmStorage:
void Read(const std::string& file_name, ReadCallback callback) override;
void Write(const std::string& file_name,
const std::vector<uint8_t>& data,
WriteCallback callback) override;
void Exists(const std::string& file_name, ExistsCallback callback) override;
void GetSize(const std::string& file_name, GetSizeCallback callback) override;
void Remove(const std::string& file_name, RemoveCallback callback) override;
private:
void OnOpenForRead(
ReadCallback callback,
media::mojom::CdmStorage::Status status,
mojo::PendingAssociatedRemote<media::mojom::CdmFile> cdm_file);
void OnReadComplete(ReadCallback callback,
media::mojom::CdmFile::Status status,
const std::vector<uint8_t>& data);
void OnOpenForWrite(
const std::vector<uint8_t>& data,
WriteCallback callback,
media::mojom::CdmStorage::Status status,
mojo::PendingAssociatedRemote<media::mojom::CdmFile> cdm_file);
void OnWriteComplete(WriteCallback callback,
media::mojom::CdmFile::Status status);
mojo::AssociatedReceiver<cdm::mojom::CdmStorage> receiver_;
mojo::Remote<media::mojom::CdmStorage> cdm_storage_remote_;
// |cdm_file_| is used to read and write the file and is released when the
// file is closed so that CdmStorage can tell that the file is no longer being
// used. It's safe to reuse this because our incoming mojo interface is
// defined as all Sync methods so we will never receive two calls at once.
mojo::AssociatedRemote<media::mojom::CdmFile> cdm_file_;
// WeakPtrFactory to use for callbacks.
base::WeakPtrFactory<CdmStorageAdapter> weak_factory_{this};
};
} // namespace chromeos
#endif // CHROMEOS_COMPONENTS_CDM_FACTORY_DAEMON_CDM_STORAGE_ADAPTER_H_
......@@ -5,7 +5,10 @@
import("//mojo/public/tools/bindings/mojom.gni")
mojom_component("mojom") {
sources = [ "cdm_factory_daemon.mojom" ]
sources = [
"cdm_factory_daemon.mojom",
"cdm_storage.mojom",
]
public_deps = [
"//components/arc/mojom:media",
......
// 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.
// Next MinVersion: 2
module chromeos.cdm.mojom;
// Provides a interface for per-origin/cdm storage handled by Chrome. This is
// meant to translate to the media/mojo/mojom/cdm_storage.mojom interface that
// is in Chrome but is tied more closely to the Widevine CE CDM IStorage
// interface on this end. This one exists for the purpose of being able to do
// version management so we can handle version diffs between Chrome and
// Chrome OS.
// Next Method ID: 5
interface CdmStorage {
// Reads the contents of |file_name| and return them in |data|. Returns
// true and the file contents if successful. Errors reading the file or
// non-existent files will return false and an empty data array.
[Sync]
Read@0(string file_name) => (bool success, array<uint8> data);
// Creates/overwrites the contents of |file_name| with |data|. If the
// write operation is successful, then true is returned, otherwise false is
// returned. The contents of the file are unknown if Write() fails.
[Sync]
Write@1(string file_name, array<uint8> data) => (bool success);
// Determines whether the specified file name exists or not. Returns true
// if the file exists and false if it does not or an error occurred.
[Sync]
Exists@2(string file_name) => (bool success);
// Gets the file size of the specified file name. Returned size is valid if
// status is true.
[Sync]
GetSize@3(string file_name) => (bool success, uint64 size);
// Removes the file at the specified path. Returns true if the file does not
// exist or it exists and was removed; returns false otherwise.
[Sync]
Remove@4(string file_name) => (bool success);
};
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