Commit 0ce14400 authored by Jun Choi's avatar Jun Choi Committed by Commit Bot

Implement BleDeviceSelectionView and model

Implement UI view and model that renders available BLE
security keys to the WebAuthN UI.

Bug: 877344
Change-Id: Ie44c848799cf5a637f9c048d2e9ec292ddf845fc
Reviewed-on: https://chromium-review.googlesource.com/c/1257789
Commit-Queue: Jun Choi <hongjunchoi@chromium.org>
Reviewed-by: default avatarBalazs Engedy <engedy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#603226}
parent 4c1b499d
......@@ -1638,6 +1638,7 @@ jumbo_split_static_library("browser") {
"vr/vr_tab_helper.h",
"web_data_service_factory.cc",
"web_data_service_factory.h",
"webauthn/authenticator_list_observer.h",
"webauthn/authenticator_reference.cc",
"webauthn/authenticator_reference.h",
"webauthn/authenticator_request_dialog_model.cc",
......@@ -1647,6 +1648,8 @@ jumbo_split_static_library("browser") {
"webauthn/authenticator_transport.h",
"webauthn/chrome_authenticator_request_delegate.cc",
"webauthn/chrome_authenticator_request_delegate.h",
"webauthn/observable_authenticator_list.cc",
"webauthn/observable_authenticator_list.h",
"webshare/share_target_pref_helper.cc",
"webshare/share_target_pref_helper.h",
"webshare/webshare_target.cc",
......
......@@ -2809,6 +2809,8 @@ jumbo_split_static_library("ui") {
"views/webauthn/authenticator_request_sheet_view.h",
"views/webauthn/authenticator_transport_selector_sheet_view.cc",
"views/webauthn/authenticator_transport_selector_sheet_view.h",
"views/webauthn/ble_device_selection_sheet_view.cc",
"views/webauthn/ble_device_selection_sheet_view.h",
"views/webauthn/ble_pin_entry_view.cc",
"views/webauthn/ble_pin_entry_view.h",
"views/webauthn/hover_list_view.cc",
......@@ -2820,6 +2822,8 @@ jumbo_split_static_library("ui") {
"views_mode_controller.cc",
"views_mode_controller.h",
"webauthn/authenticator_request_sheet_model.h",
"webauthn/ble_device_hover_list_model.cc",
"webauthn/ble_device_hover_list_model.h",
"webauthn/hover_list_model.h",
"webauthn/other_transports_menu_model.cc",
"webauthn/other_transports_menu_model.h",
......
......@@ -123,6 +123,12 @@ AuthenticatorRequestDialogView::~AuthenticatorRequestDialogView() {
// invoked straight after, which destroys child views. views::View subclasses
// shouldn't be doing anything interesting in their destructors, so it should
// be okay to destroy the |sheet_| immediately after this line.
//
// However, as AuthenticatorRequestDialogModel is owned by |this|, and
// ObservableAuthenticatorList is owned by AuthenticatorRequestDialogModel,
// destroy all view components that might own models observing the list prior
// to destroying AuthenticatorRequestDialogModel.
RemoveAllChildViews(true /* delete_children */);
}
gfx::Size AuthenticatorRequestDialogView::CalculatePreferredSize() const {
......
// Copyright 2018 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 "chrome/browser/ui/views/webauthn/ble_device_selection_sheet_view.h"
#include <utility>
#include "chrome/browser/ui/views/webauthn/hover_list_view.h"
#include "chrome/grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/layout/layout_provider.h"
#include "ui/views/style/typography.h"
#include "ui/views/view.h"
BleDeviceSelectionSheetView::BleDeviceSelectionSheetView(
std::unique_ptr<AuthenticatorBleDeviceSelectionSheetModel> model)
: AuthenticatorRequestSheetView(std::move(model)) {}
BleDeviceSelectionSheetView::~BleDeviceSelectionSheetView() = default;
std::unique_ptr<views::View>
BleDeviceSelectionSheetView::BuildStepSpecificContent() {
auto device_selection_view = std::make_unique<views::View>();
device_selection_view->SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::kVertical, gfx::Insets(),
views::LayoutProvider::Get()->GetDistanceMetric(
views::DISTANCE_RELATED_CONTROL_VERTICAL)));
auto device_list_view =
std::make_unique<HoverListView>(std::make_unique<BleDeviceHoverListModel>(
&model()->dialog_model()->saved_authenticators(), this));
auto bottom_suggestion_label = std::make_unique<views::Label>(
l10n_util::GetStringUTF16(
IDS_WEBAUTHN_BLE_DEVICE_SELECTION_REMINDER_LABEL),
views::style::CONTEXT_LABEL, views::style::STYLE_DISABLED);
bottom_suggestion_label->SetMultiLine(true);
bottom_suggestion_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
device_selection_view->AddChildView(device_list_view.release());
device_selection_view->AddChildView(bottom_suggestion_label.release());
return device_selection_view;
}
void BleDeviceSelectionSheetView::OnItemSelected(
base::StringPiece authenticator_id) {
model()->dialog_model()->InitiatePairingDevice(authenticator_id);
}
// Copyright 2018 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 CHROME_BROWSER_UI_VIEWS_WEBAUTHN_BLE_DEVICE_SELECTION_SHEET_VIEW_H_
#define CHROME_BROWSER_UI_VIEWS_WEBAUTHN_BLE_DEVICE_SELECTION_SHEET_VIEW_H_
#include <memory>
#include "base/macros.h"
#include "chrome/browser/ui/views/webauthn/authenticator_request_sheet_view.h"
#include "chrome/browser/ui/webauthn/ble_device_hover_list_model.h"
#include "chrome/browser/ui/webauthn/sheet_models.h"
// Represents a sheet in the Web Authentication request dialog that allows the
// user to pick the Bluetooth security key to which they wish to connect to
// in order to service the Web Authentication request.
class BleDeviceSelectionSheetView : public AuthenticatorRequestSheetView,
public BleDeviceHoverListModel::Delegate {
public:
explicit BleDeviceSelectionSheetView(
std::unique_ptr<AuthenticatorBleDeviceSelectionSheetModel> model);
~BleDeviceSelectionSheetView() override;
private:
AuthenticatorBleDeviceSelectionSheetModel* model() {
return static_cast<AuthenticatorBleDeviceSelectionSheetModel*>(
AuthenticatorRequestSheetView::model());
}
// AuthenticatorRequestSheetView:
std::unique_ptr<views::View> BuildStepSpecificContent() override;
// BleDeviceHoverListModel::Delegate:
void OnItemSelected(base::StringPiece authenticator_id) override;
DISALLOW_COPY_AND_ASSIGN(BleDeviceSelectionSheetView);
};
#endif // CHROME_BROWSER_UI_VIEWS_WEBAUTHN_BLE_DEVICE_SELECTION_SHEET_VIEW_H_
......@@ -103,13 +103,10 @@ HoverListView::HoverListView(std::unique_ptr<HoverListModel> model)
views::BoxLayout::kVertical, gfx::Insets(), 0));
AddSeparatorAsChild(this);
for (size_t index = 0; index < model_->GetItemCount(); ++index) {
int item_tag = model_->GetItemTag(index);
if (model_->ShouldShowItemInView(item_tag)) {
AppendListItemView(*model_->GetItemIcon(item_tag),
for (const auto item_tag : model_->GetItemTags()) {
AppendListItemView(model_->GetItemIcon(item_tag),
model_->GetItemText(item_tag), item_tag);
}
}
if (tags_to_list_item_views_.empty() &&
model_->ShouldShowPlaceholderForEmptyList())
......@@ -119,7 +116,7 @@ HoverListView::HoverListView(std::unique_ptr<HoverListModel> model)
}
HoverListView::~HoverListView() {
model_->RemoveObserver(this);
model_->RemoveObserver();
}
void HoverListView::AppendListItemView(const gfx::VectorIcon& icon,
......@@ -139,11 +136,9 @@ void HoverListView::AppendListItemView(const gfx::VectorIcon& icon,
}
void HoverListView::CreateAndAppendPlaceholderItem() {
const auto* placeholder_item_icon = model_->GetPlaceholderIcon();
DCHECK(placeholder_item_icon);
auto placeholder_item = CreateHoverButtonForListItem(
kPlaceHolderItemTag, *placeholder_item_icon, model_->GetPlaceholderText(),
nullptr, true /* is_placeholder_item */);
kPlaceHolderItemTag, model_->GetPlaceholderIcon(),
model_->GetPlaceholderText(), nullptr, true /* is_placeholder_item */);
AddChildView(placeholder_item.get());
auto* separator = AddSeparatorAsChild(this);
placeholder_list_item_view_.emplace(
......@@ -170,7 +165,7 @@ void HoverListView::OnListItemAdded(int item_tag) {
placeholder_list_item_view_.emplace();
}
AppendListItemView(*model_->GetItemIcon(item_tag),
AppendListItemView(model_->GetItemIcon(item_tag),
model_->GetItemText(item_tag), item_tag);
// TODO(hongjunchoi): The enclosing dialog may also need to be resized,
......
......@@ -8,6 +8,7 @@
#include "chrome/browser/ui/views/webauthn/authenticator_ble_pin_entry_sheet_view.h"
#include "chrome/browser/ui/views/webauthn/authenticator_request_sheet_view.h"
#include "chrome/browser/ui/views/webauthn/authenticator_transport_selector_sheet_view.h"
#include "chrome/browser/ui/views/webauthn/ble_device_selection_sheet_view.h"
#include "chrome/browser/ui/webauthn/sheet_models.h"
#include "chrome/browser/webauthn/authenticator_request_dialog_model.h"
......@@ -93,7 +94,7 @@ std::unique_ptr<AuthenticatorRequestSheetView> CreateSheetViewForCurrentStepOf(
dialog_model));
break;
case Step::kBleDeviceSelection:
sheet_view = std::make_unique<AuthenticatorRequestSheetView>(
sheet_view = std::make_unique<BleDeviceSelectionSheetView>(
std::make_unique<AuthenticatorBleDeviceSelectionSheetModel>(
dialog_model));
break;
......
......@@ -69,12 +69,10 @@ class AuthenticatorDialogTest : public DialogBrowserTest {
model->SetCurrentStep(
AuthenticatorRequestDialogModel::Step::kBleDeviceSelection);
} else if (name == "ble_pin_entry") {
model->SetSelectedAuthenticatorForTesting(
std::make_unique<AuthenticatorReference>(
model->SetSelectedAuthenticatorForTesting(AuthenticatorReference(
"test_authenticator_id" /* authenticator_id */,
base::string16() /* authenticator_display_name */,
AuthenticatorTransport::kInternal,
false /* is_in_pairing_mode */));
AuthenticatorTransport::kInternal, false /* is_in_pairing_mode */));
model->SetCurrentStep(
AuthenticatorRequestDialogModel::Step::kBlePinEntry);
} else if (name == "ble_verifying") {
......
// Copyright 2018 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 "chrome/browser/ui/webauthn/ble_device_hover_list_model.h"
#include <algorithm>
#include <iterator>
#include <numeric>
#include <utility>
#include "chrome/browser/ui/webauthn/transport_utils.h"
#include "chrome/browser/webauthn/authenticator_transport.h"
#include "chrome/grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"
namespace {
const std::map<int, std::string>::const_iterator FindElementByValue(
const std::map<int, std::string>& item_map,
base::StringPiece value) {
return std::find_if(item_map.begin(), item_map.end(),
[value](const auto& key_value_pair) {
return key_value_pair.second == value;
});
}
bool ShouldShowItemInView(const AuthenticatorReference& authenticator) {
return authenticator.is_in_pairing_mode() &&
authenticator.transport() ==
AuthenticatorTransport::kBluetoothLowEnergy;
}
} // namespace
BleDeviceHoverListModel::BleDeviceHoverListModel(
ObservableAuthenticatorList* authenticator_list,
Delegate* delegate)
: authenticator_list_(authenticator_list), delegate_(delegate) {
int tag_counter = 0;
for (const auto& authenticator : authenticator_list_->authenticator_list()) {
authenticator_tags_.emplace(++tag_counter,
authenticator.authenticator_id());
}
authenticator_list_->SetObserver(this);
}
BleDeviceHoverListModel::~BleDeviceHoverListModel() {
authenticator_list_->RemoveObserver();
}
const AuthenticatorReference* BleDeviceHoverListModel::GetAuthenticator(
int tag) const {
auto it = authenticator_tags_.find(tag);
CHECK(it != authenticator_tags_.end());
return authenticator_list_->GetAuthenticator(it->second);
}
bool BleDeviceHoverListModel::ShouldShowPlaceholderForEmptyList() const {
return true;
}
base::string16 BleDeviceHoverListModel::GetPlaceholderText() const {
return l10n_util::GetStringUTF16(
IDS_WEBAUTHN_BLE_DEVICE_SELECTION_SEARCHING_LABEL);
}
const gfx::VectorIcon& BleDeviceHoverListModel::GetPlaceholderIcon() const {
return GetTransportVectorIcon(AuthenticatorTransport::kBluetoothLowEnergy);
}
base::string16 BleDeviceHoverListModel::GetItemText(int item_tag) const {
return GetAuthenticator(item_tag)->authenticator_display_name();
}
const gfx::VectorIcon& BleDeviceHoverListModel::GetItemIcon(
int item_tag) const {
return GetTransportVectorIcon(AuthenticatorTransport::kBluetoothLowEnergy);
}
std::vector<int> BleDeviceHoverListModel::GetItemTags() const {
std::vector<int> tag_list;
tag_list.reserve(authenticator_tags_.size());
for (const auto& item : authenticator_tags_) {
const auto* authenticator =
authenticator_list_->GetAuthenticator(item.second);
CHECK(authenticator);
if (ShouldShowItemInView(*authenticator)) {
tag_list.emplace_back(item.first);
}
}
return tag_list;
}
void BleDeviceHoverListModel::OnListItemSelected(int item_tag) {
auto authenticator_item = authenticator_tags_.find(item_tag);
CHECK(authenticator_item != authenticator_tags_.end());
delegate_->OnItemSelected(authenticator_item->second);
}
void BleDeviceHoverListModel::OnAuthenticatorAdded(
const AuthenticatorReference& authenticator) {
auto item_tag = authenticator_tags_.empty()
? 0
: (--authenticator_tags_.end())->first + 1;
authenticator_tags_.emplace(item_tag, authenticator.authenticator_id());
if (ShouldShowItemInView(authenticator) && observer())
observer()->OnListItemAdded(item_tag);
}
void BleDeviceHoverListModel::OnAuthenticatorRemoved(
const AuthenticatorReference& removed_authenticator) {
const auto& authenticator_id = removed_authenticator.authenticator_id();
auto it = FindElementByValue(authenticator_tags_, authenticator_id);
CHECK(it != authenticator_tags_.end());
const auto item_tag = it->first;
authenticator_tags_.erase(it);
if (observer() && ShouldShowItemInView(removed_authenticator))
observer()->OnListItemRemoved(item_tag);
}
void BleDeviceHoverListModel::OnAuthenticatorChanged(
const AuthenticatorReference& changed_authenticator) {
auto it = FindElementByValue(authenticator_tags_,
changed_authenticator.authenticator_id());
CHECK(it != authenticator_tags_.end());
if (observer() && ShouldShowItemInView(changed_authenticator))
observer()->OnListItemAdded(it->first);
}
// Copyright 2018 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 CHROME_BROWSER_UI_WEBAUTHN_BLE_DEVICE_HOVER_LIST_MODEL_H_
#define CHROME_BROWSER_UI_WEBAUTHN_BLE_DEVICE_HOVER_LIST_MODEL_H_
#include <map>
#include <string>
#include <vector>
#include "base/macros.h"
#include "base/strings/string16.h"
#include "chrome/browser/ui/webauthn/hover_list_model.h"
#include "chrome/browser/webauthn/authenticator_list_observer.h"
#include "chrome/browser/webauthn/observable_authenticator_list.h"
#include "ui/gfx/vector_icon_types.h"
class BleDeviceHoverListModel : public HoverListModel,
public AuthenticatorListObserver {
public:
// Interface that the client should implement to learn when the user selects
// an authenticator.
class Delegate {
public:
virtual void OnItemSelected(base::StringPiece authenticator_id) = 0;
};
// |authenticator_list_| and |delegate_| must outlive |this|, and |delegate_|
// may be nullptr.
explicit BleDeviceHoverListModel(
ObservableAuthenticatorList* authenticator_list,
Delegate* delegate);
~BleDeviceHoverListModel() override;
private:
const AuthenticatorReference* GetAuthenticator(int tag) const;
// HoverListModel:
bool ShouldShowPlaceholderForEmptyList() const override;
base::string16 GetPlaceholderText() const override;
const gfx::VectorIcon& GetPlaceholderIcon() const override;
base::string16 GetItemText(int item_tag) const override;
const gfx::VectorIcon& GetItemIcon(int item_tag) const override;
std::vector<int> GetItemTags() const override;
void OnListItemSelected(int item_tag) override;
// AuthenticatorListObserver:
void OnAuthenticatorAdded(
const AuthenticatorReference& authenticator) override;
void OnAuthenticatorRemoved(
const AuthenticatorReference& removed_authenticator) override;
// Invoked when Bluetooth authenticator already included in
// |authenticator_list_| changes from being in non-pairable state to pairable
// state.
void OnAuthenticatorChanged(
const AuthenticatorReference& changed_authenticator) override;
ObservableAuthenticatorList* const authenticator_list_;
Delegate* const delegate_; // Weak, may be nullptr.
// Map where key corresponds to the tags attached to elements in above
// |authenticator_list_| and value is the corresponding authenticator id.
// Elements in authenticator_tags_ are filtered and added to the view
// component, but the size of the list should be sync with that of
// |authenticator_list_|.
std::map<int, std::string> authenticator_tags_;
DISALLOW_COPY_AND_ASSIGN(BleDeviceHoverListModel);
};
#endif // CHROME_BROWSER_UI_WEBAUTHN_BLE_DEVICE_HOVER_LIST_MODEL_H_
......@@ -7,6 +7,8 @@
#include <stddef.h>
#include <vector>
#include "base/logging.h"
#include "base/macros.h"
#include "base/strings/string16.h"
......@@ -28,20 +30,18 @@ class HoverListModel {
virtual bool ShouldShowPlaceholderForEmptyList() const = 0;
virtual base::string16 GetPlaceholderText() const = 0;
virtual const gfx::VectorIcon* GetPlaceholderIcon() const = 0;
virtual size_t GetItemCount() const = 0;
virtual bool ShouldShowItemInView(int item_tag) const = 0;
virtual const gfx::VectorIcon& GetPlaceholderIcon() const = 0;
virtual std::vector<int> GetItemTags() const = 0;
virtual base::string16 GetItemText(int item_tag) const = 0;
virtual const gfx::VectorIcon* GetItemIcon(int item_tag) const = 0;
virtual int GetItemTag(size_t index) const = 0;
virtual const gfx::VectorIcon& GetItemIcon(int item_tag) const = 0;
virtual void OnListItemSelected(int item_tag) = 0;
void SetObserver(Observer* observer) {
DCHECK(!observer_);
observer_ = observer;
}
void RemoveObserver(Observer* observer) { observer_ = nullptr; }
void RemoveObserver() { observer_ = nullptr; }
protected:
Observer* observer() { return observer_; }
......
......@@ -491,8 +491,8 @@ gfx::ImageSkia* AuthenticatorBlePinEntrySheetModel::GetStepIllustration()
base::string16 AuthenticatorBlePinEntrySheetModel::GetStepTitle() const {
const auto& authenticator_id = dialog_model()->selected_authenticator_id();
const auto* const ble_authenticator =
dialog_model()->GetAuthenticator(authenticator_id);
const auto* ble_authenticator =
dialog_model()->saved_authenticators().GetAuthenticator(authenticator_id);
DCHECK(ble_authenticator);
return l10n_util::GetStringFUTF16(
IDS_WEBAUTHN_BLE_PIN_ENTRY_TITLE,
......
......@@ -7,6 +7,7 @@
#include <utility>
#include "chrome/browser/ui/webauthn/transport_utils.h"
#include "ui/gfx/paint_vector_icon.h"
TransportHoverListModel::TransportHoverListModel(
std::vector<AuthenticatorTransport> transport_list,
......@@ -23,16 +24,16 @@ base::string16 TransportHoverListModel::GetPlaceholderText() const {
return base::string16();
}
const gfx::VectorIcon* TransportHoverListModel::GetPlaceholderIcon() const {
return nullptr;
const gfx::VectorIcon& TransportHoverListModel::GetPlaceholderIcon() const {
return gfx::kNoneIcon;
}
size_t TransportHoverListModel::GetItemCount() const {
return transport_list_.size();
}
bool TransportHoverListModel::ShouldShowItemInView(int item_tag) const {
return true;
std::vector<int> TransportHoverListModel::GetItemTags() const {
std::vector<int> tag_list(transport_list_.size());
std::transform(
transport_list_.begin(), transport_list_.end(), tag_list.begin(),
[](const auto& transport) { return base::strict_cast<int>(transport); });
return tag_list;
}
base::string16 TransportHoverListModel::GetItemText(int item_tag) const {
......@@ -41,14 +42,9 @@ base::string16 TransportHoverListModel::GetItemText(int item_tag) const {
TransportSelectionContext::kTransportSelectionSheet);
}
const gfx::VectorIcon* TransportHoverListModel::GetItemIcon(
const gfx::VectorIcon& TransportHoverListModel::GetItemIcon(
int item_tag) const {
return &GetTransportVectorIcon(static_cast<AuthenticatorTransport>(item_tag));
}
int TransportHoverListModel::GetItemTag(size_t item_index) const {
DCHECK_GT(transport_list_.size(), item_index);
return base::strict_cast<int>(transport_list_.at(item_index));
return GetTransportVectorIcon(static_cast<AuthenticatorTransport>(item_tag));
}
void TransportHoverListModel::OnListItemSelected(int item_tag) {
......
......@@ -29,12 +29,10 @@ class TransportHoverListModel : public HoverListModel {
// HoverListModel:
bool ShouldShowPlaceholderForEmptyList() const override;
base::string16 GetPlaceholderText() const override;
const gfx::VectorIcon* GetPlaceholderIcon() const override;
size_t GetItemCount() const override;
bool ShouldShowItemInView(int item_tag) const override;
const gfx::VectorIcon& GetPlaceholderIcon() const override;
std::vector<int> GetItemTags() const override;
base::string16 GetItemText(int item_tag) const override;
const gfx::VectorIcon* GetItemIcon(int item_tag) const override;
int GetItemTag(size_t item_index) const override;
const gfx::VectorIcon& GetItemIcon(int item_tag) const override;
void OnListItemSelected(int item_tag) override;
private:
......
// Copyright 2018 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 CHROME_BROWSER_WEBAUTHN_AUTHENTICATOR_LIST_OBSERVER_H_
#define CHROME_BROWSER_WEBAUTHN_AUTHENTICATOR_LIST_OBSERVER_H_
#include "chrome/browser/webauthn/authenticator_reference.h"
// Interface to observe mutations to an ObservableAuthenticatorList.
//
// This is currently only implemented by the the BleDeviceHoverListModel that is
// used by HoverListView to visualize an ObservableAuthenticatorList.
class AuthenticatorListObserver {
public:
AuthenticatorListObserver() = default;
virtual ~AuthenticatorListObserver() = default;
virtual void OnAuthenticatorAdded(
const AuthenticatorReference& added_authenticator) = 0;
virtual void OnAuthenticatorRemoved(
const AuthenticatorReference& removed_authenticator) = 0;
virtual void OnAuthenticatorChanged(
const AuthenticatorReference& changed_authenticator) = 0;
};
#endif // CHROME_BROWSER_WEBAUTHN_AUTHENTICATOR_LIST_OBSERVER_H_
......@@ -4,6 +4,7 @@
#include "chrome/browser/webauthn/authenticator_request_dialog_model.h"
#include <iterator>
#include <utility>
#include "base/bind.h"
......@@ -185,10 +186,10 @@ void AuthenticatorRequestDialogModel::StartBleDiscovery() {
}
void AuthenticatorRequestDialogModel::InitiatePairingDevice(
const std::string& authenticator_id) {
base::StringPiece authenticator_id) {
DCHECK_EQ(current_step(), Step::kBleDeviceSelection);
CHECK(GetAuthenticator(authenticator_id));
selected_authenticator_id_ = authenticator_id;
DCHECK(saved_authenticators_.GetAuthenticator(authenticator_id));
selected_authenticator_id_ = authenticator_id.as_string();
SetCurrentStep(Step::kBlePinEntry);
}
......@@ -196,7 +197,7 @@ void AuthenticatorRequestDialogModel::FinishPairingWithPin(
const base::string16& pin) {
DCHECK_EQ(current_step(), Step::kBlePinEntry);
const auto* selected_authenticator =
GetAuthenticator(selected_authenticator_id_);
saved_authenticators_.GetAuthenticator(selected_authenticator_id_);
if (!selected_authenticator) {
// TODO(hongjunchoi): Implement an error screen for error encountered when
// pairing.
......@@ -218,7 +219,8 @@ void AuthenticatorRequestDialogModel::FinishPairingWithPin(
void AuthenticatorRequestDialogModel::OnPairingSuccess(
base::StringPiece authenticator_id) {
DCHECK_EQ(current_step(), Step::kBleVerifying);
auto* authenticator = GetAuthenticator(authenticator_id);
auto* authenticator =
saved_authenticators_.GetAuthenticator(authenticator_id);
if (authenticator)
return;
......@@ -246,19 +248,20 @@ void AuthenticatorRequestDialogModel::StartTouchIdFlow() {
SetCurrentStep(Step::kTouchId);
auto& authenticators = saved_authenticators_.authenticator_list();
auto touch_id_authenticator_it =
std::find_if(saved_authenticators_.begin(), saved_authenticators_.end(),
std::find_if(authenticators.begin(), authenticators.end(),
[](const auto& authenticator) {
return authenticator->transport() ==
return authenticator.transport() ==
device::FidoTransportProtocol::kInternal;
});
if (touch_id_authenticator_it == saved_authenticators_.end())
if (touch_id_authenticator_it == authenticators.end())
return;
static base::TimeDelta kTouchIdDispatchDelay =
base::TimeDelta::FromMilliseconds(1250);
DispatchRequestAsync(touch_id_authenticator_it->get(), kTouchIdDispatchDelay);
DispatchRequestAsync(&*touch_id_authenticator_it, kTouchIdDispatchDelay);
}
void AuthenticatorRequestDialogModel::Cancel() {
......@@ -340,29 +343,20 @@ void AuthenticatorRequestDialogModel::SetBluetoothAdapterPowerOnCallback(
void AuthenticatorRequestDialogModel::UpdateAuthenticatorReferenceId(
base::StringPiece old_authenticator_id,
std::string new_authenticator_id) {
auto it = std::find_if(
saved_authenticators_.begin(), saved_authenticators_.end(),
[old_authenticator_id](const auto& authenticator) {
return authenticator->authenticator_id() == old_authenticator_id;
});
if (it != saved_authenticators_.end())
(*it)->SetAuthenticatorId(std::move(new_authenticator_id));
saved_authenticators_.ChangeAuthenticatorId(old_authenticator_id,
std::move(new_authenticator_id));
}
void AuthenticatorRequestDialogModel::AddAuthenticator(
const device::FidoAuthenticator& authenticator) {
saved_authenticators_.emplace_back(std::make_unique<AuthenticatorReference>(
saved_authenticators_.AddAuthenticator(AuthenticatorReference(
authenticator.GetId(), authenticator.GetDisplayName(),
authenticator.AuthenticatorTransport(), authenticator.IsInPairingMode()));
}
void AuthenticatorRequestDialogModel::RemoveAuthenticator(
base::StringPiece authenticator_id) {
base::EraseIf(saved_authenticators_,
[authenticator_id](const auto& authenticator_reference) {
return authenticator_reference->authenticator_id() ==
authenticator_id;
});
saved_authenticators_.RemoveAuthenticator(authenticator_id);
}
void AuthenticatorRequestDialogModel::DispatchRequestAsync(
......@@ -386,31 +380,13 @@ void AuthenticatorRequestDialogModel::DispatchRequestAsync(
void AuthenticatorRequestDialogModel::UpdateAuthenticatorReferencePairingMode(
base::StringPiece authenticator_id,
bool is_in_pairing_mode) {
auto it = std::find_if(
saved_authenticators_.begin(), saved_authenticators_.end(),
[authenticator_id](const auto& authenticator) {
return authenticator->authenticator_id() == authenticator_id;
});
if (it != saved_authenticators_.end())
(*it)->SetIsInPairingMode(is_in_pairing_mode);
saved_authenticators_.ChangeAuthenticatorPairingMode(authenticator_id,
is_in_pairing_mode);
}
void AuthenticatorRequestDialogModel::SetSelectedAuthenticatorForTesting(
std::unique_ptr<AuthenticatorReference> test_authenticator) {
selected_authenticator_id_ = test_authenticator->authenticator_id();
saved_authenticators_.emplace_back(std::move(test_authenticator));
AuthenticatorReference test_authenticator) {
selected_authenticator_id_ = test_authenticator.authenticator_id();
saved_authenticators_.AddAuthenticator(std::move(test_authenticator));
}
AuthenticatorReference* AuthenticatorRequestDialogModel::GetAuthenticator(
base::StringPiece authenticator_id) const {
auto authenticator = std::find_if(
saved_authenticators_.begin(), saved_authenticators_.end(),
[authenticator_id](const auto& authenticator) {
return authenticator->authenticator_id() == authenticator_id;
});
if (authenticator == saved_authenticators_.end())
return nullptr;
return authenticator->get();
}
......@@ -16,6 +16,7 @@
#include "base/strings/string_piece.h"
#include "chrome/browser/webauthn/authenticator_reference.h"
#include "chrome/browser/webauthn/authenticator_transport.h"
#include "chrome/browser/webauthn/observable_authenticator_list.h"
#include "device/fido/fido_request_handler_base.h"
#include "device/fido/fido_transport_protocol.h"
......@@ -186,7 +187,7 @@ class AuthenticatorRequestDialogModel {
// Initiates pairing of the device that the user has chosen.
//
// Valid action when at step: kBleDeviceSelection.
void InitiatePairingDevice(const std::string& authenticator_id);
void InitiatePairingDevice(base::StringPiece authenticator_id);
// Finishes pairing of the previously chosen device with the |pin| code
// entered.
......@@ -267,13 +268,9 @@ class AuthenticatorRequestDialogModel {
base::StringPiece authenticator_id,
bool is_in_pairing_mode);
void SetSelectedAuthenticatorForTesting(
std::unique_ptr<AuthenticatorReference> authenticator);
void SetSelectedAuthenticatorForTesting(AuthenticatorReference authenticator);
AuthenticatorReference* GetAuthenticator(
base::StringPiece authenticator_id) const;
std::vector<std::unique_ptr<AuthenticatorReference>>& saved_authenticators() {
ObservableAuthenticatorList& saved_authenticators() {
return saved_authenticators_;
}
......@@ -303,11 +300,12 @@ class AuthenticatorRequestDialogModel {
// Transport type and id of Mac TouchId and BLE authenticators are cached so
// that the WebAuthN request for the corresponding authenticators can be
// dispatched lazily after the user interacts with the UI element.
std::vector<std::unique_ptr<AuthenticatorReference>> saved_authenticators_;
ObservableAuthenticatorList saved_authenticators_;
// Represents the id of the Bluetooth authenticator that the user is trying to
// connect to or conduct WebAuthN request to via the WebAuthN UI.
std::string selected_authenticator_id_;
RequestCallback request_callback_;
BlePairingCallback ble_pairing_callback_;
base::RepeatingClosure bluetooth_adapter_power_on_callback_;
......
......@@ -472,8 +472,7 @@ TEST_F(AuthenticatorRequestDialogModelTest,
model.SetRequestCallback(base::BindRepeating(
[](int* i, const std::string& authenticator_id) { ++(*i); },
&num_called));
model.saved_authenticators().emplace_back(
std::make_unique<AuthenticatorReference>(
model.saved_authenticators().AddAuthenticator(AuthenticatorReference(
"authenticator" /* authenticator_id */,
base::string16() /* authenticator_display_name */,
AuthenticatorTransport::kInternal, false /* is_in_pairing_mode */));
......
// Copyright 2018 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 "chrome/browser/webauthn/observable_authenticator_list.h"
#include <algorithm>
#include <utility>
#include "chrome/browser/webauthn/authenticator_list_observer.h"
ObservableAuthenticatorList::ObservableAuthenticatorList() = default;
ObservableAuthenticatorList::~ObservableAuthenticatorList() = default;
void ObservableAuthenticatorList::AddAuthenticator(
AuthenticatorReference authenticator) {
authenticator_list_.emplace_back(std::move(authenticator));
if (observer_)
observer_->OnAuthenticatorAdded(authenticator_list_.back());
}
void ObservableAuthenticatorList::RemoveAuthenticator(
base::StringPiece authenticator_id) {
auto it = GetAuthenticatorIterator(authenticator_id);
if (it == authenticator_list_.end())
return;
auto removed_authenticator = std::move(*it);
authenticator_list_.erase(it);
if (observer_)
observer_->OnAuthenticatorRemoved(removed_authenticator);
}
void ObservableAuthenticatorList::ChangeAuthenticatorId(
base::StringPiece previous_id,
std::string new_id) {
auto* authenticator = GetAuthenticator(previous_id);
if (!authenticator)
return;
if (observer_)
observer_->OnAuthenticatorRemoved(*authenticator);
authenticator->SetAuthenticatorId(std::move(new_id));
if (observer_)
observer_->OnAuthenticatorAdded(*authenticator);
}
void ObservableAuthenticatorList::ChangeAuthenticatorPairingMode(
base::StringPiece authenticator_id,
bool is_in_pairing_mode) {
auto it = GetAuthenticatorIterator(authenticator_id);
if (it == authenticator_list_.end())
return;
bool previously_in_pairing_mode = it->is_in_pairing_mode();
it->SetIsInPairingMode(is_in_pairing_mode);
// TODO(hongjunchoi): Add logic to notify view components when Bluetooth
// authenticator changes from being in pairing mode to non-pairing mode.
if (observer_ && !previously_in_pairing_mode && is_in_pairing_mode) {
observer_->OnAuthenticatorChanged(
authenticator_list_[std::distance(authenticator_list_.begin(), it)]);
}
}
AuthenticatorReference* ObservableAuthenticatorList::GetAuthenticator(
base::StringPiece authenticator_id) {
auto it = GetAuthenticatorIterator(authenticator_id);
if (it == authenticator_list_.end())
return nullptr;
return &*it;
}
void ObservableAuthenticatorList::SetObserver(
AuthenticatorListObserver* observer) {
DCHECK(!observer_);
observer_ = observer;
}
void ObservableAuthenticatorList::RemoveObserver() {
observer_ = nullptr;
}
ObservableAuthenticatorList::AuthenticatorListIterator
ObservableAuthenticatorList::GetAuthenticatorIterator(
base::StringPiece authenticator_id) {
return std::find_if(authenticator_list_.begin(), authenticator_list_.end(),
[authenticator_id](const auto& authenticator) {
return authenticator.authenticator_id() ==
authenticator_id;
});
}
// Copyright 2018 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 CHROME_BROWSER_WEBAUTHN_OBSERVABLE_AUTHENTICATOR_LIST_H_
#define CHROME_BROWSER_WEBAUTHN_OBSERVABLE_AUTHENTICATOR_LIST_H_
#include <stddef.h>
#include <string>
#include <vector>
#include "base/macros.h"
#include "base/strings/string_piece.h"
#include "chrome/browser/webauthn/authenticator_reference.h"
class AuthenticatorListObserver;
// List of AuthenticatorReference maintained by AuthenticatorRequestDialogModel
// that BleDeviceHoverListModel observes to add views to WebAuthN UI modal
// dialog views.
class ObservableAuthenticatorList {
public:
ObservableAuthenticatorList();
~ObservableAuthenticatorList();
void AddAuthenticator(AuthenticatorReference authenticator);
void RemoveAuthenticator(base::StringPiece authenticator_id);
void ChangeAuthenticatorId(base::StringPiece previous_id, std::string new_id);
void ChangeAuthenticatorPairingMode(base::StringPiece authenticator_id,
bool is_in_pairing_mode);
AuthenticatorReference* GetAuthenticator(base::StringPiece authenticator_id);
void SetObserver(AuthenticatorListObserver* observer);
void RemoveObserver();
std::vector<AuthenticatorReference>& authenticator_list() {
return authenticator_list_;
}
size_t size() const { return authenticator_list_.size(); }
private:
using AuthenticatorListIterator =
std::vector<AuthenticatorReference>::iterator;
AuthenticatorListIterator GetAuthenticatorIterator(
base::StringPiece authenticator_id);
std::vector<AuthenticatorReference> authenticator_list_;
AuthenticatorListObserver* observer_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(ObservableAuthenticatorList);
};
#endif // CHROME_BROWSER_WEBAUTHN_OBSERVABLE_AUTHENTICATOR_LIST_H_
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