Commit ab8e858c authored by Maksim Ivanov's avatar Maksim Ivanov Committed by Commit Bot

Refactor away the RequestPinView's delegate

Refactor the RequestPinView class to use a pair of callbacks instead of
the callback+delegate.

This refactoring makes the interface of the RequestPinView more compact,
which will simplify the introduction of alternative UI implementations
(for the Chrome OS Login and Lock screens) in follow-up CLs.

This is a pure refactoring, it's expected to bring no behavior changes.

Bug: 964069
Change-Id: I7d35592f7897b133d98f4dbc0657a19009ebb7d1
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1722847
Commit-Queue: Maksim Ivanov <emaxx@chromium.org>
Reviewed-by: default avatarAchuith Bhandarkar <achuith@chromium.org>
Reviewed-by: default avatarIgor <igorcov@chromium.org>
Cr-Commit-Position: refs/heads/master@{#683334}
parent ecf40c20
...@@ -71,8 +71,9 @@ PinDialogManager::RequestPinResult PinDialogManager::RequestPin( ...@@ -71,8 +71,9 @@ PinDialogManager::RequestPinResult PinDialogManager::RequestPin(
if (!active_pin_dialog_->IsLocked()) if (!active_pin_dialog_->IsLocked())
return RequestPinResult::kDialogDisplayedAlready; return RequestPinResult::kDialogDisplayedAlready;
// Set the new callback to be used by the view. DCHECK(!active_request_pin_callback_);
active_pin_dialog_->SetCallback(std::move(callback)); active_request_pin_callback_ = std::move(callback);
active_pin_dialog_->SetDialogParameters(code_type, error_type, active_pin_dialog_->SetDialogParameters(code_type, error_type,
attempts_left, accept_input); attempts_left, accept_input);
active_pin_dialog_->DialogModelChanged(); active_pin_dialog_->DialogModelChanged();
...@@ -88,9 +89,16 @@ PinDialogManager::RequestPinResult PinDialogManager::RequestPin( ...@@ -88,9 +89,16 @@ PinDialogManager::RequestPinResult PinDialogManager::RequestPin(
if (current_time - sign_request_times_[key] > kSignRequestIdTimeout) if (current_time - sign_request_times_[key] > kSignRequestIdTimeout)
return RequestPinResult::kInvalidId; return RequestPinResult::kInvalidId;
DCHECK(!active_request_pin_callback_);
active_request_pin_callback_ = std::move(callback);
active_dialog_extension_id_ = extension_id; active_dialog_extension_id_ = extension_id;
active_pin_dialog_ = new RequestPinView( active_pin_dialog_ =
extension_name, code_type, attempts_left, std::move(callback), this); new RequestPinView(extension_name, code_type, attempts_left,
base::BindRepeating(&PinDialogManager::OnPinEntered,
weak_factory_.GetWeakPtr()),
base::BindOnce(&PinDialogManager::OnViewDestroyed,
weak_factory_.GetWeakPtr()));
const gfx::NativeWindow parent = GetBrowserParentWindow(); const gfx::NativeWindow parent = GetBrowserParentWindow();
// If there is no parent, falls back to the root window for new windows. // If there is no parent, falls back to the root window for new windows.
...@@ -101,18 +109,6 @@ PinDialogManager::RequestPinResult PinDialogManager::RequestPin( ...@@ -101,18 +109,6 @@ PinDialogManager::RequestPinResult PinDialogManager::RequestPin(
return RequestPinResult::kSuccess; return RequestPinResult::kSuccess;
} }
void PinDialogManager::OnPinDialogInput() {
last_response_closed_[active_dialog_extension_id_] = false;
}
void PinDialogManager::OnPinDialogClosed() {
last_response_closed_[active_dialog_extension_id_] = true;
// |active_pin_dialog_| is managed by |active_window_|. This local copy of
// the pointer is reset here to allow a new dialog to be created when a new
// request comes.
active_pin_dialog_ = nullptr;
}
PinDialogManager::StopPinRequestResult PinDialogManager::StopPinRequestResult
PinDialogManager::StopPinRequestWithError( PinDialogManager::StopPinRequestWithError(
const std::string& extension_id, const std::string& extension_id,
...@@ -126,12 +122,8 @@ PinDialogManager::StopPinRequestWithError( ...@@ -126,12 +122,8 @@ PinDialogManager::StopPinRequestWithError(
if (!active_pin_dialog_->IsLocked()) if (!active_pin_dialog_->IsLocked())
return StopPinRequestResult::kNoUserInput; return StopPinRequestResult::kNoUserInput;
active_pin_dialog_->SetCallback(base::BindOnce( DCHECK(!active_stop_pin_request_callback_);
[](StopPinRequestCallback callback, const std::string& user_input) { active_stop_pin_request_callback_ = std::move(callback);
DCHECK(user_input.empty());
std::move(callback).Run();
},
std::move(callback)));
active_pin_dialog_->SetDialogParameters( active_pin_dialog_->SetDialogParameters(
RequestPinView::RequestPinCodeType::UNCHANGED, error_type, RequestPinView::RequestPinCodeType::UNCHANGED, error_type,
/*attempts_left=*/-1, /*attempts_left=*/-1,
...@@ -154,10 +146,13 @@ bool PinDialogManager::CloseDialog(const std::string& extension_id) { ...@@ -154,10 +146,13 @@ bool PinDialogManager::CloseDialog(const std::string& extension_id) {
return false; return false;
} }
// Close the window. |active_pin_dialog_| gets deleted inside Close(). // The view destruction may happen asynchronously after the Close() call. For
// simplicity, clear our state and execute the callback immediately.
active_window_->Close(); active_window_->Close();
active_pin_dialog_ = nullptr; if (active_pin_dialog_) {
weak_factory_.InvalidateWeakPtrs();
OnPinDialogClosed();
}
return true; return true;
} }
...@@ -176,4 +171,29 @@ void PinDialogManager::ExtensionUnloaded(const std::string& extension_id) { ...@@ -176,4 +171,29 @@ void PinDialogManager::ExtensionUnloaded(const std::string& extension_id) {
} }
} }
void PinDialogManager::OnPinEntered(const std::string& user_input) {
DCHECK(!active_stop_pin_request_callback_);
last_response_closed_[active_dialog_extension_id_] = false;
if (active_request_pin_callback_)
std::move(active_request_pin_callback_).Run(user_input);
}
void PinDialogManager::OnViewDestroyed() {
OnPinDialogClosed();
}
void PinDialogManager::OnPinDialogClosed() {
DCHECK(active_pin_dialog_);
DCHECK(!active_request_pin_callback_ || !active_stop_pin_request_callback_);
active_pin_dialog_ = nullptr;
active_window_ = nullptr;
last_response_closed_[active_dialog_extension_id_] = true;
active_dialog_extension_id_.clear();
if (active_request_pin_callback_)
std::move(active_request_pin_callback_).Run(/*user_input=*/std::string());
if (active_stop_pin_request_callback_)
std::move(active_stop_pin_request_callback_).Run();
}
} // namespace chromeos } // namespace chromeos
...@@ -21,7 +21,7 @@ namespace chromeos { ...@@ -21,7 +21,7 @@ namespace chromeos {
// Manages the state of the dialog that requests the PIN from user. Used by the // Manages the state of the dialog that requests the PIN from user. Used by the
// extensions that need to request the PIN. Implemented as requirement for // extensions that need to request the PIN. Implemented as requirement for
// crbug.com/612886 // crbug.com/612886
class PinDialogManager final : RequestPinView::Delegate { class PinDialogManager final {
public: public:
enum class RequestPinResult { enum class RequestPinResult {
kSuccess, kSuccess,
...@@ -75,10 +75,6 @@ class PinDialogManager final : RequestPinView::Delegate { ...@@ -75,10 +75,6 @@ class PinDialogManager final : RequestPinView::Delegate {
int attempts_left, int attempts_left,
RequestPinCallback callback); RequestPinCallback callback);
// chromeos::RequestPinView::Delegate overrides.
void OnPinDialogInput() override;
void OnPinDialogClosed() override;
// Updates the existing dialog with new error message. Runs |callback| when // Updates the existing dialog with new error message. Runs |callback| when
// user closes the dialog. Returns whether the provided |extension_id| matches // user closes the dialog. Returns whether the provided |extension_id| matches
// the extension owning the active dialog. // the extension owning the active dialog.
...@@ -105,6 +101,16 @@ class PinDialogManager final : RequestPinView::Delegate { ...@@ -105,6 +101,16 @@ class PinDialogManager final : RequestPinView::Delegate {
private: private:
using ExtensionNameRequestIdPair = std::pair<std::string, int>; using ExtensionNameRequestIdPair = std::pair<std::string, int>;
// The callback that gets invoked once the user sends some input into the PIN
// dialog.
void OnPinEntered(const std::string& user_input);
// The callback that gets invoked once the PIN dialog's view gets destroyed.
void OnViewDestroyed();
// Called when the PIN dialog is closed. Cleans up the internal state and runs
// the needed callbacks.
void OnPinDialogClosed();
// Tells whether user closed the last request PIN dialog issued by an // Tells whether user closed the last request PIN dialog issued by an
// extension. The extension_id is the key and value is true if user closed the // extension. The extension_id is the key and value is true if user closed the
// dialog. Used to determine if the limit of dialogs rejected by the user has // dialog. Used to determine if the limit of dialogs rejected by the user has
...@@ -120,6 +126,8 @@ class PinDialogManager final : RequestPinView::Delegate { ...@@ -120,6 +126,8 @@ class PinDialogManager final : RequestPinView::Delegate {
RequestPinView* active_pin_dialog_ = nullptr; RequestPinView* active_pin_dialog_ = nullptr;
std::string active_dialog_extension_id_; std::string active_dialog_extension_id_;
views::Widget* active_window_ = nullptr; views::Widget* active_window_ = nullptr;
RequestPinCallback active_request_pin_callback_;
StopPinRequestCallback active_stop_pin_request_callback_;
base::WeakPtrFactory<PinDialogManager> weak_factory_{this}; base::WeakPtrFactory<PinDialogManager> weak_factory_{this};
}; };
......
...@@ -33,14 +33,15 @@ constexpr int kDefaultTextWidth = 200; ...@@ -33,14 +33,15 @@ constexpr int kDefaultTextWidth = 200;
} // namespace } // namespace
RequestPinView::RequestPinView(const std::string& extension_name, RequestPinView::RequestPinView(
RequestPinView::RequestPinCodeType code_type, const std::string& extension_name,
int attempts_left, RequestPinView::RequestPinCodeType code_type,
RequestPinCallback callback, int attempts_left,
Delegate* delegate) const PinEnteredCallback& pin_entered_callback,
: callback_(std::move(callback)), delegate_(delegate) { ViewDestructionCallback view_destruction_callback)
: pin_entered_callback_(pin_entered_callback),
view_destruction_callback_(std::move(view_destruction_callback)) {
DCHECK_NE(code_type, RequestPinCodeType::UNCHANGED); DCHECK_NE(code_type, RequestPinCodeType::UNCHANGED);
DCHECK(delegate);
Init(); Init();
SetExtensionName(extension_name); SetExtensionName(extension_name);
const bool accept_input = (attempts_left != 0); const bool accept_input = (attempts_left != 0);
...@@ -49,13 +50,8 @@ RequestPinView::RequestPinView(const std::string& extension_name, ...@@ -49,13 +50,8 @@ RequestPinView::RequestPinView(const std::string& extension_name,
chrome::RecordDialogCreation(chrome::DialogIdentifier::REQUEST_PIN); chrome::RecordDialogCreation(chrome::DialogIdentifier::REQUEST_PIN);
} }
// When the parent window is closed while the dialog is active, this object is
// destroyed without triggering Accept or Cancel. If the callback_ wasn't called
// it needs to send the response.
RequestPinView::~RequestPinView() { RequestPinView::~RequestPinView() {
if (callback_) std::move(view_destruction_callback_).Run();
std::move(callback_).Run(/*user_input=*/std::string());
delegate_->OnPinDialogClosed();
} }
void RequestPinView::ContentsChanged(views::Textfield* sender, void RequestPinView::ContentsChanged(views::Textfield* sender,
...@@ -64,16 +60,15 @@ void RequestPinView::ContentsChanged(views::Textfield* sender, ...@@ -64,16 +60,15 @@ void RequestPinView::ContentsChanged(views::Textfield* sender,
} }
bool RequestPinView::Cancel() { bool RequestPinView::Cancel() {
// Destructor will be called after this which notifies the delegate. // Destructor will be called after this which notifies the callback.
return true; return true;
} }
bool RequestPinView::Accept() { bool RequestPinView::Accept() {
DCHECK(!callback_.is_null());
if (!textfield_->GetEnabled()) if (!textfield_->GetEnabled())
return true; return true;
DCHECK(!textfield_->GetText().empty()); DCHECK(!textfield_->GetText().empty());
DCHECK(!locked_);
error_label_->SetVisible(true); error_label_->SetVisible(true);
error_label_->SetText( error_label_->SetText(
...@@ -84,9 +79,9 @@ bool RequestPinView::Accept() { ...@@ -84,9 +79,9 @@ bool RequestPinView::Accept() {
// The |textfield_| and OK button become disabled, but the user still can // The |textfield_| and OK button become disabled, but the user still can
// close the dialog. // close the dialog.
SetAcceptInput(false); SetAcceptInput(false);
std::move(callback_).Run(base::UTF16ToUTF8(textfield_->GetText())); pin_entered_callback_.Run(base::UTF16ToUTF8(textfield_->GetText()));
locked_ = true;
DialogModelChanged(); DialogModelChanged();
delegate_->OnPinDialogInput();
return false; return false;
} }
...@@ -96,7 +91,7 @@ bool RequestPinView::IsDialogButtonEnabled(ui::DialogButton button) const { ...@@ -96,7 +91,7 @@ bool RequestPinView::IsDialogButtonEnabled(ui::DialogButton button) const {
case ui::DialogButton::DIALOG_BUTTON_CANCEL: case ui::DialogButton::DIALOG_BUTTON_CANCEL:
return true; return true;
case ui::DialogButton::DIALOG_BUTTON_OK: case ui::DialogButton::DIALOG_BUTTON_OK:
if (callback_.is_null()) if (locked_)
return false; return false;
// Not locked but the |textfield_| is not enabled. It's just a // Not locked but the |textfield_| is not enabled. It's just a
// notification to the user and [OK] button can be used to close the // notification to the user and [OK] button can be used to close the
...@@ -131,12 +126,7 @@ gfx::Size RequestPinView::CalculatePreferredSize() const { ...@@ -131,12 +126,7 @@ gfx::Size RequestPinView::CalculatePreferredSize() const {
} }
bool RequestPinView::IsLocked() const { bool RequestPinView::IsLocked() const {
return callback_.is_null(); return locked_;
}
void RequestPinView::SetCallback(RequestPinCallback callback) {
DCHECK(!callback_);
callback_ = std::move(callback);
} }
void RequestPinView::SetDialogParameters( void RequestPinView::SetDialogParameters(
...@@ -144,6 +134,7 @@ void RequestPinView::SetDialogParameters( ...@@ -144,6 +134,7 @@ void RequestPinView::SetDialogParameters(
RequestPinView::RequestPinErrorType error_type, RequestPinView::RequestPinErrorType error_type,
int attempts_left, int attempts_left,
bool accept_input) { bool accept_input) {
locked_ = false;
SetErrorMessage(error_type, attempts_left); SetErrorMessage(error_type, attempts_left);
SetAcceptInput(accept_input); SetAcceptInput(accept_input);
......
...@@ -26,8 +26,8 @@ namespace chromeos { ...@@ -26,8 +26,8 @@ namespace chromeos {
// A dialog box for requesting PIN code. Instances of this class are managed by // A dialog box for requesting PIN code. Instances of this class are managed by
// PinDialogManager. // PinDialogManager.
class RequestPinView : public views::DialogDelegateView, class RequestPinView final : public views::DialogDelegateView,
public views::TextfieldController { public views::TextfieldController {
public: public:
enum RequestPinCodeType { PIN, PUK, UNCHANGED }; enum RequestPinCodeType { PIN, PUK, UNCHANGED };
...@@ -39,19 +39,9 @@ class RequestPinView : public views::DialogDelegateView, ...@@ -39,19 +39,9 @@ class RequestPinView : public views::DialogDelegateView,
UNKNOWN_ERROR UNKNOWN_ERROR
}; };
class Delegate { using PinEnteredCallback =
public: base::RepeatingCallback<void(const std::string& user_input)>;
// Notification when user closes the PIN dialog. using ViewDestructionCallback = base::OnceClosure;
virtual void OnPinDialogClosed() = 0;
// Notification when the user provided input to dialog.
virtual void OnPinDialogInput() = 0;
};
// Used to send the PIN/PUK entered by the user in the textfield to the
// extension that asked for the code.
using RequestPinCallback =
base::OnceCallback<void(const std::string& user_input)>;
// Creates the view to be embeded in the dialog that requests the PIN/PUK. // Creates the view to be embeded in the dialog that requests the PIN/PUK.
// |extension_name| - the name of the extension making the request. Displayed // |extension_name| - the name of the extension making the request. Displayed
...@@ -62,13 +52,13 @@ class RequestPinView : public views::DialogDelegateView, ...@@ -62,13 +52,13 @@ class RequestPinView : public views::DialogDelegateView,
// zero the textfield is disabled and user cannot provide any input. When // zero the textfield is disabled and user cannot provide any input. When
// -1 the user is allowed to provide the input and no information about // -1 the user is allowed to provide the input and no information about
// the attepts left is displayed in the view. // the attepts left is displayed in the view.
// |callback| - used to send the value of the PIN/PUK the user entered. // |pin_entered_callback| - called every time the user submits the input.
// |delegate| - used to notify that dialog was closed. Cannot be null. // |view_destruction_callback| - called by the destructor.
RequestPinView(const std::string& extension_name, RequestPinView(const std::string& extension_name,
RequestPinCodeType code_type, RequestPinCodeType code_type,
int attempts_left, int attempts_left,
RequestPinCallback callback, const PinEnteredCallback& pin_entered_callback,
Delegate* delegate); ViewDestructionCallback view_destruction_callback);
RequestPinView(const RequestPinView&) = delete; RequestPinView(const RequestPinView&) = delete;
RequestPinView& operator=(const RequestPinView&) = delete; RequestPinView& operator=(const RequestPinView&) = delete;
~RequestPinView() override; ~RequestPinView() override;
...@@ -92,10 +82,6 @@ class RequestPinView : public views::DialogDelegateView, ...@@ -92,10 +82,6 @@ class RequestPinView : public views::DialogDelegateView,
// the user input data. // the user input data.
bool IsLocked() const; bool IsLocked() const;
// Set the new callback to be used when user will provide the input. The old
// callback must be used and reset to null at this point.
void SetCallback(RequestPinCallback callback);
// |code_type| - specifies whether the user is asked to enter PIN or PUK. If // |code_type| - specifies whether the user is asked to enter PIN or PUK. If
// UNCHANGED value is provided, the dialog displays the same value that // UNCHANGED value is provided, the dialog displays the same value that
// was last set. // was last set.
...@@ -126,14 +112,12 @@ class RequestPinView : public views::DialogDelegateView, ...@@ -126,14 +112,12 @@ class RequestPinView : public views::DialogDelegateView,
// |window_title_| and |code_type_|. // |window_title_| and |code_type_|.
void UpdateHeaderText(); void UpdateHeaderText();
// Used to send the input when the view is not locked. If user closes the const PinEnteredCallback pin_entered_callback_;
// view, the provided input is empty. The |callback_| must be reset to null ViewDestructionCallback view_destruction_callback_;
// after being used, allowing to check that it was used when a new callback is
// set.
RequestPinCallback callback_;
// Owned by the caller. // Whether the UI is locked, disallowing the user to input any data, while the
Delegate* delegate_ = nullptr; // caller processes the previously entered PIN/PUK.
bool locked_ = false;
base::string16 window_title_; base::string16 window_title_;
views::Label* header_label_ = nullptr; views::Label* header_label_ = nullptr;
......
...@@ -244,7 +244,6 @@ void CertificateProviderStopPinRequestFunction::OnPinRequestStopped() { ...@@ -244,7 +244,6 @@ void CertificateProviderStopPinRequestFunction::OnPinRequestStopped() {
DCHECK(service); DCHECK(service);
Respond(NoArguments()); Respond(NoArguments());
service->pin_dialog_manager()->OnPinDialogClosed();
} }
CertificateProviderRequestPinFunction:: CertificateProviderRequestPinFunction::
......
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