Commit 22e89174 authored by Alex Ilin's avatar Alex Ilin Committed by Commit Bot

[Signin] Implement reauth popup

SigninViewController::ShowReauthPopup() will start showing a popup
window with a reauth page if "SigninReauthPrompt" feature is enabled.

This popup observes all navigations and reports success once a special
reauth endpoint is successfully loaded. This endpoint is currently
available only on test Gaia.

The behavior of ShowReauthPopup() without the feature flag also has
changed. Now Chrome will display a fake reauth dialog by default.
ShowReauthPopup() is still in development and shouldn't be used without
a flag anyways. There is no need to guard it behind another feature
flag.

The screen recording of the resulting flow is available at
https://screencast.googleplex.com/cast/NTM5Njc2MjgxNjY3NTg0MHw0MTg2MGQ0OS02Yg

Bug: 1045515
Change-Id: I8a685b593dadec3ec059c77a6a4eccb946f4c98c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2107840
Commit-Queue: Alex Ilin <alexilin@chromium.org>
Reviewed-by: default avatarDavid Roger <droger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#751342}
parent 37a164f1
...@@ -2175,6 +2175,8 @@ jumbo_static_library("ui") { ...@@ -2175,6 +2175,8 @@ jumbo_static_library("ui") {
"avatar_button_error_controller_delegate.h", "avatar_button_error_controller_delegate.h",
"frame/window_frame_util.cc", "frame/window_frame_util.cc",
"frame/window_frame_util.h", "frame/window_frame_util.h",
"signin_reauth_popup_delegate.cc",
"signin_reauth_popup_delegate.h",
"signin_view_controller.cc", "signin_view_controller.cc",
"signin_view_controller.h", "signin_view_controller.h",
"signin_view_controller_delegate.h", "signin_view_controller_delegate.h",
......
...@@ -267,6 +267,7 @@ enum class DialogIdentifier { ...@@ -267,6 +267,7 @@ enum class DialogIdentifier {
PRINT_JOB_CONFIRMATION = 102, PRINT_JOB_CONFIRMATION = 102,
CROSTINI_RECOVERY = 103, CROSTINI_RECOVERY = 103,
PARENT_PERMISSION = 104, // ChromeOS only. PARENT_PERMISSION = 104, // ChromeOS only.
SIGNIN_REAUTH = 105,
// Add values above this line with a corresponding label in // Add values above this line with a corresponding label in
// tools/metrics/histograms/enums.xml // tools/metrics/histograms/enums.xml
MAX_VALUE MAX_VALUE
......
// Copyright 2020 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/signin_reauth_popup_delegate.h"
#include "base/logging.h"
#include "chrome/browser/signin/reauth_result.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_navigator.h"
#include "chrome/browser/ui/browser_navigator_params.h"
#include "chrome/browser/ui/signin_view_controller.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/web_contents.h"
#include "google_apis/gaia/core_account_id.h"
#include "google_apis/gaia/gaia_urls.h"
#include "net/http/http_status_code.h"
#include "ui/base/page_transition_types.h"
#include "ui/base/window_open_disposition.h"
namespace {
const int kPopupWidth = 657;
const int kPopupHeight = 708;
} // namespace
SigninReauthPopupDelegate::SigninReauthPopupDelegate(
SigninViewController* signin_view_controller,
Browser* browser,
const CoreAccountId& account_id,
base::OnceCallback<void(signin::ReauthResult)> reauth_callback)
: signin_view_controller_(signin_view_controller),
browser_(browser),
reauth_callback_(std::move(reauth_callback)) {
NavigateParams nav_params(browser_, reauth_url(),
ui::PAGE_TRANSITION_AUTO_TOPLEVEL);
nav_params.disposition = WindowOpenDisposition::NEW_POPUP;
nav_params.window_action = NavigateParams::SHOW_WINDOW;
nav_params.trusted_source = false;
nav_params.user_gesture = true;
nav_params.window_bounds = gfx::Rect(kPopupWidth, kPopupHeight);
Navigate(&nav_params);
web_contents_ = nav_params.navigated_or_inserted_contents;
content::WebContentsObserver::Observe(web_contents_);
}
SigninReauthPopupDelegate::~SigninReauthPopupDelegate() = default;
void SigninReauthPopupDelegate::CloseModalSignin() {
CompleteReauth(signin::ReauthResult::kCancelled);
}
void SigninReauthPopupDelegate::ResizeNativeView(int height) {
NOTIMPLEMENTED();
}
content::WebContents* SigninReauthPopupDelegate::GetWebContents() {
return web_contents_;
}
void SigninReauthPopupDelegate::DidFinishNavigation(
content::NavigationHandle* navigation_handle) {
if (!navigation_handle->IsInMainFrame() ||
navigation_handle->IsSameDocument()) {
return;
}
GURL::Replacements replacements;
replacements.ClearQuery();
GURL url_without_query =
navigation_handle->GetURL().ReplaceComponents(replacements);
if (url_without_query != reauth_url())
return;
// TODO(https://crbug.com/1045515): update the response code once Gaia
// implements a landing page.
if (navigation_handle->IsErrorPage() ||
!navigation_handle->GetResponseHeaders() ||
navigation_handle->GetResponseHeaders()->response_code() !=
net::HTTP_NOT_IMPLEMENTED) {
CompleteReauth(signin::ReauthResult::kLoadFailed);
return;
}
CompleteReauth(signin::ReauthResult::kSuccess);
}
void SigninReauthPopupDelegate::WebContentsDestroyed() {
if (signin_view_controller_) {
signin_view_controller_->ResetModalSigninDelegate();
signin_view_controller_ = nullptr;
}
// The last chance to invoke |reauth_callback_|. Run it only if WebContents
// descruction was caused by an event outside of this class.
if (reauth_callback_)
std::move(reauth_callback_).Run(signin::ReauthResult::kDismissedByUser);
delete this;
}
void SigninReauthPopupDelegate::CompleteReauth(signin::ReauthResult result) {
std::move(reauth_callback_).Run(result);
// Close WebContents asynchronously so other WebContentsObservers can safely
// finish their task.
content::GetUIThreadTaskRunner({})->PostTask(
FROM_HERE, base::BindOnce(&SigninReauthPopupDelegate::CloseWebContents,
weak_ptr_factory_.GetWeakPtr()));
}
void SigninReauthPopupDelegate::CloseWebContents() {
web_contents_->ClosePage();
}
const GURL& SigninReauthPopupDelegate::reauth_url() const {
return GaiaUrls::GetInstance()->reauth_url();
}
// Copyright 2020 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_SIGNIN_REAUTH_POPUP_DELEGATE_H_
#define CHROME_BROWSER_UI_SIGNIN_REAUTH_POPUP_DELEGATE_H_
#include "base/callback.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/ui/signin_view_controller_delegate.h"
#include "content/public/browser/web_contents_observer.h"
#include "url/gurl.h"
class SigninViewController;
class Browser;
struct CoreAccountId;
namespace content {
class WebContents;
}
class SigninReauthPopupDelegate : public SigninViewControllerDelegate,
public content::WebContentsObserver {
public:
SigninReauthPopupDelegate(
SigninViewController* signin_view_controller,
Browser* browser,
const CoreAccountId& account_id,
base::OnceCallback<void(signin::ReauthResult)> reauth_callback);
~SigninReauthPopupDelegate() override;
// SigninViewControllerDelegate:
void CloseModalSignin() override;
void ResizeNativeView(int height) override;
content::WebContents* GetWebContents() override;
// content::WebContentsObserver:
void DidFinishNavigation(
content::NavigationHandle* navigation_handle) override;
void WebContentsDestroyed() override;
private:
void CompleteReauth(signin::ReauthResult result);
void CloseWebContents();
const GURL& reauth_url() const;
SigninViewController* signin_view_controller_;
Browser* const browser_;
base::OnceCallback<void(signin::ReauthResult)> reauth_callback_;
content::WebContents* web_contents_;
GURL reauth_url_;
base::WeakPtrFactory<SigninReauthPopupDelegate> weak_ptr_factory_{this};
};
#endif // CHROME_BROWSER_UI_SIGNIN_REAUTH_POPUP_DELEGATE_H_
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "chrome/browser/signin/reauth_result.h" #include "chrome/browser/signin/reauth_result.h"
#include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_dialogs.h" #include "chrome/browser/ui/browser_dialogs.h"
#include "chrome/browser/ui/signin_reauth_popup_delegate.h"
#include "chrome/browser/ui/signin_view_controller_delegate.h" #include "chrome/browser/ui/signin_view_controller_delegate.h"
#include "components/signin/public/base/signin_buildflags.h" #include "components/signin/public/base/signin_buildflags.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
...@@ -166,14 +167,18 @@ void SigninViewController::ShowReauthPrompt( ...@@ -166,14 +167,18 @@ void SigninViewController::ShowReauthPrompt(
base::OnceCallback<void(signin::ReauthResult)> reauth_callback) { base::OnceCallback<void(signin::ReauthResult)> reauth_callback) {
CloseModalSignin(); CloseModalSignin();
if (!base::FeatureList::IsEnabled(kSigninReauthPrompt)) { // The delegate will delete itself on request of the UI code when the widget
// Reauth is disabled - always return failure. // is closed.
std::move(reauth_callback).Run(signin::ReauthResult::kDismissedByUser); if (base::FeatureList::IsEnabled(kSigninReauthPrompt)) {
return; delegate_ = new SigninReauthPopupDelegate(this, browser, account_id,
} std::move(reauth_callback));
} else {
// This currently displays a fake dialog for development purposes. Should
// not be called in production.
delegate_ = SigninViewControllerDelegate::CreateReauthDelegate( delegate_ = SigninViewControllerDelegate::CreateReauthDelegate(
this, browser, account_id, std::move(reauth_callback)); this, browser, account_id, std::move(reauth_callback));
}
chrome::RecordDialogCreation(chrome::DialogIdentifier::SIGNIN_REAUTH);
} }
bool SigninViewController::ShowsModalDialog() { bool SigninViewController::ShowsModalDialog() {
......
...@@ -56,6 +56,7 @@ const char kOAuthRevokeTokenUrlSuffix[] = "AuthSubRevokeToken"; ...@@ -56,6 +56,7 @@ const char kOAuthRevokeTokenUrlSuffix[] = "AuthSubRevokeToken";
const char kListAccountsSuffix[] = "ListAccounts?json=standard"; const char kListAccountsSuffix[] = "ListAccounts?json=standard";
const char kEmbeddedSigninSuffix[] = "embedded/setup/chrome/usermenu"; const char kEmbeddedSigninSuffix[] = "embedded/setup/chrome/usermenu";
const char kAddAccountSuffix[] = "AddSession"; const char kAddAccountSuffix[] = "AddSession";
const char kReauthSuffix[] = "embedded/xreauth/chrome";
const char kGetCheckConnectionInfoSuffix[] = "GetCheckConnectionInfo"; const char kGetCheckConnectionInfoSuffix[] = "GetCheckConnectionInfo";
// API calls from accounts.google.com (LSO) // API calls from accounts.google.com (LSO)
...@@ -151,6 +152,7 @@ GaiaUrls::GaiaUrls() { ...@@ -151,6 +152,7 @@ GaiaUrls::GaiaUrls() {
list_accounts_url_ = gaia_url_.Resolve(kListAccountsSuffix); list_accounts_url_ = gaia_url_.Resolve(kListAccountsSuffix);
embedded_signin_url_ = gaia_url_.Resolve(kEmbeddedSigninSuffix); embedded_signin_url_ = gaia_url_.Resolve(kEmbeddedSigninSuffix);
add_account_url_ = gaia_url_.Resolve(kAddAccountSuffix); add_account_url_ = gaia_url_.Resolve(kAddAccountSuffix);
reauth_url_ = gaia_url_.Resolve(kReauthSuffix);
get_check_connection_info_url_ = get_check_connection_info_url_ =
gaia_url_.Resolve(kGetCheckConnectionInfoSuffix); gaia_url_.Resolve(kGetCheckConnectionInfoSuffix);
...@@ -274,6 +276,10 @@ const GURL& GaiaUrls::add_account_url() const { ...@@ -274,6 +276,10 @@ const GURL& GaiaUrls::add_account_url() const {
return add_account_url_; return add_account_url_;
} }
const GURL& GaiaUrls::reauth_url() const {
return reauth_url_;
}
const std::string& GaiaUrls::oauth2_chrome_client_id() const { const std::string& GaiaUrls::oauth2_chrome_client_id() const {
return oauth2_chrome_client_id_; return oauth2_chrome_client_id_;
} }
......
...@@ -41,6 +41,7 @@ class GaiaUrls { ...@@ -41,6 +41,7 @@ class GaiaUrls {
const GURL& oauth1_login_url() const; const GURL& oauth1_login_url() const;
const GURL& embedded_signin_url() const; const GURL& embedded_signin_url() const;
const GURL& add_account_url() const; const GURL& add_account_url() const;
const GURL& reauth_url() const;
const std::string& oauth2_chrome_client_id() const; const std::string& oauth2_chrome_client_id() const;
const std::string& oauth2_chrome_client_secret() const; const std::string& oauth2_chrome_client_secret() const;
...@@ -90,6 +91,7 @@ class GaiaUrls { ...@@ -90,6 +91,7 @@ class GaiaUrls {
GURL list_accounts_url_; GURL list_accounts_url_;
GURL embedded_signin_url_; GURL embedded_signin_url_;
GURL add_account_url_; GURL add_account_url_;
GURL reauth_url_;
GURL get_check_connection_info_url_; GURL get_check_connection_info_url_;
std::string oauth2_chrome_client_id_; std::string oauth2_chrome_client_id_;
......
...@@ -15159,6 +15159,7 @@ to ensure that the crash string is shown properly on the user-facing crash UI. ...@@ -15159,6 +15159,7 @@ to ensure that the crash string is shown properly on the user-facing crash UI.
<int value="101" label="App Uninstall"/> <int value="101" label="App Uninstall"/>
<int value="102" label="Print Job Confirmation"/> <int value="102" label="Print Job Confirmation"/>
<int value="103" label="Crostini Recovery Dialog"/> <int value="103" label="Crostini Recovery Dialog"/>
<int value="104" label="Signin Reauth Dialog"/>
</enum> </enum>
<enum name="DialogOriginRelationship"> <enum name="DialogOriginRelationship">
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