blob: d65f3b14826cc43c0a7cf630eb3ff9af373aaa71 [file] [log] [blame]
// Copyright 2016 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/profiles/signin_view_controller_delegate_views.h"
#include "base/macros.h"
#include "build/build_config.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_avatar_icon_util.h"
#include "chrome/browser/signin/signin_promo.h"
#include "chrome/browser/signin/unified_consent_helper.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/browser/ui/views_mode_controller.h"
#include "chrome/browser/ui/webui/signin/sync_confirmation_ui.h"
#include "chrome/common/url_constants.h"
#include "components/constrained_window/constrained_window_views.h"
#include "components/web_modal/web_contents_modal_dialog_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents.h"
#include "ui/views/controls/webview/webview.h"
#include "ui/views/widget/widget.h"
namespace {
const int kFixedGaiaViewHeight = 612;
const int kModalDialogWidth = 448;
const int kModalDialogWidthForDice = 512;
const int kSyncConfirmationDialogHeight = 487;
const int kSigninErrorDialogHeight = 164;
int GetSyncConfirmationDialogPreferredHeight(Profile* profile) {
// If sync is disabled, then the sync confirmation dialog looks like an error
// dialog and thus it has the same preferred size.
return profile->IsSyncAllowed() ? kSyncConfirmationDialogHeight
: kSigninErrorDialogHeight;
}
int GetSyncConfirmationDialogPreferredWidth(Profile* profile) {
// With Unity-enabled profiles, we show a different sync confirmation dialog
// which uses a different width.
return IsUnifiedConsentEnabled(profile) && profile->IsSyncAllowed()
? kModalDialogWidthForDice
: kModalDialogWidth;
}
} // namespace
SigninViewControllerDelegateViews::SigninViewControllerDelegateViews(
SigninViewController* signin_view_controller,
std::unique_ptr<views::WebView> content_view,
Browser* browser,
ui::ModalType dialog_modal_type,
bool wait_for_size)
: SigninViewControllerDelegate(signin_view_controller,
content_view->GetWebContents(),
browser),
content_view_(content_view.release()),
modal_signin_widget_(nullptr),
dialog_modal_type_(dialog_modal_type) {
DCHECK(dialog_modal_type == ui::MODAL_TYPE_CHILD ||
dialog_modal_type == ui::MODAL_TYPE_WINDOW)
<< "Unsupported dialog modal type " << dialog_modal_type;
if (!wait_for_size)
DisplayModal();
}
SigninViewControllerDelegateViews::~SigninViewControllerDelegateViews() {}
// views::DialogDelegateView:
views::View* SigninViewControllerDelegateViews::GetContentsView() {
return content_view_;
}
views::Widget* SigninViewControllerDelegateViews::GetWidget() {
return content_view_->GetWidget();
}
const views::Widget* SigninViewControllerDelegateViews::GetWidget() const {
return content_view_->GetWidget();
}
void SigninViewControllerDelegateViews::DeleteDelegate() {
ResetSigninViewControllerDelegate();
delete this;
}
ui::ModalType SigninViewControllerDelegateViews::GetModalType() const {
return dialog_modal_type_;
}
bool SigninViewControllerDelegateViews::ShouldShowCloseButton() const {
return false;
}
int SigninViewControllerDelegateViews::GetDialogButtons() const {
return ui::DIALOG_BUTTON_NONE;
}
void SigninViewControllerDelegateViews::PerformClose() {
if (modal_signin_widget_)
modal_signin_widget_->Close();
}
void SigninViewControllerDelegateViews::ResizeNativeView(int height) {
int max_height = browser()
->window()
->GetWebContentsModalDialogHost()
->GetMaximumDialogSize()
.height();
content_view_->SetPreferredSize(gfx::Size(
content_view_->GetPreferredSize().width(), std::min(height, max_height)));
if (!modal_signin_widget_) {
// The modal wasn't displayed yet so just show it with the already resized
// view.
DisplayModal();
}
}
void SigninViewControllerDelegateViews::HandleKeyboardEvent(
content::WebContents* source,
const content::NativeWebKeyboardEvent& event) {
// If this is a MODAL_TYPE_CHILD, then GetFocusManager() will return the focus
// manager of the parent window, which has registered accelerators, and the
// accelerators will fire. If this is a MODAL_TYPE_WINDOW, then this will have
// no effect, since no accelerators have been registered for this standalone
// window.
unhandled_keyboard_event_handler_.HandleKeyboardEvent(event,
GetFocusManager());
}
void SigninViewControllerDelegateViews::DisplayModal() {
DCHECK(!modal_signin_widget_);
content::WebContents* host_web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
// Avoid displaying the sign-in modal view if there are no active web
// contents. This happens if the user closes the browser window before this
// dialog has a chance to be displayed.
if (!host_web_contents)
return;
gfx::NativeWindow window = host_web_contents->GetTopLevelNativeWindow();
switch (dialog_modal_type_) {
case ui::MODAL_TYPE_WINDOW:
modal_signin_widget_ =
constrained_window::CreateBrowserModalDialogViews(this, window);
modal_signin_widget_->Show();
break;
case ui::MODAL_TYPE_CHILD:
modal_signin_widget_ = constrained_window::ShowWebModalDialogViews(
this, browser()->tab_strip_model()->GetActiveWebContents());
break;
default:
NOTREACHED() << "Unsupported dialog modal type " << dialog_modal_type_;
}
content_view_->RequestFocus();
}
// static
std::unique_ptr<views::WebView>
SigninViewControllerDelegateViews::CreateGaiaWebView(
content::WebContentsDelegate* delegate,
profiles::BubbleViewMode mode,
Browser* browser,
signin_metrics::AccessPoint access_point) {
GURL url =
signin::GetSigninURLFromBubbleViewMode(
browser->profile(), mode, access_point);
int max_height = browser
->window()
->GetWebContentsModalDialogHost()
->GetMaximumDialogSize().height();
// Adds Gaia signin webview.
const gfx::Size pref_size(kModalDialogWidth,
std::min(kFixedGaiaViewHeight, max_height));
views::WebView* web_view = new views::WebView(browser->profile());
web_view->LoadInitialURL(url);
if (delegate)
web_view->GetWebContents()->SetDelegate(delegate);
web_view->SetPreferredSize(pref_size);
content::RenderWidgetHostView* rwhv =
web_view->GetWebContents()->GetRenderWidgetHostView();
if (rwhv)
rwhv->SetBackgroundColor(profiles::kAvatarBubbleGaiaBackgroundColor);
return std::unique_ptr<views::WebView>(web_view);
}
std::unique_ptr<views::WebView>
SigninViewControllerDelegateViews::CreateSyncConfirmationWebView(
Browser* browser,
bool is_consent_bump) {
return CreateDialogWebView(
browser,
is_consent_bump ? chrome::kChromeUISyncConsentBumpURL
: chrome::kChromeUISyncConfirmationURL,
GetSyncConfirmationDialogPreferredHeight(browser->profile()),
GetSyncConfirmationDialogPreferredWidth(browser->profile()));
}
std::unique_ptr<views::WebView>
SigninViewControllerDelegateViews::CreateSigninErrorWebView(Browser* browser) {
return CreateDialogWebView(browser, chrome::kChromeUISigninErrorURL,
kSigninErrorDialogHeight, base::nullopt);
}
std::unique_ptr<views::WebView>
SigninViewControllerDelegateViews::CreateDialogWebView(
Browser* browser,
const std::string& url,
int dialog_height,
base::Optional<int> opt_width) {
int dialog_width = opt_width.value_or(kModalDialogWidth);
views::WebView* web_view = new views::WebView(browser->profile());
web_view->LoadInitialURL(GURL(url));
SigninWebDialogUI* web_dialog_ui = static_cast<SigninWebDialogUI*>(
web_view->GetWebContents()->GetWebUI()->GetController());
web_dialog_ui->InitializeMessageHandlerWithBrowser(browser);
int max_height = browser->window()
->GetWebContentsModalDialogHost()
->GetMaximumDialogSize()
.height();
web_view->SetPreferredSize(
gfx::Size(dialog_width, std::min(dialog_height, max_height)));
return std::unique_ptr<views::WebView>(web_view);
}
SigninViewControllerDelegate*
SigninViewControllerDelegate::CreateModalSigninDelegate(
SigninViewController* signin_view_controller,
profiles::BubbleViewMode mode,
Browser* browser,
signin_metrics::AccessPoint access_point) {
#if defined(OS_MACOSX)
if (views_mode_controller::IsViewsBrowserCocoa()) {
return CreateModalSigninDelegateCocoa(signin_view_controller, mode, browser,
access_point);
}
#endif
return new SigninViewControllerDelegateViews(
signin_view_controller,
SigninViewControllerDelegateViews::CreateGaiaWebView(
nullptr, mode, browser, access_point),
browser, ui::MODAL_TYPE_CHILD, false);
}
SigninViewControllerDelegate*
SigninViewControllerDelegate::CreateSyncConfirmationDelegate(
SigninViewController* signin_view_controller,
Browser* browser,
bool is_consent_bump) {
#if defined(OS_MACOSX)
if (views_mode_controller::IsViewsBrowserCocoa()) {
return CreateSyncConfirmationDelegateCocoa(signin_view_controller, browser,
is_consent_bump);
}
#endif
return new SigninViewControllerDelegateViews(
signin_view_controller,
SigninViewControllerDelegateViews::CreateSyncConfirmationWebView(
browser, is_consent_bump),
browser, ui::MODAL_TYPE_WINDOW, true);
}
SigninViewControllerDelegate*
SigninViewControllerDelegate::CreateSigninErrorDelegate(
SigninViewController* signin_view_controller,
Browser* browser) {
#if defined(OS_MACOSX)
if (views_mode_controller::IsViewsBrowserCocoa()) {
return CreateSigninErrorDelegateCocoa(signin_view_controller, browser);
}
#endif
return new SigninViewControllerDelegateViews(
signin_view_controller,
SigninViewControllerDelegateViews::CreateSigninErrorWebView(browser),
browser, ui::MODAL_TYPE_WINDOW, true);
}