blob: 8814929c3a876961a514253e4ce60680170dce34 [file] [log] [blame]
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/smart_card/smart_card_service.h"
#include "content/browser/renderer_host/isolated_context_util.h"
#include "content/browser/renderer_host/render_frame_host_impl.h"
#include "content/public/browser/document_service.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/smart_card_delegate.h"
#include "services/device/public/mojom/smart_card.mojom.h"
#include "third_party/blink/public/common/features_generated.h"
namespace content {
namespace {
// Deletes the SmartCardService when the connected document is destroyed.
class DocumentHelper
: public content::DocumentService<blink::mojom::SmartCardService> {
public:
DocumentHelper(std::unique_ptr<SmartCardService> service,
RenderFrameHost& render_frame_host,
mojo::PendingReceiver<blink::mojom::SmartCardService> receiver)
: DocumentService(render_frame_host, std::move(receiver)),
service_(std::move(service)) {
DCHECK(service_);
}
~DocumentHelper() override = default;
// blink::mojom::SmartCardService:
void GetReaders(GetReadersCallback callback) override {
service_->GetReaders(std::move(callback));
}
void RegisterClient(mojo::PendingAssociatedRemote<
blink::mojom::SmartCardServiceClient> client,
RegisterClientCallback callback) override {
service_->RegisterClient(std::move(client), std::move(callback));
}
private:
const std::unique_ptr<SmartCardService> service_;
};
} // namespace
SmartCardService::SmartCardService(SmartCardDelegate& delegate)
: delegate_(delegate) {
scoped_observation_.Observe(&delegate);
}
SmartCardService::~SmartCardService() = default;
// static
void SmartCardService::Create(
RenderFrameHostImpl* render_frame_host,
mojo::PendingReceiver<blink::mojom::SmartCardService> receiver) {
BrowserContext* browser_context = render_frame_host->GetBrowserContext();
DCHECK(browser_context);
if (!base::FeatureList::IsEnabled(blink::features::kSmartCard)) {
mojo::ReportBadMessage("The SmartCard feature is disabled.");
return;
}
if (!render_frame_host->IsFeatureEnabled(
blink::mojom::PermissionsPolicyFeature::kSmartCard)) {
mojo::ReportBadMessage(
"Access to the feature \"smart-card\" is disallowed by permissions "
"policy.");
return;
}
if (!IsFrameSufficientlyIsolated(render_frame_host)) {
mojo::ReportBadMessage(
"Frame is not sufficiently isolated to use the Smart Card API.");
return;
}
SmartCardDelegate* delegate =
GetContentClient()->browser()->GetSmartCardDelegate(browser_context);
if (!delegate) {
mojo::ReportBadMessage("Browser has no Smart Card delegate.");
return;
}
// DocumentHelper observes the lifetime of the document connected to
// `render_frame_host` and destroys the SmartCardService when the Mojo
// connection is disconnected, RenderFrameHost is deleted, or the
// RenderFrameHost commits a cross-document navigation. It forwards its Mojo
// interface to SmartCardService.
new DocumentHelper(std::make_unique<SmartCardService>(*delegate),
*render_frame_host, std::move(receiver));
}
void SmartCardService::GetReaders(
SmartCardService::GetReadersCallback callback) {
delegate_->GetReaders(std::move(callback));
}
void SmartCardService::RegisterClient(
mojo::PendingAssociatedRemote<blink::mojom::SmartCardServiceClient> client,
RegisterClientCallback callback) {
clients_.Add(std::move(client));
const bool can_notify_added_removed =
delegate_->SupportsReaderAddedRemovedNotifications();
std::move(callback).Run(can_notify_added_removed);
}
void SmartCardService::OnReaderAdded(
const blink::mojom::SmartCardReaderInfo& reader_info) {
for (auto& client : clients_) {
client->ReaderAdded(reader_info.Clone());
}
}
void SmartCardService::OnReaderRemoved(
const blink::mojom::SmartCardReaderInfo& reader_info) {
for (auto& client : clients_) {
client->ReaderRemoved(reader_info.Clone());
}
}
void SmartCardService::OnReaderChanged(
const blink::mojom::SmartCardReaderInfo& reader_info) {
NOTIMPLEMENTED();
// TODO(crbug.com/1386175): Implement and test.
}
} // namespace content