mirror of
https://github.com/electron/electron.git
synced 2026-05-02 03:00:22 -04:00
feat: add support for the U2F Web API (#30438)
* feat: add support for the U2F Web API * chore: fix lint * chore: fix tests * build: disable src caching * Revert "build: disable src caching" This reverts commit c4c8a60fc435a10788475ec171399a55ac2dd674. * chore: update per feedback * chore: consistent code removal
This commit is contained in:
@@ -142,6 +142,7 @@
|
||||
#include "extensions/browser/api/mime_handler_private/mime_handler_private.h"
|
||||
#include "extensions/browser/api/web_request/web_request_api.h"
|
||||
#include "extensions/browser/browser_context_keyed_api_factory.h"
|
||||
#include "extensions/browser/event_router.h"
|
||||
#include "extensions/browser/extension_host.h"
|
||||
#include "extensions/browser/extension_message_filter.h"
|
||||
#include "extensions/browser/extension_navigation_throttle.h"
|
||||
@@ -163,6 +164,7 @@
|
||||
#include "shell/browser/extensions/electron_extension_message_filter.h"
|
||||
#include "shell/browser/extensions/electron_extension_system.h"
|
||||
#include "shell/browser/extensions/electron_extension_web_contents_observer.h"
|
||||
#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(ENABLE_PLUGINS)
|
||||
@@ -1551,6 +1553,16 @@ void BindBeforeUnloadControl(
|
||||
}
|
||||
#endif
|
||||
|
||||
void ElectronBrowserClient::ExposeInterfacesToRenderer(
|
||||
service_manager::BinderRegistry* registry,
|
||||
blink::AssociatedInterfaceRegistry* associated_registry,
|
||||
content::RenderProcessHost* render_process_host) {
|
||||
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||
associated_registry->AddInterface(base::BindRepeating(
|
||||
&extensions::EventRouter::BindForRenderer, render_process_host->GetID()));
|
||||
#endif
|
||||
}
|
||||
|
||||
void ElectronBrowserClient::RegisterBrowserInterfaceBindersForFrame(
|
||||
content::RenderFrameHost* render_frame_host,
|
||||
mojo::BinderMapWithContext<content::RenderFrameHost*>* map) {
|
||||
|
||||
@@ -69,6 +69,10 @@ class ElectronBrowserClient : public content::ContentBrowserClient,
|
||||
void BindHostReceiverForRenderer(
|
||||
content::RenderProcessHost* render_process_host,
|
||||
mojo::GenericPendingReceiver receiver) override;
|
||||
void ExposeInterfacesToRenderer(
|
||||
service_manager::BinderRegistry* registry,
|
||||
blink::AssociatedInterfaceRegistry* associated_registry,
|
||||
content::RenderProcessHost* render_process_host) override;
|
||||
void RegisterBrowserInterfaceBindersForFrame(
|
||||
content::RenderFrameHost* render_frame_host,
|
||||
mojo::BinderMapWithContext<content::RenderFrameHost*>* map) override;
|
||||
|
||||
@@ -10,6 +10,7 @@ assert(enable_extensions,
|
||||
|
||||
function_registration("api_registration") {
|
||||
sources = [
|
||||
"//electron/shell/common/extensions/api/cryptotoken_private.idl",
|
||||
"//electron/shell/common/extensions/api/extension.json",
|
||||
"//electron/shell/common/extensions/api/i18n.json",
|
||||
"//electron/shell/common/extensions/api/resources_private.idl",
|
||||
|
||||
@@ -0,0 +1,311 @@
|
||||
// Copyright 2014 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 "shell/browser/extensions/api/cryptotoken_private/cryptotoken_private_api.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "base/bind.h"
|
||||
#include "base/callback.h"
|
||||
#include "base/metrics/histogram_macros.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "build/build_config.h"
|
||||
// #include "chrome/browser/extensions/extension_tab_util.h"
|
||||
// #include "chrome/browser/permissions/attestation_permission_request.h"
|
||||
// #include "chrome/browser/profiles/profile.h"
|
||||
#include "chrome/common/chrome_features.h"
|
||||
#include "chrome/common/pref_names.h"
|
||||
// #include
|
||||
// "components/page_load_metrics/browser/metrics_web_contents_observer.h"
|
||||
// #include "components/permissions/permission_request_manager.h"
|
||||
#include "components/pref_registry/pref_registry_syncable.h"
|
||||
#include "components/prefs/pref_service.h"
|
||||
#include "content/public/browser/render_frame_host.h"
|
||||
#include "content/public/browser/web_contents.h"
|
||||
#include "crypto/sha2.h"
|
||||
#include "device/fido/filter.h"
|
||||
#include "extensions/browser/extension_api_frame_id_map.h"
|
||||
#include "extensions/common/error_utils.h"
|
||||
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
|
||||
#include "shell/browser/api/electron_api_web_contents.h"
|
||||
#include "url/origin.h"
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#include "device/fido/features.h"
|
||||
#include "device/fido/win/webauthn_api.h"
|
||||
#endif // defined(OS_WIN)
|
||||
|
||||
namespace extensions {
|
||||
|
||||
namespace api {
|
||||
|
||||
namespace {
|
||||
|
||||
const char kGoogleDotCom[] = "google.com";
|
||||
constexpr const char* kGoogleGstaticAppIds[] = {
|
||||
"https://www.gstatic.com/securitykey/origins.json",
|
||||
"https://www.gstatic.com/securitykey/a/google.com/origins.json"};
|
||||
|
||||
// ContainsAppIdByHash returns true iff the SHA-256 hash of one of the
|
||||
// elements of |list| equals |hash|.
|
||||
bool ContainsAppIdByHash(const base::ListValue& list,
|
||||
const std::vector<uint8_t>& hash) {
|
||||
if (hash.size() != crypto::kSHA256Length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const auto& i : list.GetList()) {
|
||||
const std::string& s = i.GetString();
|
||||
if (s.find('/') == std::string::npos) {
|
||||
// No slashes mean that this is a webauthn RP ID, not a U2F AppID.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (crypto::SHA256HashString(s).compare(
|
||||
0, crypto::kSHA256Length,
|
||||
reinterpret_cast<const char*>(hash.data()),
|
||||
crypto::kSHA256Length) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
content::RenderFrameHost* RenderFrameHostForTabAndFrameId(
|
||||
content::BrowserContext* const browser_context,
|
||||
const int tab_id,
|
||||
const int frame_id) {
|
||||
auto* contents = electron::api::WebContents::FromID(tab_id);
|
||||
if (!contents || !contents->web_contents()) {
|
||||
return nullptr;
|
||||
}
|
||||
return ExtensionApiFrameIdMap::GetRenderFrameHostById(
|
||||
contents->web_contents(), frame_id);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// void CryptotokenRegisterProfilePrefs(
|
||||
// user_prefs::PrefRegistrySyncable* registry) {
|
||||
// registry->RegisterListPref(prefs::kSecurityKeyPermitAttestation);
|
||||
// }
|
||||
|
||||
CryptotokenPrivateCanOriginAssertAppIdFunction::
|
||||
CryptotokenPrivateCanOriginAssertAppIdFunction() = default;
|
||||
|
||||
ExtensionFunction::ResponseAction
|
||||
CryptotokenPrivateCanOriginAssertAppIdFunction::Run() {
|
||||
std::unique_ptr<cryptotoken_private::CanOriginAssertAppId::Params> params =
|
||||
cryptotoken_private::CanOriginAssertAppId::Params::Create(*args_);
|
||||
EXTENSION_FUNCTION_VALIDATE(params);
|
||||
|
||||
const GURL origin_url(params->security_origin);
|
||||
if (!origin_url.is_valid()) {
|
||||
return RespondNow(Error(extensions::ErrorUtils::FormatErrorMessage(
|
||||
"Security origin * is not a valid URL", params->security_origin)));
|
||||
}
|
||||
const GURL app_id_url(params->app_id_url);
|
||||
if (!app_id_url.is_valid()) {
|
||||
return RespondNow(Error(extensions::ErrorUtils::FormatErrorMessage(
|
||||
"appId * is not a valid URL", params->app_id_url)));
|
||||
}
|
||||
|
||||
if (origin_url == app_id_url) {
|
||||
return RespondNow(OneArgument(base::Value(true)));
|
||||
}
|
||||
|
||||
// Fetch the eTLD+1 of both.
|
||||
const std::string origin_etldp1 =
|
||||
net::registry_controlled_domains::GetDomainAndRegistry(
|
||||
origin_url,
|
||||
net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
|
||||
if (origin_etldp1.empty()) {
|
||||
return RespondNow(Error(extensions::ErrorUtils::FormatErrorMessage(
|
||||
"Could not find an eTLD for origin *", params->security_origin)));
|
||||
}
|
||||
const std::string app_id_etldp1 =
|
||||
net::registry_controlled_domains::GetDomainAndRegistry(
|
||||
app_id_url,
|
||||
net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
|
||||
if (app_id_etldp1.empty()) {
|
||||
return RespondNow(Error(extensions::ErrorUtils::FormatErrorMessage(
|
||||
"Could not find an eTLD for appId *", params->app_id_url)));
|
||||
}
|
||||
if (origin_etldp1 == app_id_etldp1) {
|
||||
return RespondNow(OneArgument(base::Value(true)));
|
||||
}
|
||||
// For legacy purposes, allow google.com origins to assert certain
|
||||
// gstatic.com appIds.
|
||||
// TODO(juanlang): remove when legacy constraints are removed.
|
||||
if (origin_etldp1 == kGoogleDotCom) {
|
||||
for (const char* id : kGoogleGstaticAppIds) {
|
||||
if (params->app_id_url == id)
|
||||
return RespondNow(OneArgument(base::Value(true)));
|
||||
}
|
||||
}
|
||||
return RespondNow(OneArgument(base::Value(false)));
|
||||
}
|
||||
|
||||
CryptotokenPrivateIsAppIdHashInEnterpriseContextFunction::
|
||||
CryptotokenPrivateIsAppIdHashInEnterpriseContextFunction() {}
|
||||
|
||||
ExtensionFunction::ResponseAction
|
||||
CryptotokenPrivateIsAppIdHashInEnterpriseContextFunction::Run() {
|
||||
std::unique_ptr<cryptotoken_private::IsAppIdHashInEnterpriseContext::Params>
|
||||
params(
|
||||
cryptotoken_private::IsAppIdHashInEnterpriseContext::Params::Create(
|
||||
*args_));
|
||||
EXTENSION_FUNCTION_VALIDATE(params);
|
||||
|
||||
#if 0
|
||||
Profile* const profile = Profile::FromBrowserContext(browser_context());
|
||||
const PrefService* const prefs = profile->GetPrefs();
|
||||
const base::ListValue* const permit_attestation =
|
||||
prefs->GetList(prefs::kSecurityKeyPermitAttestation);
|
||||
#endif
|
||||
const base::ListValue permit_attestation;
|
||||
|
||||
return RespondNow(ArgumentList(
|
||||
cryptotoken_private::IsAppIdHashInEnterpriseContext::Results::Create(
|
||||
ContainsAppIdByHash(permit_attestation, params->app_id_hash))));
|
||||
}
|
||||
|
||||
CryptotokenPrivateCanAppIdGetAttestationFunction::
|
||||
CryptotokenPrivateCanAppIdGetAttestationFunction() {}
|
||||
|
||||
ExtensionFunction::ResponseAction
|
||||
CryptotokenPrivateCanAppIdGetAttestationFunction::Run() {
|
||||
std::unique_ptr<cryptotoken_private::CanAppIdGetAttestation::Params> params =
|
||||
cryptotoken_private::CanAppIdGetAttestation::Params::Create(*args_);
|
||||
EXTENSION_FUNCTION_VALIDATE(params);
|
||||
|
||||
return RespondNow(Error("API not supported in Electron"));
|
||||
#if 0
|
||||
const GURL origin_url(params->options.origin);
|
||||
if (!origin_url.is_valid()) {
|
||||
return RespondNow(Error(extensions::ErrorUtils::FormatErrorMessage(
|
||||
"Security origin * is not a valid URL", params->options.origin)));
|
||||
}
|
||||
const url::Origin origin(url::Origin::Create(origin_url));
|
||||
|
||||
const std::string& app_id = params->options.app_id;
|
||||
|
||||
// If the appId is permitted by the enterprise policy then no permission
|
||||
// prompt is shown.
|
||||
// Profile* const profile = Profile::FromBrowserContext(browser_context());
|
||||
// const PrefService* const prefs = profile->GetPrefs();
|
||||
// const base::ListValue* const permit_attestation =
|
||||
// prefs->GetList(prefs::kSecurityKeyPermitAttestation);
|
||||
|
||||
// for (const auto& entry : permit_attestation->GetList()) {
|
||||
// if (entry.GetString() == app_id)
|
||||
// return RespondNow(OneArgument(base::Value(true)));
|
||||
// }
|
||||
|
||||
// If the origin is blocked, reject attestation.
|
||||
if (device::fido_filter::Evaluate(
|
||||
device::fido_filter::Operation::MAKE_CREDENTIAL, origin.Serialize(),
|
||||
/*device=*/absl::nullopt, /*id=*/absl::nullopt) ==
|
||||
device::fido_filter::Action::NO_ATTESTATION) {
|
||||
return RespondNow(OneArgument(base::Value(false)));
|
||||
}
|
||||
|
||||
// If prompting is disabled, allow attestation because that is the historical
|
||||
// behavior.
|
||||
if (!base::FeatureList::IsEnabled(
|
||||
::features::kSecurityKeyAttestationPrompt)) {
|
||||
return RespondNow(OneArgument(base::Value(true)));
|
||||
}
|
||||
|
||||
#if defined(OS_WIN)
|
||||
// If the request was handled by the Windows WebAuthn API on a version of
|
||||
// Windows that shows an attestation permission prompt, don't show another
|
||||
// one.
|
||||
//
|
||||
// Note that this does not account for the possibility of the
|
||||
// WinWebAuthnApi having been disabled by a FidoDiscoveryFactory override,
|
||||
// which may be done in tests or via the Virtual Authenticator WebDriver
|
||||
// API.
|
||||
if (base::FeatureList::IsEnabled(device::kWebAuthUseNativeWinApi) &&
|
||||
device::WinWebAuthnApi::GetDefault()->IsAvailable() &&
|
||||
device::WinWebAuthnApi::GetDefault()->Version() >=
|
||||
WEBAUTHN_API_VERSION_2) {
|
||||
return RespondNow(OneArgument(base::Value(true)));
|
||||
}
|
||||
#endif // defined(OS_WIN)
|
||||
|
||||
// Otherwise, show a permission prompt and pass the user's decision back.
|
||||
const GURL app_id_url(app_id);
|
||||
EXTENSION_FUNCTION_VALIDATE(app_id_url.is_valid());
|
||||
|
||||
auto* contents = electron::api::WebContents::FromID(params->options.tab_id);
|
||||
if (!contents || !contents->web_contents()) {
|
||||
return RespondNow(Error("cannot find specified tab"));
|
||||
}
|
||||
|
||||
// permissions::PermissionRequestManager* permission_request_manager =
|
||||
// permissions::PermissionRequestManager::FromWebContents(web_contents);
|
||||
// nullptr;
|
||||
// if (!permission_request_manager) {
|
||||
return RespondNow(Error("no PermissionRequestManager"));
|
||||
// }
|
||||
|
||||
// // The created AttestationPermissionRequest deletes itself once complete.
|
||||
// permission_request_manager->AddRequest(
|
||||
// web_contents->GetMainFrame(), // Extension API targets a particular
|
||||
// tab,
|
||||
// // so select the current main frame to
|
||||
// // handle the request.
|
||||
// NewAttestationPermissionRequest(
|
||||
// origin,
|
||||
// base::BindOnce(
|
||||
// &CryptotokenPrivateCanAppIdGetAttestationFunction::Complete,
|
||||
// this)));
|
||||
// return RespondLater();
|
||||
#endif
|
||||
}
|
||||
|
||||
void CryptotokenPrivateCanAppIdGetAttestationFunction::Complete(bool result) {
|
||||
Respond(OneArgument(base::Value(result)));
|
||||
}
|
||||
|
||||
ExtensionFunction::ResponseAction
|
||||
CryptotokenPrivateRecordRegisterRequestFunction::Run() {
|
||||
auto params =
|
||||
cryptotoken_private::RecordRegisterRequest::Params::Create(*args_);
|
||||
EXTENSION_FUNCTION_VALIDATE(params);
|
||||
|
||||
content::RenderFrameHost* frame = RenderFrameHostForTabAndFrameId(
|
||||
browser_context(), params->tab_id, params->frame_id);
|
||||
if (!frame) {
|
||||
return RespondNow(Error("cannot find specified tab or frame"));
|
||||
}
|
||||
|
||||
// page_load_metrics::MetricsWebContentsObserver::RecordFeatureUsage(
|
||||
// frame, blink::mojom::WebFeature::kU2FCryptotokenRegister);
|
||||
return RespondNow(NoArguments());
|
||||
}
|
||||
|
||||
ExtensionFunction::ResponseAction
|
||||
CryptotokenPrivateRecordSignRequestFunction::Run() {
|
||||
auto params = cryptotoken_private::RecordSignRequest::Params::Create(*args_);
|
||||
EXTENSION_FUNCTION_VALIDATE(params);
|
||||
|
||||
content::RenderFrameHost* frame = RenderFrameHostForTabAndFrameId(
|
||||
browser_context(), params->tab_id, params->frame_id);
|
||||
if (!frame) {
|
||||
return RespondNow(Error("cannot find specified tab or frame"));
|
||||
}
|
||||
|
||||
// page_load_metrics::MetricsWebContentsObserver::RecordFeatureUsage(
|
||||
// frame, blink::mojom::WebFeature::kU2FCryptotokenSign);
|
||||
return RespondNow(NoArguments());
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
} // namespace extensions
|
||||
@@ -0,0 +1,86 @@
|
||||
// Copyright 2014 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 SHELL_BROWSER_EXTENSIONS_API_CRYPTOTOKEN_PRIVATE_CRYPTOTOKEN_PRIVATE_API_H_
|
||||
#define SHELL_BROWSER_EXTENSIONS_API_CRYPTOTOKEN_PRIVATE_CRYPTOTOKEN_PRIVATE_API_H_
|
||||
|
||||
#include "chrome/common/extensions/api/cryptotoken_private.h"
|
||||
#include "extensions/browser/extension_function.h"
|
||||
|
||||
namespace user_prefs {
|
||||
class PrefRegistrySyncable;
|
||||
}
|
||||
|
||||
// Implementations for chrome.cryptotokenPrivate API functions.
|
||||
|
||||
namespace extensions {
|
||||
namespace api {
|
||||
|
||||
// void CryptotokenRegisterProfilePrefs(
|
||||
// user_prefs::PrefRegistrySyncable* registry);
|
||||
|
||||
class CryptotokenPrivateCanOriginAssertAppIdFunction
|
||||
: public ExtensionFunction {
|
||||
public:
|
||||
CryptotokenPrivateCanOriginAssertAppIdFunction();
|
||||
DECLARE_EXTENSION_FUNCTION("cryptotokenPrivate.canOriginAssertAppId",
|
||||
CRYPTOTOKENPRIVATE_CANORIGINASSERTAPPID)
|
||||
protected:
|
||||
~CryptotokenPrivateCanOriginAssertAppIdFunction() override {}
|
||||
ResponseAction Run() override;
|
||||
};
|
||||
|
||||
class CryptotokenPrivateIsAppIdHashInEnterpriseContextFunction
|
||||
: public ExtensionFunction {
|
||||
public:
|
||||
CryptotokenPrivateIsAppIdHashInEnterpriseContextFunction();
|
||||
DECLARE_EXTENSION_FUNCTION(
|
||||
"cryptotokenPrivate.isAppIdHashInEnterpriseContext",
|
||||
CRYPTOTOKENPRIVATE_ISAPPIDHASHINENTERPRISECONTEXT)
|
||||
|
||||
protected:
|
||||
~CryptotokenPrivateIsAppIdHashInEnterpriseContextFunction() override {}
|
||||
ResponseAction Run() override;
|
||||
};
|
||||
|
||||
class CryptotokenPrivateCanAppIdGetAttestationFunction
|
||||
: public ExtensionFunction {
|
||||
public:
|
||||
CryptotokenPrivateCanAppIdGetAttestationFunction();
|
||||
DECLARE_EXTENSION_FUNCTION("cryptotokenPrivate.canAppIdGetAttestation",
|
||||
CRYPTOTOKENPRIVATE_CANAPPIDGETATTESTATION)
|
||||
|
||||
protected:
|
||||
~CryptotokenPrivateCanAppIdGetAttestationFunction() override {}
|
||||
ResponseAction Run() override;
|
||||
void Complete(bool result);
|
||||
};
|
||||
|
||||
class CryptotokenPrivateRecordRegisterRequestFunction
|
||||
: public ExtensionFunction {
|
||||
public:
|
||||
CryptotokenPrivateRecordRegisterRequestFunction() = default;
|
||||
DECLARE_EXTENSION_FUNCTION("cryptotokenPrivate.recordRegisterRequest",
|
||||
CRYPTOTOKENPRIVATE_RECORDREGISTERREQUEST)
|
||||
|
||||
protected:
|
||||
~CryptotokenPrivateRecordRegisterRequestFunction() override = default;
|
||||
ResponseAction Run() override;
|
||||
};
|
||||
|
||||
class CryptotokenPrivateRecordSignRequestFunction : public ExtensionFunction {
|
||||
public:
|
||||
CryptotokenPrivateRecordSignRequestFunction() = default;
|
||||
DECLARE_EXTENSION_FUNCTION("cryptotokenPrivate.recordSignRequest",
|
||||
CRYPTOTOKENPRIVATE_RECORDSIGNREQUEST)
|
||||
|
||||
protected:
|
||||
~CryptotokenPrivateRecordSignRequestFunction() override = default;
|
||||
ResponseAction Run() override;
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
} // namespace extensions
|
||||
|
||||
#endif // SHELL_BROWSER_EXTENSIONS_API_CRYPTOTOKEN_PRIVATE_CRYPTOTOKEN_PRIVATE_API_H_
|
||||
@@ -200,6 +200,8 @@ ExtensionFunction::ResponseAction TabsGetFunction::Run() {
|
||||
tab.url = std::make_unique<std::string>(
|
||||
contents->web_contents()->GetLastCommittedURL().spec());
|
||||
|
||||
tab.active = contents->IsFocused();
|
||||
|
||||
return RespondNow(ArgumentList(tabs::Get::Results::Create(std::move(tab))));
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "content/public/browser/notification_service.h"
|
||||
#include "content/public/browser/notification_source.h"
|
||||
#include "electron/buildflags/buildflags.h"
|
||||
#include "electron/grit/electron_resources.h"
|
||||
#include "extensions/browser/api/app_runtime/app_runtime_api.h"
|
||||
#include "extensions/browser/extension_registry.h"
|
||||
#include "extensions/browser/info_map.h"
|
||||
@@ -36,6 +37,7 @@
|
||||
#include "extensions/common/constants.h"
|
||||
#include "extensions/common/file_util.h"
|
||||
#include "shell/browser/extensions/electron_extension_loader.h"
|
||||
#include "ui/base/resource/resource_bundle.h"
|
||||
|
||||
#if BUILDFLAG(ENABLE_PDF_VIEWER)
|
||||
#include "chrome/browser/pdf/pdf_extension_util.h" // nogncheck
|
||||
@@ -46,6 +48,18 @@ using content::BrowserThread;
|
||||
|
||||
namespace extensions {
|
||||
|
||||
namespace {
|
||||
|
||||
std::string GetCryptoTokenManifest() {
|
||||
std::string manifest_contents(
|
||||
ui::ResourceBundle::GetSharedInstance().GetRawDataResource(
|
||||
IDR_CRYPTOTOKEN_MANIFEST));
|
||||
|
||||
return manifest_contents;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
ElectronExtensionSystem::ElectronExtensionSystem(
|
||||
BrowserContext* browser_context)
|
||||
: browser_context_(browser_context),
|
||||
@@ -109,8 +123,8 @@ std::unique_ptr<base::DictionaryValue> ParseManifest(
|
||||
}
|
||||
|
||||
void ElectronExtensionSystem::LoadComponentExtensions() {
|
||||
#if BUILDFLAG(ENABLE_PDF_VIEWER)
|
||||
std::string utf8_error;
|
||||
#if BUILDFLAG(ENABLE_PDF_VIEWER)
|
||||
std::string pdf_manifest_string = pdf_extension_util::GetManifest();
|
||||
std::unique_ptr<base::DictionaryValue> pdf_manifest =
|
||||
ParseManifest(pdf_manifest_string);
|
||||
@@ -125,6 +139,22 @@ void ElectronExtensionSystem::LoadComponentExtensions() {
|
||||
extension_loader_->registrar()->AddExtension(pdf_extension);
|
||||
}
|
||||
#endif
|
||||
|
||||
std::string cryptotoken_manifest_string = GetCryptoTokenManifest();
|
||||
std::unique_ptr<base::DictionaryValue> cryptotoken_manifest =
|
||||
ParseManifest(cryptotoken_manifest_string);
|
||||
DCHECK(cryptotoken_manifest);
|
||||
if (cryptotoken_manifest) {
|
||||
base::FilePath root_directory;
|
||||
CHECK(base::PathService::Get(chrome::DIR_RESOURCES, &root_directory));
|
||||
root_directory = root_directory.Append(FILE_PATH_LITERAL("cryptotoken"));
|
||||
scoped_refptr<const Extension> cryptotoken_extension =
|
||||
extensions::Extension::Create(
|
||||
root_directory, extensions::mojom::ManifestLocation::kComponent,
|
||||
*cryptotoken_manifest, extensions::Extension::REQUIRE_KEY,
|
||||
&utf8_error);
|
||||
extension_loader_->registrar()->AddExtension(cryptotoken_extension);
|
||||
}
|
||||
}
|
||||
|
||||
ExtensionService* ElectronExtensionSystem::extension_service() {
|
||||
|
||||
@@ -36,6 +36,7 @@ group("extensions_features") {
|
||||
|
||||
generated_json_strings("generated_api_json_strings") {
|
||||
sources = [
|
||||
"cryptotoken_private.idl",
|
||||
"extension.json",
|
||||
"i18n.json",
|
||||
"resources_private.idl",
|
||||
@@ -54,6 +55,7 @@ generated_json_strings("generated_api_json_strings") {
|
||||
|
||||
generated_types("generated_api_types") {
|
||||
sources = [
|
||||
"cryptotoken_private.idl",
|
||||
"i18n.json",
|
||||
"resources_private.idl",
|
||||
"tabs.json",
|
||||
|
||||
@@ -37,5 +37,9 @@
|
||||
"matches": [
|
||||
"chrome://print/*"
|
||||
]
|
||||
}]
|
||||
}],
|
||||
"cryptotokenPrivate": {
|
||||
"dependencies": ["permission:cryptotokenPrivate"],
|
||||
"contexts": ["blessed_extension"]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,5 +11,13 @@
|
||||
"extension_types": [
|
||||
"extension"
|
||||
]
|
||||
},
|
||||
"cryptotokenPrivate": {
|
||||
"channel": "stable",
|
||||
"extension_types": ["extension"],
|
||||
"location": "component",
|
||||
"allowlist": [
|
||||
"E24F1786D842E91E74C27929B0B3715A4689A473" // Cryptotoken
|
||||
]
|
||||
}
|
||||
}
|
||||
63
shell/common/extensions/api/cryptotoken_private.idl
Normal file
63
shell/common/extensions/api/cryptotoken_private.idl
Normal file
@@ -0,0 +1,63 @@
|
||||
// Copyright 2014 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.
|
||||
|
||||
// <code>chrome.cryptotokenPrivate</code> API that provides hooks to Chrome to
|
||||
// be used by cryptotoken component extension.
|
||||
// <p>In the context of this API, an AppId is roughly an origin and is formally
|
||||
// defined in
|
||||
// <a href="https://fidoalliance.org/specs/fido-u2f-v1.2-ps-20170411/fido-appid-and-facets-v1.2-ps-20170411.html">
|
||||
// the FIDO spec</a></p>
|
||||
namespace cryptotokenPrivate {
|
||||
|
||||
callback BooleanCallback = void(boolean result);
|
||||
callback VoidCallback = void();
|
||||
|
||||
dictionary CanAppIdGetAttestationOptions {
|
||||
// The AppId (see definition, above) that was used in the registration
|
||||
// request and which has been authenticated by |canOriginAssertAppId|.
|
||||
DOMString appId;
|
||||
// The origin of the caller.
|
||||
DOMString origin;
|
||||
// Identifies the tab in which the registration is occuring so that any
|
||||
// permissions prompt is correctly located.
|
||||
long tabId;
|
||||
};
|
||||
|
||||
interface Functions {
|
||||
// Checks whether the origin is allowed to assert the appId, according to
|
||||
// the same origin policy defined at
|
||||
// http://fidoalliance.org/specs/fido-u2f-v1.0-ps-20141009/
|
||||
// fido-appid-and-facets-ps-20141009.html
|
||||
// |securityOrigin| is the origin as seen by the extension, and |appIdUrl|
|
||||
// is the appId being asserted by the origin.
|
||||
static void canOriginAssertAppId(DOMString securityOrigin,
|
||||
DOMString appIdUrl,
|
||||
BooleanCallback callback);
|
||||
|
||||
// Checks whether the given appId is specified in the
|
||||
// SecurityKeyPermitAttestation policy. This causes a signal to be sent to
|
||||
// the token that informs it that an individually-identifying attestation
|
||||
// certificate may be used. Without that signal, the token is required to
|
||||
// use its batch attestation certificate.
|
||||
static void isAppIdHashInEnterpriseContext(ArrayBuffer appIdHash,
|
||||
BooleanCallback callback);
|
||||
|
||||
// Checks whether the given appId may receive attestation data that
|
||||
// identifies the token. If not, the attestation from the token must be
|
||||
// substituted with a randomly generated certificate since webauthn and U2F
|
||||
// require that some attestation be provided.
|
||||
static void canAppIdGetAttestation(CanAppIdGetAttestationOptions options,
|
||||
BooleanCallback callback);
|
||||
|
||||
// Increments the WebFeature::kU2FCryptotokenRegister UseCounter for the
|
||||
// main frame associated with |tabId|.
|
||||
static void recordRegisterRequest(long tabId, long frameId,
|
||||
optional VoidCallback callback);
|
||||
|
||||
// Increments the WebFeature::kU2FCryptotokenSign UseCounter for the
|
||||
// main frame associated with |tabId|.
|
||||
static void recordSignRequest(long tabId, long frameId,
|
||||
optional VoidCallback callback);
|
||||
};
|
||||
};
|
||||
@@ -35,6 +35,7 @@ constexpr APIPermissionInfo::InitInfo permissions_to_register[] = {
|
||||
{mojom::APIPermissionID::kResourcesPrivate, "resourcesPrivate",
|
||||
APIPermissionInfo::kFlagCannotBeOptional},
|
||||
{mojom::APIPermissionID::kManagement, "management"},
|
||||
{mojom::APIPermissionID::kCryptotokenPrivate, "cryptotokenPrivate"},
|
||||
};
|
||||
base::span<const APIPermissionInfo::InitInfo> GetPermissionInfos() {
|
||||
return base::make_span(permissions_to_register);
|
||||
|
||||
Reference in New Issue
Block a user