Commit e93252ac authored by Adam Langley's avatar Adam Langley Committed by Commit Bot

webauthn: provide caBLE status updates.

Plumb though better error information (for a future change) and some
status updates. Use the status updates to visually indicate the progress
of a QR transaction.

BUG=1002262

Change-Id: I94ce3abf4accb5b28273fc5ee6a9f07386f64d0c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2511975
Commit-Queue: Adam Langley <agl@chromium.org>
Reviewed-by: default avatarMartin Kreichgauer <martinkr@google.com>
Cr-Commit-Position: refs/heads/master@{#825952}
parent eed8e4c3
...@@ -47,6 +47,8 @@ android_resources("java_resources") { ...@@ -47,6 +47,8 @@ android_resources("java_resources") {
"java/res/layout/cablev2_fcm.xml", "java/res/layout/cablev2_fcm.xml",
"java/res/layout/cablev2_qr_scan.xml", "java/res/layout/cablev2_qr_scan.xml",
"java/res/layout/cablev2_usb_attached.xml", "java/res/layout/cablev2_usb_attached.xml",
"java/res/values/attrs.xml",
"java/res/values/styles.xml",
] ]
deps = [ "//chrome/android:chrome_app_java_resources" ] deps = [ "//chrome/android:chrome_app_java_resources" ]
} }
......
...@@ -12,12 +12,15 @@ ...@@ -12,12 +12,15 @@
android:fillColor="@color/modern_grey_200" android:fillColor="@color/modern_grey_200"
android:fillType="nonZero"/> android:fillType="nonZero"/>
<path <path
android:pathData="M329.278,37.36L329.278,32.145c10.735,0 19.175,-3 25.1,-8.955 9.3,-9.36 9.325,-23.015 9.325,-23.15l5.25,-0.04c0,0.645 0,15.9 -10.815,26.82 -6.935,6.995 -16.645,10.54 -28.85,10.54z" android:pathData="m358.92,31.398v-4.363c8.982,0 16.043,-2.51 21.001,-7.493 7.781,-7.831 7.802,-19.256 7.802,-19.369l4.393,-0.033c0,0.54 0,13.303 -9.049,22.44 -5.802,5.853 -13.927,8.819 -24.138,8.819z"
android:strokeWidth="0.836685"
android:fillColor="@color/modern_grey_200" android:fillColor="@color/modern_grey_200"
android:fillType="nonZero"/> android:fillType="nonZero"/>
<path <path
android:pathData="m294.563,68.145h-5.245a40.45,40.45 0,0 1,5 -18c4.605,-8.2 14.4,-18 34.96,-18v5.215c-14.465,0 -24.685,5.17 -30.385,15.36A35.35,35.35 0,0 0,294.563 68.145Z" android:pathData="m329.875,57.155h-4.388a33.844,33.844 0,0 1,4.183 -15.06c3.853,-6.861 12.048,-15.06 29.251,-15.06v4.363c-12.103,0 -20.654,4.326 -25.423,12.851a29.577,29.577 0,0 0,-3.623 12.906z"
android:strokeWidth="0.836685"
android:fillColor="@color/google_blue_grey_500" android:fillColor="@color/google_blue_grey_500"
android:fillAlpha="1"
android:fillType="nonZero"/> android:fillType="nonZero"/>
<path <path
android:pathData="m285.609,35.639h-17.28a8.64,8.64 0,0 1,17.28 0zM203.784,55.404h20v4h-20z" android:pathData="m285.609,35.639h-17.28a8.64,8.64 0,0 1,17.28 0zM203.784,55.404h20v4h-20z"
...@@ -55,7 +58,7 @@ ...@@ -55,7 +58,7 @@
android:pathData="M39.297,23.65L69.526,23.65A8.613,8.613 0,0 1,78.139 32.263L78.139,100.309A8.613,8.613 0,0 1,69.526 108.923L39.297,108.923A8.613,8.613 0,0 1,30.684 100.309L30.684,32.263A8.613,8.613 0,0 1,39.297 23.65z" android:pathData="M39.297,23.65L69.526,23.65A8.613,8.613 0,0 1,78.139 32.263L78.139,100.309A8.613,8.613 0,0 1,69.526 108.923L39.297,108.923A8.613,8.613 0,0 1,30.684 100.309L30.684,32.263A8.613,8.613 0,0 1,39.297 23.65z"
android:strokeAlpha="1" android:strokeAlpha="1"
android:strokeWidth="1.368" android:strokeWidth="1.368"
android:strokeColor="@color/modern_grey_500" android:strokeColor="?attr/phone_stroke"
android:strokeLineCap="round"/> android:strokeLineCap="round"/>
<path <path
android:pathData="M84.304,41.552m-18.974,0a18.974,18.974 0,1 1,37.948 0a18.974,18.974 0,1 1,-37.948 0" android:pathData="M84.304,41.552m-18.974,0a18.974,18.974 0,1 1,37.948 0a18.974,18.974 0,1 1,-37.948 0"
...@@ -72,9 +75,9 @@ ...@@ -72,9 +75,9 @@
android:fillAlpha="1" android:fillAlpha="1"
android:strokeLineCap="round"/> android:strokeLineCap="round"/>
<path <path
android:pathData="m370.758,33.052c-2.393,0 -4.318,1.926 -4.318,4.318v59.451c0,0.185 0.03,0.362 0.053,0.541h90.072c0.022,-0.179 0.055,-0.356 0.055,-0.541L456.619,37.37c0,-2.393 -1.926,-4.318 -4.318,-4.318z" android:pathData="m370.758,33.052c-2.393,0 -4.318,1.926 -4.318,4.318v59.451c0,0.185 0.03,0.362 0.053,0.541h90.072c0.022,-0.179 0.055,-0.356 0.055,-0.541V37.37c0,-2.393 -1.926,-4.318 -4.318,-4.318z"
android:strokeWidth="1.368" android:strokeWidth="1.368"
android:strokeColor="@color/modern_grey_500" android:strokeColor="?attr/laptop_stroke"
android:fillAlpha="1" android:fillAlpha="1"
android:strokeLineCap="round"/> android:strokeLineCap="round"/>
<path <path
...@@ -82,7 +85,7 @@ ...@@ -82,7 +85,7 @@
android:strokeAlpha="1" android:strokeAlpha="1"
android:strokeLineJoin="miter" android:strokeLineJoin="miter"
android:strokeWidth="1.368" android:strokeWidth="1.368"
android:strokeColor="@color/modern_grey_500" android:strokeColor="?attr/laptop_stroke"
android:fillType="evenOdd" android:fillType="evenOdd"
android:strokeLineCap="butt"/> android:strokeLineCap="butt"/>
<path <path
...@@ -91,4 +94,22 @@ ...@@ -91,4 +94,22 @@
android:strokeWidth="1.92357" android:strokeWidth="1.92357"
android:strokeColor="@color/modern_grey_500" android:strokeColor="@color/modern_grey_500"
android:strokeLineCap="round"/> android:strokeLineCap="round"/>
<path
android:pathData="M80.268,67.561H209.122"
android:strokeAlpha="?attr/link1_alpha"
android:strokeLineJoin="miter"
android:strokeWidth="2.26772"
android:strokeColor="@color/google_green_600"
android:fillType="evenOdd"
android:fillAlpha="0"
android:strokeLineCap="round"/>
<path
android:pathData="m260.684,67.561 l103.061,0"
android:strokeAlpha="?attr/link2_alpha"
android:strokeLineJoin="miter"
android:strokeWidth="2.26772"
android:strokeColor="@color/google_green_600"
android:fillType="evenOdd"
android:fillAlpha="0"
android:strokeLineCap="round"/>
</vector> </vector>
...@@ -13,8 +13,7 @@ ...@@ -13,8 +13,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="100dp" android:layout_height="100dp"
android:layout_marginBottom="24dp" android:layout_marginBottom="24dp"
android:background ="@color/modern_grey_50" android:background ="@color/modern_grey_50" />
android:src="@drawable/header" />
<LinearLayout <LinearLayout
android:id="@+id/qr_scan" android:id="@+id/qr_scan"
......
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="header">
<attr name="phone_stroke" format="color" />
<attr name="laptop_stroke" format="color" />
<attr name="link1_alpha" format="float" />
<attr name="link2_alpha" format="float" />
</declare-styleable>
</resources>
<resources>
<style name="idle">
<item name="phone_stroke">@color/modern_grey_500</item>
<item name="laptop_stroke">@color/modern_grey_500</item>
<item name="link1_alpha">0</item>
<item name="link2_alpha">0</item>
</style>
<style name="step1">
<item name="phone_stroke">@color/modern_blue_800</item>
<item name="laptop_stroke">@color/modern_grey_500</item>
<item name="link1_alpha">0</item>
<item name="link2_alpha">0</item>
</style>
<style name="step2">
<item name="phone_stroke">@color/modern_blue_800</item>
<item name="laptop_stroke">@color/modern_grey_500</item>
<item name="link1_alpha">1</item>
<item name="link2_alpha">0</item>
</style>
<style name="step3">
<item name="phone_stroke">@color/modern_blue_800</item>
<item name="laptop_stroke">@color/modern_grey_500</item>
<item name="link1_alpha">1</item>
<item name="link2_alpha">1</item>
</style>
<style name="step4">
<item name="phone_stroke">@color/modern_blue_800</item>
<item name="laptop_stroke">@color/modern_blue_800</item>
<item name="link1_alpha">1</item>
<item name="link2_alpha">1</item>
</style>
</resources>
...@@ -104,6 +104,9 @@ class CableAuthenticator { ...@@ -104,6 +104,9 @@ class CableAuthenticator {
void onAuthenticatorResult(Result result); void onAuthenticatorResult(Result result);
// Invoked when the authenticator has finished. The UI should be dismissed at this point. // Invoked when the authenticator has finished. The UI should be dismissed at this point.
void onComplete(); void onComplete();
// Called when an informative status update is available. The argument has the same values
// as the Status enum from v2_authenticator.h.
void onStatus(int code);
} }
public CableAuthenticator(Context context, CableAuthenticatorUI ui, long networkContext, public CableAuthenticator(Context context, CableAuthenticatorUI ui, long networkContext,
...@@ -162,6 +165,13 @@ class CableAuthenticator { ...@@ -162,6 +165,13 @@ class CableAuthenticator {
// Calls from native code. // Calls from native code.
// Called when an informative status update is available. The argument has the same values
// as the Status enum from v2_authenticator.h.
@CalledByNative
public void onStatus(int code) {
mCallback.onStatus(code);
}
@CalledByNative @CalledByNative
public static BLEAdvert newBLEAdvert(byte[] payload) { public static BLEAdvert newBLEAdvert(byte[] payload) {
return new BLEAdvert(payload); return new BLEAdvert(payload);
......
...@@ -10,15 +10,19 @@ import android.app.Activity; ...@@ -10,15 +10,19 @@ import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.hardware.usb.UsbAccessory; import android.hardware.usb.UsbAccessory;
import android.hardware.usb.UsbManager; import android.hardware.usb.UsbManager;
import android.os.Bundle; import android.os.Bundle;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.View.OnClickListener; import android.view.View.OnClickListener;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import androidx.core.content.res.ResourcesCompat;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import org.chromium.ui.base.ActivityAndroidPermissionDelegate; import org.chromium.ui.base.ActivityAndroidPermissionDelegate;
...@@ -41,6 +45,7 @@ public class CableAuthenticatorUI extends Fragment ...@@ -41,6 +45,7 @@ public class CableAuthenticatorUI extends Fragment
private AndroidPermissionDelegate mPermissionDelegate; private AndroidPermissionDelegate mPermissionDelegate;
private CableAuthenticator mAuthenticator; private CableAuthenticator mAuthenticator;
private LinearLayout mQRButton; private LinearLayout mQRButton;
private ImageView mHeader;
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
...@@ -94,6 +99,9 @@ public class CableAuthenticatorUI extends Fragment ...@@ -94,6 +99,9 @@ public class CableAuthenticatorUI extends Fragment
mQRButton = v.findViewById(R.id.qr_scan); mQRButton = v.findViewById(R.id.qr_scan);
mQRButton.setOnClickListener(this); mQRButton.setOnClickListener(this);
mHeader = v.findViewById(R.id.qr_image);
setHeader(R.style.idle);
return v; return v;
} }
...@@ -101,6 +109,18 @@ public class CableAuthenticatorUI extends Fragment ...@@ -101,6 +109,18 @@ public class CableAuthenticatorUI extends Fragment
return null; return null;
} }
/**
* Updates the header image to be shown in a new "style". The Android
* style system is used to make certain elements appear as a QR handshake
* progresses.
*/
private void setHeader(int style) {
ContextThemeWrapper theme = new ContextThemeWrapper(getContext(), style);
Drawable drawable =
ResourcesCompat.getDrawable(getResources(), R.drawable.header, theme.getTheme());
mHeader.setImageDrawable(drawable);
}
/** /**
* Called when the button to scan a QR code is pressed. * Called when the button to scan a QR code is pressed.
*/ */
...@@ -135,9 +155,28 @@ public class CableAuthenticatorUI extends Fragment ...@@ -135,9 +155,28 @@ public class CableAuthenticatorUI extends Fragment
@Override @Override
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
public void onQRCode(String value) { public void onQRCode(String value) {
setHeader(R.style.step1);
mAuthenticator.onQRCode(value); mAuthenticator.onQRCode(value);
} }
@Override
public void onStatus(int code) {
if (mMode != Mode.QR) {
// In FCM mode, the handshake is done before the UI appears. For
// USB everything should happen immediately.
return;
}
// These values must match up with the Status enum in v2_authenticator.h
if (code == 1) {
setHeader(R.style.step2);
} else if (code == 2) {
setHeader(R.style.step3);
} else if (code == 3) {
setHeader(R.style.step4);
}
}
/** /**
* Called when camera permission has been requested and the user has resolved the permission * Called when camera permission has been requested and the user has resolved the permission
* request. * request.
......
...@@ -235,7 +235,18 @@ class AndroidPlatform : public device::cablev2::authenticator::Platform { ...@@ -235,7 +235,18 @@ class AndroidPlatform : public device::cablev2::authenticator::Platform {
NeedInteractive(); NeedInteractive();
} }
void OnCompleted(bool success) override { void OnStatus(Status status) override {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!cable_authenticator_) {
return;
}
Java_CableAuthenticator_onStatus(env_, cable_authenticator_,
static_cast<int>(status));
}
void OnCompleted(base::Optional<Error> maybe_error) override {
// The transaction might fail before interactive mode, thus // The transaction might fail before interactive mode, thus
// |cable_authenticator_| may be empty. // |cable_authenticator_| may be empty.
if (cable_authenticator_) { if (cable_authenticator_) {
...@@ -357,9 +368,8 @@ class USBTransport : public device::cablev2::authenticator::Transport { ...@@ -357,9 +368,8 @@ class USBTransport : public device::cablev2::authenticator::Transport {
// Transport: // Transport:
void StartReading( void StartReading(
base::RepeatingCallback<void(base::Optional<std::vector<uint8_t>>)> base::RepeatingCallback<void(Update)> update_callback) override {
read_callback) override { callback_ = update_callback;
callback_ = read_callback;
Java_USBHandler_startReading(env_, usb_device_); Java_USBHandler_startReading(env_, usb_device_);
} }
...@@ -370,7 +380,7 @@ class USBTransport : public device::cablev2::authenticator::Transport { ...@@ -370,7 +380,7 @@ class USBTransport : public device::cablev2::authenticator::Transport {
private: private:
void OnData(base::Optional<base::span<const uint8_t>> data) { void OnData(base::Optional<base::span<const uint8_t>> data) {
if (!data) { if (!data) {
callback_.Run(base::nullopt); callback_.Run(Disconnected::kDisconnected);
} else { } else {
callback_.Run(device::fido_parsing_utils::Materialize(*data)); callback_.Run(device::fido_parsing_utils::Materialize(*data));
} }
...@@ -378,7 +388,7 @@ class USBTransport : public device::cablev2::authenticator::Transport { ...@@ -378,7 +388,7 @@ class USBTransport : public device::cablev2::authenticator::Transport {
JNIEnv* const env_; JNIEnv* const env_;
const ScopedJavaGlobalRef<jobject> usb_device_; const ScopedJavaGlobalRef<jobject> usb_device_;
base::RepeatingCallback<void(base::Optional<std::vector<uint8_t>>)> callback_; base::RepeatingCallback<void(Update)> callback_;
base::WeakPtrFactory<USBTransport> weak_factory_{this}; base::WeakPtrFactory<USBTransport> weak_factory_{this};
}; };
......
...@@ -283,12 +283,11 @@ class TunnelTransport : public Transport { ...@@ -283,12 +283,11 @@ class TunnelTransport : public Transport {
// Transport: // Transport:
void StartReading( void StartReading(
base::RepeatingCallback<void(base::Optional<std::vector<uint8_t>>)> base::RepeatingCallback<void(Update)> update_callback) override {
read_callback) override {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!read_callback_); DCHECK(!update_callback_);
read_callback_ = std::move(read_callback); update_callback_ = std::move(update_callback);
network_context_->CreateWebSocket( network_context_->CreateWebSocket(
target_, {device::kCableWebSocketProtocol}, net::SiteForCookies(), target_, {device::kCableWebSocketProtocol}, net::SiteForCookies(),
...@@ -336,7 +335,7 @@ class TunnelTransport : public Transport { ...@@ -336,7 +335,7 @@ class TunnelTransport : public Transport {
if (!ok) { if (!ok) {
FIDO_LOG(ERROR) << "Failed to connect to tunnel server"; FIDO_LOG(ERROR) << "Failed to connect to tunnel server";
read_callback_.Run(base::nullopt); update_callback_.Run(Platform::Error::TUNNEL_SERVER_CONNECT_FAILED);
return; return;
} }
...@@ -363,6 +362,8 @@ class TunnelTransport : public Transport { ...@@ -363,6 +362,8 @@ class TunnelTransport : public Transport {
std::vector<uint8_t> msg = std::vector<uint8_t> msg =
handshaker_->BuildInitialMessage(BuildGetInfoResponse()); handshaker_->BuildInitialMessage(BuildGetInfoResponse());
websocket_client_->Write(msg); websocket_client_->Write(msg);
update_callback_.Run(Platform::Status::TUNNEL_SERVER_CONNECT);
} }
void OnTunnelData(base::Optional<base::span<const uint8_t>> msg) { void OnTunnelData(base::Optional<base::span<const uint8_t>> msg) {
...@@ -370,7 +371,7 @@ class TunnelTransport : public Transport { ...@@ -370,7 +371,7 @@ class TunnelTransport : public Transport {
if (!msg) { if (!msg) {
FIDO_LOG(DEBUG) << "WebSocket tunnel closed"; FIDO_LOG(DEBUG) << "WebSocket tunnel closed";
read_callback_.Run(base::nullopt); update_callback_.Run(Disconnected::kDisconnected);
return; return;
} }
...@@ -383,10 +384,11 @@ class TunnelTransport : public Transport { ...@@ -383,10 +384,11 @@ class TunnelTransport : public Transport {
handshaker_.reset(); handshaker_.reset();
if (!result) { if (!result) {
FIDO_LOG(ERROR) << "caBLE handshake failure"; FIDO_LOG(ERROR) << "caBLE handshake failure";
read_callback_.Run(base::nullopt); update_callback_.Run(Platform::Error::HANDSHAKE_FAILED);
return; return;
} }
FIDO_LOG(DEBUG) << "caBLE handshake complete"; FIDO_LOG(DEBUG) << "caBLE handshake complete";
update_callback_.Run(Platform::Status::HANDSHAKE_COMPLETE);
crypter_ = std::move(result->first); crypter_ = std::move(result->first);
if (state_ == State::kConnected) { if (state_ == State::kConnected) {
...@@ -409,11 +411,15 @@ class TunnelTransport : public Transport { ...@@ -409,11 +411,15 @@ class TunnelTransport : public Transport {
std::vector<uint8_t> plaintext; std::vector<uint8_t> plaintext;
if (!crypter_->Decrypt(*msg, &plaintext)) { if (!crypter_->Decrypt(*msg, &plaintext)) {
FIDO_LOG(ERROR) << "failed to decrypt caBLE message"; FIDO_LOG(ERROR) << "failed to decrypt caBLE message";
read_callback_.Run(base::nullopt); update_callback_.Run(Platform::Error::DECRYPT_FAILURE);
return; return;
} }
read_callback_.Run(plaintext); if (first_message_) {
update_callback_.Run(Platform::Status::REQUEST_RECEIVED);
first_message_ = false;
}
update_callback_.Run(std::move(plaintext));
break; break;
} }
...@@ -450,8 +456,8 @@ class TunnelTransport : public Transport { ...@@ -450,8 +456,8 @@ class TunnelTransport : public Transport {
bssl::UniquePtr<EC_KEY> local_identity_; bssl::UniquePtr<EC_KEY> local_identity_;
GURL target_; GURL target_;
std::unique_ptr<Platform::BLEAdvert> ble_advert_; std::unique_ptr<Platform::BLEAdvert> ble_advert_;
base::RepeatingCallback<void(base::Optional<std::vector<uint8_t>>)> base::RepeatingCallback<void(Update)> update_callback_;
read_callback_; bool first_message_ = true;
SEQUENCE_CHECKER(sequence_checker_); SEQUENCE_CHECKER(sequence_checker_);
}; };
...@@ -461,25 +467,34 @@ class CTAP2Processor : public Transaction { ...@@ -461,25 +467,34 @@ class CTAP2Processor : public Transaction {
CTAP2Processor(std::unique_ptr<Transport> transport, CTAP2Processor(std::unique_ptr<Transport> transport,
std::unique_ptr<Platform> platform) std::unique_ptr<Platform> platform)
: transport_(std::move(transport)), platform_(std::move(platform)) { : transport_(std::move(transport)), platform_(std::move(platform)) {
transport_->StartReading( transport_->StartReading(base::BindRepeating(
base::BindRepeating(&CTAP2Processor::OnData, base::Unretained(this))); &CTAP2Processor::OnTransportUpdate, base::Unretained(this)));
} }
private: private:
void OnData(base::Optional<std::vector<uint8_t>> msg) { void OnTransportUpdate(Transport::Update update) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!msg) { if (auto* error = absl::get_if<Platform::Error>(&update)) {
FIDO_LOG(ERROR) << "Closing transaction due to transport EOF"; platform_->OnCompleted(*error);
platform_->OnCompleted(transaction_done_); return;
} else if (auto* status = absl::get_if<Platform::Status>(&update)) {
platform_->OnStatus(*status);
return;
} else if (absl::get_if<Transport::Disconnected>(&update)) {
base::Optional<Platform::Error> maybe_error;
if (!transaction_done_) {
maybe_error = Platform::Error::UNEXPECTED_EOF;
}
platform_->OnCompleted(maybe_error);
return; return;
} }
base::Optional<std::vector<uint8_t>> response = ProcessCTAPMessage(*msg); std::vector<uint8_t>& msg = absl::get<std::vector<uint8_t>>(update);
base::Optional<std::vector<uint8_t>> response = ProcessCTAPMessage(msg);
if (!response) { if (!response) {
// Fatal error. // TODO(agl): expose more error information from |ProcessCTAPMessage|.
// TODO: need to signal this to the UI. platform_->OnCompleted(Platform::Error::INVALID_CTAP);
platform_->OnCompleted(false);
return; return;
} }
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "device/fido/cable/v2_constants.h" #include "device/fido/cable/v2_constants.h"
#include "device/fido/fido_constants.h" #include "device/fido/fido_constants.h"
#include "services/network/public/mojom/network_context.mojom-forward.h" #include "services/network/public/mojom/network_context.mojom-forward.h"
#include "third_party/abseil-cpp/absl/types/variant.h"
namespace device { namespace device {
namespace cablev2 { namespace cablev2 {
...@@ -35,6 +36,23 @@ class Platform { ...@@ -35,6 +36,23 @@ class Platform {
virtual ~Platform(); virtual ~Platform();
enum class Status {
TUNNEL_SERVER_CONNECT = 1,
HANDSHAKE_COMPLETE = 2,
REQUEST_RECEIVED = 3,
};
enum class Error {
UNEXPECTED_EOF = 100,
TUNNEL_SERVER_CONNECT_FAILED = 101,
HANDSHAKE_FAILED = 102,
DECRYPT_FAILURE = 103,
INVALID_CBOR = 104,
INVALID_CTAP = 105,
UNKNOWN_COMMAND = 106,
INTERNAL_ERROR = 107,
};
using MakeCredentialCallback = using MakeCredentialCallback =
base::OnceCallback<void(uint32_t status, base::OnceCallback<void(uint32_t status,
base::span<const uint8_t> client_data_json, base::span<const uint8_t> client_data_json,
...@@ -82,10 +100,13 @@ class Platform { ...@@ -82,10 +100,13 @@ class Platform {
virtual void GetAssertion(std::unique_ptr<GetAssertionParams> params) = 0; virtual void GetAssertion(std::unique_ptr<GetAssertionParams> params) = 0;
// OnStatus is called when a new informative status is available.
virtual void OnStatus(Status) = 0;
// OnCompleted is called when the transaction has completed. Note that calling // OnCompleted is called when the transaction has completed. Note that calling
// this may result in the |Transaction| that owns this |Platform| being // this may result in the |Transaction| that owns this |Platform| being
// deleted. // deleted.
virtual void OnCompleted(bool success) = 0; virtual void OnCompleted(base::Optional<Error>) = 0;
virtual std::unique_ptr<BLEAdvert> SendBLEAdvert( virtual std::unique_ptr<BLEAdvert> SendBLEAdvert(
base::span<const uint8_t, kAdvertSize> payload) = 0; base::span<const uint8_t, kAdvertSize> payload) = 0;
...@@ -95,13 +116,23 @@ class Platform { ...@@ -95,13 +116,23 @@ class Platform {
// The framing of messages must be preserved. // The framing of messages must be preserved.
class Transport { class Transport {
public: public:
// Disconnected is a fresh type in order to be distinguishable in |Update|.
enum class Disconnected { kDisconnected = 200 };
// Update is a sum type of all the possible signals that a transport can
// report. The first element is a message from the peer. |Disconnected| is
// handled separately because it's context dependent whether that is an error
// or not.
using Update = absl::variant<std::vector<uint8_t>,
Platform::Error,
Platform::Status,
Disconnected>;
virtual ~Transport(); virtual ~Transport();
// StartReading requests that the given callback be called whenever a message // StartReading requests that the given callback be called whenever a message
// arrives from the peer. // arrives from the peer, an error occurs, or the status of the link changes.
virtual void StartReading( virtual void StartReading(
base::RepeatingCallback<void(base::Optional<std::vector<uint8_t>>)> base::RepeatingCallback<void(Update)> update_callback) = 0;
read_callback) = 0;
virtual void Write(std::vector<uint8_t> data) = 0; virtual void Write(std::vector<uint8_t> data) = 0;
}; };
......
...@@ -378,7 +378,8 @@ class TestPlatform : public authenticator::Platform { ...@@ -378,7 +378,8 @@ class TestPlatform : public authenticator::Platform {
NOTREACHED(); NOTREACHED();
} }
void OnCompleted(bool success) override {} void OnStatus(Status status) override {}
void OnCompleted(base::Optional<Error> maybe_error) override {}
std::unique_ptr<authenticator::Platform::BLEAdvert> SendBLEAdvert( std::unique_ptr<authenticator::Platform::BLEAdvert> SendBLEAdvert(
base::span<const uint8_t, kAdvertSize> payload) override { base::span<const uint8_t, kAdvertSize> payload) override {
......
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