Commit fe95cd62 authored by zmin's avatar zmin Committed by Commit bot

Display error message when user try to open a locked supervised user profile...

Display error message when user try to open a locked supervised user profile when force-sign-in is enabled.

BUG=642059

Review-Url: https://codereview.chromium.org/2552473002
Cr-Commit-Position: refs/heads/master@{#437668}
parent 3a43b1fa
......@@ -11212,6 +11212,9 @@ I don't think this site should be blocked!
<message name="IDS_SYNC_LOGIN_NAME_PROHIBITED" desc="The error message shown when the user tries to sign in to sync using a name that is not allowed by the admin policy">
Signing in with this username has been disabled by your administrator.
</message>
<message name="IDS_SUPERVISED_USER_NOT_ALLOWED_BY_POLICY" desc="The error message shown when the user tries to use the supervised user profile when it's disabled by policy">
Supervised users have been disabled by your administrator.
</message>
<if expr="is_android">
<message name="IDS_SYNC_USER_NAME_IN_USE_ERROR" desc="Mobile: An error message shown when a user tries to sign in to sync using a user name that's already in use by another profile.">
This account is already being used on this device.
......@@ -15,7 +15,7 @@
#include "chrome/browser/profiles/profile_window.h"
#include "components/signin/core/browser/signin_metrics.h"
@class ReauthDialogWindowController;
@class DialogWindowController;
@class UserManagerWindowController;
// Dialog widget that contains the Desktop User Manager webui. This object
......@@ -44,10 +44,10 @@ class UserManagerMac {
void LogTimeToOpen();
void ShowReauthDialog(content::BrowserContext* browser_context,
const std::string& email,
signin_metrics::Reason reason);
void CloseReauthDialog();
void ShowDialog(content::BrowserContext* browser_context,
const std::string& email,
const GURL& url);
void CloseDialog();
void DisplayErrorMessage();
......@@ -61,7 +61,7 @@ class UserManagerMac {
// Controller of the window.
base::scoped_nsobject<UserManagerWindowController> window_controller_;
base::scoped_nsobject<ReauthDialogWindowController> reauth_window_;
base::scoped_nsobject<DialogWindowController> reauth_window_;
base::Time user_manager_started_showing_;
......
......@@ -16,17 +16,18 @@ bool AddToSet(std::set<content::WebContents*>* content_set,
} // namespace
UserManager::BaseReauthDialogDelegate::BaseReauthDialogDelegate()
UserManagerProfileDialog::BaseDialogDelegate::BaseDialogDelegate()
: guest_web_contents_(nullptr) {}
bool UserManager::BaseReauthDialogDelegate::HandleContextMenu(
bool UserManagerProfileDialog::BaseDialogDelegate::HandleContextMenu(
const content::ContextMenuParams& params) {
// Ignores context menu.
return true;
}
void UserManager::BaseReauthDialogDelegate::LoadingStateChanged(
content::WebContents* source, bool to_different_document) {
void UserManagerProfileDialog::BaseDialogDelegate::LoadingStateChanged(
content::WebContents* source,
bool to_different_document) {
if (source->IsLoading() || guest_web_contents_)
return;
......
......@@ -23,16 +23,6 @@ class UserManager {
static constexpr int kWindowWidth = 800;
static constexpr int kWindowHeight = 600;
// Dimensions of the reauth dialog displaying the old-style signin flow with
// the username and password challenge on the same form.
static constexpr int kPasswordCombinedReauthDialogHeight = 440;
static constexpr int kPasswordCombinedReauthDialogWidth = 360;
// Dimensions of the reauth dialog displaying the password-separated signin
// flow.
static constexpr int kReauthDialogHeight = 512;
static constexpr int kReauthDialogWidth = 448;
// Shows the User Manager or re-activates an existing one, focusing the
// profile given by |profile_path_to_focus|; passing an empty base::FilePath
// focuses no user pod. Based on the value of |tutorial_mode|, a tutorial
......@@ -58,6 +48,26 @@ class UserManager {
static void AddOnUserManagerShownCallbackForTesting(
const base::Closure& callback);
// Get the path of profile that is being signed in.
static base::FilePath GetSigninProfilePath();
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(UserManager);
};
// Dialog that will be displayed when a profile is selected in UserManager.
class UserManagerProfileDialog {
public:
// Dimensions of the reauth dialog displaying the old-style signin flow with
// the username and password challenge on the same form.
static constexpr int kPasswordCombinedDialogHeight = 440;
static constexpr int kPasswordCombinedDialogWidth = 360;
// Dimensions of the reauth dialog displaying the password-separated signin
// flow.
static constexpr int kDialogHeight = 512;
static constexpr int kDialogWidth = 448;
// Shows a dialog where the user can re-authenticate the profile with the
// given |email|. This is called in the following scenarios:
// -From the user manager when a profile is locked and the user's password is
......@@ -70,26 +80,27 @@ class UserManager {
const std::string& email,
signin_metrics::Reason reason);
// Hides the reauth dialog if it is showing.
static void HideReauthDialog();
// Shows a dialog where the user logs into their profile for the first time
// via the user manager.
static void ShowSigninDialog(content::BrowserContext* browser_context,
const base::FilePath& profile_path);
// Show the dialog and display local sign in error message without browser.
static void ShowDialogAndDisplayErrorMessage(
content::BrowserContext* browser_context);
// Display local sign in error message without browser.
static void DisplayErrorMessage();
// Get the path of profile that is being signed in.
static base::FilePath GetSigninProfilePath();
// Hides the dialog if it is showing.
static void HideDialog();
// Abstract base class for performing online reauthentication of profiles in
// the User Manager. It is concretely implemented in UserManagerMac and
// UserManagerView to specialize the closing of the UI's dialog widgets.
class BaseReauthDialogDelegate : public content::WebContentsDelegate {
class BaseDialogDelegate : public content::WebContentsDelegate {
public:
BaseReauthDialogDelegate();
BaseDialogDelegate();
// content::WebContentsDelegate:
bool HandleContextMenu(const content::ContextMenuParams& params) override;
......@@ -98,17 +109,14 @@ class UserManager {
void LoadingStateChanged(content::WebContents* source,
bool to_different_document) override;
private:
virtual void CloseReauthDialog() = 0;
protected:
virtual void CloseDialog() = 0;
// WebContents of the embedded WebView.
content::WebContents* guest_web_contents_;
DISALLOW_COPY_AND_ASSIGN(BaseReauthDialogDelegate);
DISALLOW_COPY_AND_ASSIGN(BaseDialogDelegate);
};
private:
DISALLOW_COPY_AND_ASSIGN(UserManager);
};
#endif // CHROME_BROWSER_UI_USER_MANAGER_H_
......@@ -55,88 +55,81 @@ base::Closure* user_manager_shown_callback_for_testing_ = nullptr;
bool instance_under_construction_ = false;
} // namespace
// ReauthDelegate---------------------------------------------------------------
ReauthDelegate::ReauthDelegate(UserManagerView* parent,
views::WebView* web_view,
const std::string& email_address,
signin_metrics::Reason reason)
: parent_(parent),
web_view_(web_view),
email_address_(email_address) {
// Delegate---------------------------------------------------------------
UserManagerProfileDialogDelegate::UserManagerProfileDialogDelegate(
UserManagerView* parent,
views::WebView* web_view,
const std::string& email_address,
const GURL& url)
: parent_(parent), web_view_(web_view), email_address_(email_address) {
AddChildView(web_view_);
SetLayoutManager(new views::FillLayout());
web_view_->GetWebContents()->SetDelegate(this);
// Load the re-auth URL, prepopulated with the user's email address.
// Add the index of the profile to the URL so that the inline login page
// knows which profile to load and update the credentials.
GURL url = signin::GetReauthURLWithEmail(
signin_metrics::AccessPoint::ACCESS_POINT_USER_MANAGER, reason,
email_address_);
web_view_->LoadInitialURL(url);
}
ReauthDelegate::~ReauthDelegate() {}
UserManagerProfileDialogDelegate::~UserManagerProfileDialogDelegate() {}
gfx::Size ReauthDelegate::GetPreferredSize() const {
return switches::UsePasswordSeparatedSigninFlow() ?
gfx::Size(UserManager::kReauthDialogWidth,
UserManager::kReauthDialogHeight) :
gfx::Size(UserManager::kPasswordCombinedReauthDialogWidth,
UserManager::kPasswordCombinedReauthDialogHeight);
gfx::Size UserManagerProfileDialogDelegate::GetPreferredSize() const {
return switches::UsePasswordSeparatedSigninFlow()
? gfx::Size(UserManagerProfileDialog::kDialogWidth,
UserManagerProfileDialog::kDialogHeight)
: gfx::Size(
UserManagerProfileDialog::kPasswordCombinedDialogWidth,
UserManagerProfileDialog::kPasswordCombinedDialogHeight);
}
void ReauthDelegate::DisplayErrorMessage() {
void UserManagerProfileDialogDelegate::DisplayErrorMessage() {
web_view_->LoadInitialURL(GURL(chrome::kChromeUISigninErrorURL));
}
bool ReauthDelegate::CanResize() const {
bool UserManagerProfileDialogDelegate::CanResize() const {
return true;
}
bool ReauthDelegate::CanMaximize() const {
bool UserManagerProfileDialogDelegate::CanMaximize() const {
return true;
}
bool ReauthDelegate::CanMinimize() const {
bool UserManagerProfileDialogDelegate::CanMinimize() const {
return true;
}
bool ReauthDelegate::ShouldUseCustomFrame() const {
bool UserManagerProfileDialogDelegate::ShouldUseCustomFrame() const {
return false;
}
ui::ModalType ReauthDelegate::GetModalType() const {
ui::ModalType UserManagerProfileDialogDelegate::GetModalType() const {
return ui::MODAL_TYPE_WINDOW;
}
void ReauthDelegate::DeleteDelegate() {
OnReauthDialogDestroyed();
void UserManagerProfileDialogDelegate::DeleteDelegate() {
OnDialogDestroyed();
delete this;
}
base::string16 ReauthDelegate::GetWindowTitle() const {
base::string16 UserManagerProfileDialogDelegate::GetWindowTitle() const {
return l10n_util::GetStringUTF16(IDS_PROFILES_GAIA_SIGNIN_TITLE);
}
int ReauthDelegate::GetDialogButtons() const {
int UserManagerProfileDialogDelegate::GetDialogButtons() const {
return ui::DIALOG_BUTTON_NONE;
}
views::View* ReauthDelegate::GetInitiallyFocusedView() {
views::View* UserManagerProfileDialogDelegate::GetInitiallyFocusedView() {
return static_cast<views::View*>(web_view_);
}
void ReauthDelegate::CloseReauthDialog() {
OnReauthDialogDestroyed();
void UserManagerProfileDialogDelegate::CloseDialog() {
OnDialogDestroyed();
GetWidget()->Close();
}
void ReauthDelegate::OnReauthDialogDestroyed() {
void UserManagerProfileDialogDelegate::OnDialogDestroyed() {
if (parent_) {
parent_->OnReauthDialogDestroyed();
parent_->OnDialogDestroyed();
parent_ = nullptr;
}
}
......@@ -209,49 +202,68 @@ void UserManager::OnUserManagerShown() {
}
// static
void UserManager::ShowReauthDialog(content::BrowserContext* browser_context,
const std::string& email,
signin_metrics::Reason reason) {
// This method should only be called if the user manager is already showing.
if (!IsShowing())
return;
instance_->ShowReauthDialog(browser_context, email, reason);
void UserManager::AddOnUserManagerShownCallbackForTesting(
const base::Closure& callback) {
DCHECK(!user_manager_shown_callback_for_testing_);
user_manager_shown_callback_for_testing_ = new base::Closure(callback);
}
// static
void UserManager::HideReauthDialog() {
// This method should only be called if the user manager is already showing.
if (instance_ && instance_->GetWidget()->IsVisible())
instance_->HideReauthDialog();
base::FilePath UserManager::GetSigninProfilePath() {
return instance_->GetSigninProfilePath();
}
// UserManagerProfileDialog
// -------------------------------------------------------------
// static
void UserManager::AddOnUserManagerShownCallbackForTesting(
const base::Closure& callback) {
DCHECK(!user_manager_shown_callback_for_testing_);
user_manager_shown_callback_for_testing_ = new base::Closure(callback);
void UserManagerProfileDialog::ShowReauthDialog(
content::BrowserContext* browser_context,
const std::string& email,
signin_metrics::Reason reason) {
// This method should only be called if the user manager is already showing.
if (!UserManager::IsShowing())
return;
// Load the re-auth URL, prepopulated with the user's email address.
// Add the index of the profile to the URL so that the inline login page
// knows which profile to load and update the credentials.
GURL url = signin::GetReauthURLWithEmail(
signin_metrics::AccessPoint::ACCESS_POINT_USER_MANAGER, reason, email);
instance_->ShowDialog(browser_context, email, url);
}
// static
void UserManager::ShowSigninDialog(content::BrowserContext* browser_context,
const base::FilePath& profile_path) {
if (!IsShowing())
void UserManagerProfileDialog::ShowSigninDialog(
content::BrowserContext* browser_context,
const base::FilePath& profile_path) {
if (!UserManager::IsShowing())
return;
instance_->SetSigninProfilePath(profile_path);
ShowReauthDialog(browser_context, std::string(),
signin_metrics::Reason::REASON_SIGNIN_PRIMARY_ACCOUNT);
GURL url = signin::GetPromoURL(
signin_metrics::AccessPoint::ACCESS_POINT_USER_MANAGER,
signin_metrics::Reason::REASON_SIGNIN_PRIMARY_ACCOUNT, true, true);
instance_->ShowDialog(browser_context, std::string(), url);
}
void UserManagerProfileDialog::ShowDialogAndDisplayErrorMessage(
content::BrowserContext* browser_context) {
if (!UserManager::IsShowing())
return;
instance_->ShowDialog(browser_context, std::string(),
GURL(chrome::kChromeUISigninErrorURL));
}
// static
void UserManager::DisplayErrorMessage() {
void UserManagerProfileDialog::DisplayErrorMessage() {
// This method should only be called if the user manager is already showing.
DCHECK(instance_);
instance_->DisplayErrorMessage();
}
// static
base::FilePath UserManager::GetSigninProfilePath() {
return instance_->GetSigninProfilePath();
void UserManagerProfileDialog::HideDialog() {
if (instance_ && instance_->GetWidget()->IsVisible())
instance_->HideDialog();
}
// UserManagerView -------------------------------------------------------------
......@@ -265,7 +277,7 @@ UserManagerView::UserManagerView()
}
UserManagerView::~UserManagerView() {
HideReauthDialog();
HideDialog();
}
// static
......@@ -283,29 +295,27 @@ void UserManagerView::OnSystemProfileCreated(
instance_->Init(system_profile, GURL(url));
}
void UserManagerView::ShowReauthDialog(content::BrowserContext* browser_context,
const std::string& email,
signin_metrics::Reason reason) {
HideReauthDialog();
void UserManagerView::ShowDialog(content::BrowserContext* browser_context,
const std::string& email,
const GURL& url) {
HideDialog();
// The dialog delegate will be deleted when the widget closes. The created
// WebView's lifetime is managed by the delegate.
delegate_ = new ReauthDelegate(this,
new views::WebView(browser_context),
email,
reason);
delegate_ = new UserManagerProfileDialogDelegate(
this, new views::WebView(browser_context), email, url);
gfx::NativeView parent = instance_->GetWidget()->GetNativeView();
views::DialogDelegate::CreateDialogWidget(delegate_, nullptr, parent);
delegate_->GetWidget()->Show();
}
void UserManagerView::HideReauthDialog() {
void UserManagerView::HideDialog() {
if (delegate_) {
delegate_->CloseReauthDialog();
delegate_->CloseDialog();
DCHECK(!delegate_);
}
}
void UserManagerView::OnReauthDialogDestroyed() {
void UserManagerView::OnDialogDestroyed() {
delegate_ = nullptr;
}
......
......@@ -19,27 +19,28 @@
class ScopedKeepAlive;
class UserManagerView;
class ReauthDelegate : public views::DialogDelegateView,
public UserManager::BaseReauthDialogDelegate {
class UserManagerProfileDialogDelegate
: public views::DialogDelegateView,
public UserManagerProfileDialog::BaseDialogDelegate {
public:
ReauthDelegate(UserManagerView* parent,
views::WebView* web_view,
const std::string& email_address,
signin_metrics::Reason reason);
~ReauthDelegate() override;
UserManagerProfileDialogDelegate(UserManagerView* parent,
views::WebView* web_view,
const std::string& email_address,
const GURL& url);
~UserManagerProfileDialogDelegate() override;
// UserManager::BaseReauthDialogDelegate:
void CloseReauthDialog() override;
// UserManagerProfileDialog::BaseDialogDelegate
void CloseDialog() override;
// Display the local error message inside login window.
void DisplayErrorMessage();
private:
ReauthDelegate();
UserManagerProfileDialogDelegate();
// Before its destruction, tells its parent container to reset its reference
// to the ReauthDelegate.
void OnReauthDialogDestroyed();
// to the UserManagerProfileDialogDelegate.
void OnDialogDestroyed();
// views::DialogDelegate:
gfx::Size GetPreferredSize() const override;
......@@ -57,7 +58,7 @@ class ReauthDelegate : public views::DialogDelegateView,
views::WebView* web_view_;
const std::string email_address_;
DISALLOW_COPY_AND_ASSIGN(ReauthDelegate);
DISALLOW_COPY_AND_ASSIGN(UserManagerProfileDialogDelegate);
};
namespace views {
......@@ -85,20 +86,14 @@ class UserManagerView : public views::DialogDelegateView {
// Logs how long it took the UserManager to open.
void LogTimeToOpen();
// Shows a dialog where the user can re-authenticate the profile with the
// given |email|. This is called in the following scenarios:
// -From the user manager when a profile is locked and the user's password is
// detected to have been changed.
// -From the user manager when a custodian account needs to be
// reauthenticated.
// reason| can be REASON_UNLOCK or REASON_REAUTHENTICATION to indicate
// whether this is a reauth or unlock scenario.
void ShowReauthDialog(content::BrowserContext* browser_context,
const std::string& email,
signin_metrics::Reason reason);
// Hides the reauth dialog if it is showing.
void HideReauthDialog();
void HideDialog();
// Show a dialog where the user can auth the profile or see the auth error
// message.
void ShowDialog(content::BrowserContext* browser_context,
const std::string& email,
const GURL& url);
// Display sign in error message that is created by Chrome but not GAIA
// without browser window.
......@@ -110,13 +105,13 @@ class UserManagerView : public views::DialogDelegateView {
base::FilePath GetSigninProfilePath();
private:
friend class ReauthDelegate;
friend class UserManagerProfileDialogDelegate;
friend std::default_delete<UserManagerView>;
~UserManagerView() override;
// Resets delegate_ to nullptr when delegate_ is no longer alive.
void OnReauthDialogDestroyed();
void OnDialogDestroyed();
// Creates dialog and initializes UI.
void Init(Profile* guest_profile, const GURL& url);
......@@ -136,7 +131,7 @@ class UserManagerView : public views::DialogDelegateView {
views::WebView* web_view_;
ReauthDelegate* delegate_;
UserManagerProfileDialogDelegate* delegate_;
std::unique_ptr<ScopedKeepAlive> keep_alive_;
base::Time user_manager_started_showing_;
......
......@@ -26,7 +26,8 @@ namespace {
void ShowSigninDialog(base::FilePath signin_profile_path,
Profile* system_profile,
Profile::CreateStatus status) {
UserManager::ShowSigninDialog(system_profile, signin_profile_path);
UserManagerProfileDialog::ShowSigninDialog(system_profile,
signin_profile_path);
}
void DeleteProfileCallback(std::unique_ptr<ScopedKeepAlive> keep_alive,
......
......@@ -285,5 +285,5 @@ void InlineLoginHandler::HandleDialogClose(const base::ListValue* args) {
browser->CloseModalSigninWindow();
// Does nothing if user manager is not showing.
UserManager::HideReauthDialog();
UserManagerProfileDialog::HideDialog();
}
......@@ -77,7 +77,7 @@ void LoginUIService::DisplayLoginResult(Browser* browser,
if (browser)
browser->ShowModalSigninErrorWindow();
else
UserManager::DisplayErrorMessage();
UserManagerProfileDialog::DisplayErrorMessage();
} else if (browser) {
browser->window()->ShowAvatarBubbleFromAvatarButton(
error_message.empty() ? BrowserWindow::AVATAR_BUBBLE_MODE_CONFIRM_SIGNIN
......
......@@ -429,8 +429,8 @@ void SigninCreateProfileHandler::OpenNewWindowForProfile(
}
void SigninCreateProfileHandler::OpenSigninDialogForProfile(Profile* profile) {
UserManager::ShowSigninDialog(web_ui()->GetWebContents()->GetBrowserContext(),
profile->GetPath());
UserManagerProfileDialog::ShowSigninDialog(
web_ui()->GetWebContents()->GetBrowserContext(), profile->GetPath());
}
void SigninCreateProfileHandler::ShowProfileCreationError(
......
......@@ -83,7 +83,7 @@ void SigninErrorHandler::CloseDialog() {
if (is_system_profile_) {
// Avoid closing the user manager window when the error message is displayed
// without browser window.
UserManager::HideReauthDialog();
UserManagerProfileDialog::HideDialog();
} else {
Browser* browser = signin::GetDesktopBrowser(web_ui());
DCHECK(browser);
......
......@@ -42,6 +42,9 @@ SigninErrorUI::SigninErrorUI(content::WebUI* web_ui,
if (is_system_profile) {
signin_profile = g_browser_process->profile_manager()->GetProfileByPath(
UserManager::GetSigninProfilePath());
// Sign in is completed before profile creation.
if (!signin_profile)
signin_profile = webui_profile->GetOriginalProfile();
} else {
signin_profile = webui_profile;
}
......
......@@ -139,7 +139,7 @@ void SigninSupervisedUserImportHandler::AuthenticateCustodian(
bool success = args->GetString(0, &email);
DCHECK(success);
UserManager::ShowReauthDialog(
UserManagerProfileDialog::ShowReauthDialog(
web_ui()->GetWebContents()->GetBrowserContext(), email,
signin_metrics::Reason::REASON_REAUTHENTICATION);
}
......
......@@ -43,6 +43,8 @@
#include "chrome/browser/ui/singleton_tabs.h"
#include "chrome/browser/ui/user_manager.h"
#include "chrome/browser/ui/webui/profile_helper.h"
#include "chrome/browser/ui/webui/signin/login_ui_service.h"
#include "chrome/browser/ui/webui/signin/login_ui_service_factory.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
......@@ -462,11 +464,22 @@ void UserManagerScreenHandler::HandleAuthenticatedLaunchUser(
if (!email_address_.empty()) {
// In order to support the upgrade case where we have a local hash but no
// password token, the user must perform a full online reauth.
UserManager::ShowReauthDialog(browser_context, email_address_,
signin_metrics::Reason::REASON_UNLOCK);
UserManagerProfileDialog::ShowReauthDialog(
browser_context, email_address_, signin_metrics::Reason::REASON_UNLOCK);
} else if (entry->IsSigninRequired() && entry->IsSupervised()) {
// Supervised profile will only be locked when force-sign-in is enabled
// and it shouldn't be unlocked. Display the error message directly via
// the system profile to avoid profile creation.
LoginUIServiceFactory::GetForProfile(
Profile::FromWebUI(web_ui())->GetOriginalProfile())
->DisplayLoginResult(nullptr,
l10n_util::GetStringUTF16(
IDS_SUPERVISED_USER_NOT_ALLOWED_BY_POLICY),
base::string16());
UserManagerProfileDialog::ShowDialogAndDisplayErrorMessage(browser_context);
} else {
// Fresh sign in via user manager without existing email address.
UserManager::ShowSigninDialog(browser_context, profile_path);
UserManagerProfileDialog::ShowSigninDialog(browser_context, profile_path);
}
}
......@@ -691,9 +704,9 @@ void UserManagerScreenHandler::OnOAuthError() {
// Password has changed. Go through online signin flow.
DCHECK(!email_address_.empty());
oauth_client_.reset();
UserManager::ShowReauthDialog(web_ui()->GetWebContents()->GetBrowserContext(),
email_address_,
signin_metrics::Reason::REASON_UNLOCK);
UserManagerProfileDialog::ShowReauthDialog(
web_ui()->GetWebContents()->GetBrowserContext(), email_address_,
signin_metrics::Reason::REASON_UNLOCK);
}
void UserManagerScreenHandler::OnNetworkError(int response_code) {
......
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