blob: 7c21734f672622c468861b3891eda6cf057c15cd [file] [log] [blame]
// Copyright 2020 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/font_access/font_access_manager.h"
#include <limits>
#include <memory>
#include <utility>
#include <vector>
#include "base/functional/bind.h"
#include "base/memory/read_only_shared_memory_region.h"
#include "base/sequence_checker.h"
#include "base/task/thread_pool.h"
#include "base/types/pass_key.h"
#include "content/browser/font_access/font_enumeration_cache.h"
#include "content/browser/font_access/font_enumeration_data_source.h"
#include "content/browser/renderer_host/frame_tree_node.h"
#include "content/browser/renderer_host/render_frame_host_impl.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/global_routing_id.h"
#include "content/public/browser/permission_controller.h"
#include "content/public/browser/permission_descriptor_util.h"
#include "content/public/browser/permission_request_description.h"
#include "content/public/browser/permission_result.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/content_client.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/font_access/font_enumeration_table.pb.h"
#include "third_party/blink/public/common/permissions/permission_utils.h"
#include "third_party/blink/public/mojom/frame/lifecycle.mojom-shared.h"
#include "third_party/blink/public/mojom/permissions/permission_status.mojom-shared.h"
namespace content {
// static
std::unique_ptr<FontAccessManager> FontAccessManager::Create() {
return std::make_unique<FontAccessManager>(
FontEnumerationCache::Create(), base::PassKey<FontAccessManager>());
}
// static
std::unique_ptr<FontAccessManager> FontAccessManager::CreateForTesting(
base::SequenceBound<FontEnumerationCache> font_enumeration_cache) {
return std::make_unique<FontAccessManager>(
std::move(font_enumeration_cache), base::PassKey<FontAccessManager>());
}
FontAccessManager::FontAccessManager(
base::SequenceBound<FontEnumerationCache> font_enumeration_cache,
base::PassKey<FontAccessManager>)
: font_enumeration_cache_(std::move(font_enumeration_cache)),
results_task_runner_(GetUIThreadTaskRunner({})) {}
FontAccessManager::~FontAccessManager() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
}
void FontAccessManager::BindReceiver(
GlobalRenderFrameHostId frame_id,
mojo::PendingReceiver<blink::mojom::FontAccessManager> receiver) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
receivers_.Add(this, std::move(receiver),
{
.frame_id = frame_id,
});
}
void FontAccessManager::EnumerateLocalFonts(
EnumerateLocalFontsCallback callback) {
DCHECK(base::FeatureList::IsEnabled(blink::features::kFontAccess));
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (skip_privacy_checks_for_testing_) {
DidRequestPermission(
std::move(callback),
PermissionResult(blink::mojom::PermissionStatus::GRANTED,
PermissionStatusSource::UNSPECIFIED));
return;
}
const BindingContext& context = receivers_.current_context();
RenderFrameHostImpl* rfh = RenderFrameHostImpl::FromID(context.frame_id);
if (rfh == nullptr) {
std::move(callback).Run(
blink::mojom::FontEnumerationStatus::kUnexpectedError,
base::ReadOnlySharedMemoryRegion());
return;
}
// Page Visibility is required for the API to function at all.
if (rfh->GetVisibilityState() !=
blink::mojom::PageVisibilityState::kVisible) {
std::move(callback).Run(blink::mojom::FontEnumerationStatus::kNotVisible,
base::ReadOnlySharedMemoryRegion());
return;
}
content::PermissionController* permission_controller =
rfh->GetBrowserContext()->GetPermissionController();
DCHECK(permission_controller);
auto status = permission_controller->GetPermissionStatusForCurrentDocument(
content::PermissionDescriptorUtil::
CreatePermissionDescriptorForPermissionType(
blink::PermissionType::LOCAL_FONTS),
rfh);
if (status != blink::mojom::PermissionStatus::ASK) {
// Permission has been requested before.
DidRequestPermission(
std::move(callback),
PermissionResult(status, PermissionStatusSource::UNSPECIFIED));
return;
}
// Transient User Activation only required before showing permission prompt.
// This action will consume it.
if (!rfh->HasTransientUserActivation()) {
std::move(callback).Run(
blink::mojom::FontEnumerationStatus::kNeedsUserActivation,
base::ReadOnlySharedMemoryRegion());
return;
}
rfh->frame_tree_node()->UpdateUserActivationState(
blink::mojom::UserActivationUpdateType::kConsumeTransientActivation,
blink::mojom::UserActivationNotificationType::kNone);
permission_controller->RequestPermissionFromCurrentDocument(
rfh,
PermissionRequestDescription(
content::PermissionDescriptorUtil::
CreatePermissionDescriptorForPermissionType(
blink::PermissionType::LOCAL_FONTS),
/*user_gesture=*/true),
base::BindOnce(&FontAccessManager::DidRequestPermission,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}
void FontAccessManager::DidRequestPermission(
EnumerateLocalFontsCallback callback,
PermissionResult permission_result) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (permission_result.status != blink::mojom::PermissionStatus::GRANTED) {
std::move(callback).Run(
blink::mojom::FontEnumerationStatus::kPermissionDenied,
base::ReadOnlySharedMemoryRegion());
return;
}
// Per-platform delegation for obtaining cached font enumeration data occurs
// here, after the permission has been granted.
font_enumeration_cache_
.AsyncCall(&FontEnumerationCache::GetFontEnumerationData)
.Then(base::BindOnce(
[](EnumerateLocalFontsCallback callback, FontEnumerationData data) {
std::move(callback).Run(data.status, std::move(data.font_data));
},
std::move(callback)));
}
} // namespace content