| // 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/extensions/chrome_extension_web_contents_observer.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/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/webui/signin/sync_confirmation_ui.h" |
| #include "chrome/common/url_constants.h" |
| #include "components/constrained_window/constrained_window_views.h" |
| #include "components/unified_consent/feature.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 kModalDialogWidth = 448; |
| const int kModalDialogWidthForUnifiedConsent = 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) { |
| // If unified consent is enabled, we show a different sync confirmation dialog |
| // which uses a different width. |
| return unified_consent::IsUnifiedConsentFeatureEnabled() && |
| profile->IsSyncAllowed() |
| ? kModalDialogWidthForUnifiedConsent |
| : 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) |
| : signin_view_controller_(signin_view_controller), |
| web_contents_(content_view->GetWebContents()), |
| browser_(browser), |
| content_view_(content_view.release()), |
| modal_signin_widget_(nullptr), |
| dialog_modal_type_(dialog_modal_type) { |
| DCHECK(web_contents_); |
| DCHECK(browser_); |
| DCHECK(browser_->tab_strip_model()->GetActiveWebContents()) |
| << "A tab must be active to present the sign-in modal dialog."; |
| web_contents_->SetDelegate(this); |
| |
| 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::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(); |
| } |
| } |
| |
| content::WebContents* SigninViewControllerDelegateViews::GetWebContents() { |
| return web_contents_; |
| } |
| |
| void SigninViewControllerDelegateViews::CloseModalSignin() { |
| ResetSigninViewControllerDelegate(); |
| if (modal_signin_widget_) |
| modal_signin_widget_->Close(); |
| } |
| |
| 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(); |
| } |
| |
| bool 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. |
| return unhandled_keyboard_event_handler_.HandleKeyboardEvent( |
| event, GetFocusManager()); |
| } |
| |
| bool SigninViewControllerDelegateViews::HandleContextMenu( |
| const content::ContextMenuParams& params) { |
| // Discard the context menu |
| return true; |
| } |
| |
| std::unique_ptr<views::WebView> |
| SigninViewControllerDelegateViews::CreateSyncConfirmationWebView( |
| Browser* browser) { |
| return CreateDialogWebView( |
| browser, 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)); |
| // To record metrics using javascript, extensions are needed. |
| extensions::ChromeExtensionWebContentsObserver::CreateForWebContents( |
| web_view->GetWebContents()); |
| |
| 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); |
| } |
| |
| web_modal::WebContentsModalDialogHost* |
| SigninViewControllerDelegateViews::GetWebContentsModalDialogHost() { |
| return browser()->window()->GetWebContentsModalDialogHost(); |
| } |
| |
| void SigninViewControllerDelegateViews::ResetSigninViewControllerDelegate() { |
| if (signin_view_controller_) { |
| signin_view_controller_->ResetModalSigninDelegate(); |
| signin_view_controller_ = nullptr; |
| } |
| } |
| |
| // -------------------------------------------------------------------- |
| // SigninViewControllerDelegate static methods |
| // -------------------------------------------------------------------- |
| |
| SigninViewControllerDelegate* |
| SigninViewControllerDelegate::CreateSyncConfirmationDelegate( |
| SigninViewController* signin_view_controller, |
| Browser* browser) { |
| return new SigninViewControllerDelegateViews( |
| signin_view_controller, |
| SigninViewControllerDelegateViews::CreateSyncConfirmationWebView(browser), |
| browser, ui::MODAL_TYPE_WINDOW, true); |
| } |
| |
| SigninViewControllerDelegate* |
| SigninViewControllerDelegate::CreateSigninErrorDelegate( |
| SigninViewController* signin_view_controller, |
| Browser* browser) { |
| return new SigninViewControllerDelegateViews( |
| signin_view_controller, |
| SigninViewControllerDelegateViews::CreateSigninErrorWebView(browser), |
| browser, ui::MODAL_TYPE_WINDOW, true); |
| } |