Commit 27190349 authored by Nina Satragno's avatar Nina Satragno Committed by Commit Bot

[webauthn] Add WebAuthn DevTools Domain.

Add a DevTools Domain that allows enabling and disabling the WebAuthn Virtual
Authenticator Environment. Eventually the domain will have a set of methods to
add and interact with authenticators.

This patch also removes a race condition from the
devtools/agents-enable-disable.js web test that was made apparent by adding this
domain. Domains' `.disable` methods are no longer assumed to be finish in the
same order as their `.enable` methods.

For an overview of the overall design, please see
https://docs.google.com/document/d/1bp2cMgjm2HSpvL9-WsJoIQMsBi1oKGQY6CvWD-9WmIQ/edit?usp=sharing

Bug: 922572
Change-Id: Id43c184e5830de72736410049fdacba9a965a6d3
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1617550
Commit-Queue: Nina Satragno <nsatragno@chromium.org>
Reviewed-by: default avatarAndrey Kosyakov <caseq@chromium.org>
Reviewed-by: default avatarKim Paulhamus <kpaulhamus@chromium.org>
Reviewed-by: default avatarAlexei Filippov <alph@chromium.org>
Cr-Commit-Position: refs/heads/master@{#664392}
parent 31c95bcd
......@@ -2496,9 +2496,15 @@ jumbo_source_set("browser") {
} else {
# Not Android.
sources += [
# The WebAuthn devtools protocol API is not supported in Android yet.
"$target_gen_dir/devtools/protocol/web_authn.cc",
"$target_gen_dir/devtools/protocol/web_authn.h",
# Devtools frontend not included in Android
"devtools/devtools_frontend_host_impl.cc",
"devtools/devtools_frontend_host_impl.h",
"devtools/protocol/webauthn_handler.cc",
"devtools/protocol/webauthn_handler.h",
"host_zoom_level_context.cc",
"host_zoom_level_context.h",
"host_zoom_map_impl.cc",
......
......@@ -123,6 +123,8 @@ inspector_protocol_generate("protocol_sources") {
"protocol/tethering.h",
"protocol/tracing.cc",
"protocol/tracing.h",
"protocol/web_authn.cc",
"protocol/web_authn.h",
]
}
......
// Copyright 2019 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 "content/browser/devtools/protocol/webauthn_handler.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/webauth/authenticator_environment_impl.h"
namespace content {
namespace protocol {
WebAuthnHandler::WebAuthnHandler()
: DevToolsDomainHandler(WebAuthn::Metainfo::domainName) {}
WebAuthnHandler::~WebAuthnHandler() = default;
void WebAuthnHandler::SetRenderer(int process_host_id,
RenderFrameHostImpl* frame_host) {
frame_host_ = frame_host;
}
void WebAuthnHandler::Wire(UberDispatcher* dispatcher) {
WebAuthn::Dispatcher::wire(dispatcher, this);
}
Response WebAuthnHandler::Enable() {
AuthenticatorEnvironmentImpl::GetInstance()->EnableVirtualAuthenticatorFor(
frame_host_);
return Response::OK();
}
Response WebAuthnHandler::Disable() {
AuthenticatorEnvironmentImpl::GetInstance()->DisableVirtualAuthenticatorFor(
frame_host_);
return Response::OK();
}
} // namespace protocol
} // namespace content
// Copyright 2019 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 CONTENT_BROWSER_DEVTOOLS_PROTOCOL_WEBAUTHN_HANDLER_H_
#define CONTENT_BROWSER_DEVTOOLS_PROTOCOL_WEBAUTHN_HANDLER_H_
#include "base/macros.h"
#include "content/browser/devtools/protocol/devtools_domain_handler.h"
#include "content/browser/devtools/protocol/web_authn.h"
namespace content {
namespace protocol {
class WebAuthnHandler : public DevToolsDomainHandler, public WebAuthn::Backend {
public:
WebAuthnHandler();
~WebAuthnHandler() override;
// DevToolsDomainHandler:
void SetRenderer(int process_host_id,
RenderFrameHostImpl* frame_host) override;
void Wire(UberDispatcher* dispatcher) override;
// WebAuthn::Backend
Response Enable() override;
Response Disable() override;
private:
RenderFrameHostImpl* frame_host_;
DISALLOW_COPY_AND_ASSIGN(WebAuthnHandler);
};
} // namespace protocol
} // namespace content
#endif // CONTENT_BROWSER_DEVTOOLS_PROTOCOL_WEBAUTHN_HANDLER_H_
......@@ -99,6 +99,10 @@
{
"domain": "Fetch",
"async": ["enable", "continueRequest", "failRequest", "fulfillRequest", "continueWithAuth", "getResponseBody", "takeResponseBodyAsStream"]
},
{
"domain": "WebAuthn",
"include": ["enable", "disable"]
}
]
},
......
......@@ -65,6 +65,8 @@
#include "content/browser/renderer_host/compositor_impl_android.h"
#include "content/public/browser/render_widget_host_view.h"
#include "services/device/public/mojom/wake_lock_context.mojom.h"
#else
#include "content/browser/devtools/protocol/webauthn_handler.h"
#endif
namespace content {
......@@ -323,6 +325,9 @@ bool RenderFrameDevToolsAgentHost::AttachSession(DevToolsSession* session) {
session->AddHandler(std::make_unique<protocol::TracingHandler>(
frame_tree_node_, GetIOContext()));
}
#if !defined(OS_ANDROID)
session->AddHandler(std::make_unique<protocol::WebAuthnHandler>());
#endif // !defined(OS_ANDROID)
if (sessions().empty()) {
bool use_video_capture_api = true;
......
......@@ -6794,3 +6794,13 @@ experimental domain WebAudio
event contextChanged
parameters
BaseAudioContext context
# This domain allows configuring virtual authenticators to test the WebAuthn
# API.
experimental domain WebAuthn
# Enable the WebAuthn domain and start intercepting credential storage and
# retrieval with a virtual authenticator.
command enable
# Disable the WebAuthn domain.
command disable
......@@ -19,6 +19,7 @@ Performance.disable finished successfully
Profiler.disable finished successfully
Runtime.disable finished successfully
WebAudio.disable finished successfully
WebAuthn.disable finished successfully
Accessibility.enable finished successfully
Accessibility.disable finished successfully
......@@ -77,3 +78,6 @@ Runtime.disable finished successfully
WebAudio.enable finished successfully
WebAudio.disable finished successfully
WebAuthn.enable finished successfully
WebAuthn.disable finished successfully
......@@ -5,21 +5,13 @@
(async function() {
TestRunner.addResult(`Test that each agent could be enabled/disabled separately.\n`);
var requestsSent = 0;
var responsesReceived = 0;
function finishWhenDone(agentName, action, errorString) {
function printResult(agentName, action, errorString) {
if (action === 'enable')
TestRunner.addResult('');
if (errorString)
TestRunner.addResult(agentName + '.' + action + ' finished with error ' + errorString);
else
TestRunner.addResult(agentName + '.' + action + ' finished successfully');
++responsesReceived;
if (responsesReceived === requestsSent)
TestRunner.completeTest();
}
var targets = SDK.targetManager.targets();
......@@ -39,24 +31,25 @@
.sort();
async function disableAgent(agentName) {
++requestsSent;
var agent = target._agents[agentName];
var response = await agent.invoke_disable({});
finishWhenDone(agentName, 'disable', response[Protocol.Error]);
printResult(agentName, 'disable', response[Protocol.Error]);
}
async function enableAgent(agentName) {
++requestsSent;
var agent = target._agents[agentName];
var response = await agent.invoke_enable({});
finishWhenDone(agentName, 'enable', response[Protocol.Error]);
printResult(agentName, 'enable', response[Protocol.Error]);
}
agentNames.forEach(disableAgent);
for (agentName of agentNames)
await disableAgent(agentName);
agentNames.forEach(agentName => {
enableAgent(agentName);
disableAgent(agentName);
});
for (agentName of agentNames) {
await enableAgent(agentName);
await disableAgent(agentName);
}
}
TestRunner.completeTest();
})();
<!DOCTYPE html>
<html lang="en">
<head>
<script>
async function registerCredential() {
try {
await navigator.credentials.create({
publicKey: {
authenticatorSelection: {
requireResidentKey: false,
},
rp: {
id: 'devtools.test',
name: 'DevTools Test',
},
challenge: Uint8Array.from('challenge'),
pubKeyCredParams: [
{type: 'public-key', alg: -7},
],
user: {
name: 'name',
displayName: 'displayName',
id: Uint8Array.from([1]),
}
}});
return "OK";
} catch (error) {
return error.toString();
}
}
</script>
</head>
<body>
</body>
</html>
Check that calling WebAuthn.enable starts the WebAuthn virtual authenticator environment.
OK
(async function(testRunner) {
var {page, session, dp} =
await testRunner.startBlank(
"Check that calling WebAuthn.enable starts the WebAuthn virtual " +
"authenticator environment.");
await page.navigate(
"https://devtools.test:8443/inspector-protocol/webauthn/resources/create-credential-test.https.html");
await dp.WebAuthn.enable();
const result = await session.evaluateAsync("registerCredential()");
testRunner.log(result);
testRunner.completeTest();
})
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