Commit 4963f793 authored by David Roger's avatar David Roger Committed by Commit Bot

[signin] Plumb Dice signin interception callback to the WebUI bubble

This CL adds a callback to the signin interception bubble.
The callback will be called when the user interacts with the inner
WebUI (in a follow-up CL) or when the bubble is closed.

Bug: 1076880
Change-Id: Ie09df4915965ea1b62c88b5569c7530936f13b2f
Cq-Do-Not-Cancel-Tryjobs: true
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2279197
Commit-Queue: David Roger <droger@chromium.org>
Reviewed-by: default avatarBret Sepulveda <bsep@chromium.org>
Reviewed-by: default avatarAlex Ilin <alexilin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#786279}
parent ef507e63
...@@ -31,5 +31,5 @@ void DiceWebSigninInterceptorDelegate::ShowSigninInterceptionBubble( ...@@ -31,5 +31,5 @@ void DiceWebSigninInterceptorDelegate::ShowSigninInterceptionBubble(
} }
ShowSigninInterceptionBubbleInternal( ShowSigninInterceptionBubbleInternal(
chrome::FindBrowserWithWebContents(web_contents)); chrome::FindBrowserWithWebContents(web_contents), std::move(callback));
} }
...@@ -31,7 +31,9 @@ class DiceWebSigninInterceptorDelegate ...@@ -31,7 +31,9 @@ class DiceWebSigninInterceptorDelegate
private: private:
// Implemented in dice_web_signin_interception_bubble_view.cc // Implemented in dice_web_signin_interception_bubble_view.cc
void ShowSigninInterceptionBubbleInternal(Browser* browser); void ShowSigninInterceptionBubbleInternal(
Browser* browser,
base::OnceCallback<void(bool)> callback);
}; };
#endif // CHROME_BROWSER_UI_SIGNIN_DICE_WEB_SIGNIN_INTERCEPTOR_DELEGATE_H_ #endif // CHROME_BROWSER_UI_SIGNIN_DICE_WEB_SIGNIN_INTERCEPTOR_DELEGATE_H_
...@@ -6,6 +6,8 @@ ...@@ -6,6 +6,8 @@
#include <memory> #include <memory>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/check.h" #include "base/check.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser.h"
...@@ -13,35 +15,46 @@ ...@@ -13,35 +15,46 @@
#include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/browser/ui/views/frame/toolbar_button_provider.h" #include "chrome/browser/ui/views/frame/toolbar_button_provider.h"
#include "chrome/browser/ui/views/profiles/avatar_toolbar_button.h" #include "chrome/browser/ui/views/profiles/avatar_toolbar_button.h"
#include "chrome/browser/ui/webui/signin/dice_web_signin_intercept_ui.h"
#include "chrome/common/webui_url_constants.h" #include "chrome/common/webui_url_constants.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui.h"
#include "ui/views/bubble/bubble_border.h" #include "ui/views/bubble/bubble_border.h"
#include "ui/views/controls/webview/webview.h" #include "ui/views/controls/webview/webview.h"
#include "ui/views/layout/fill_layout.h" #include "ui/views/layout/fill_layout.h"
#include "ui/views/widget/widget.h"
namespace { namespace {
constexpr int kInterceptionBubbleHeight = 362; constexpr int kInterceptionBubbleHeight = 362;
constexpr int kInterceptionBubbleWidth = 290; constexpr int kInterceptionBubbleWidth = 290;
} // namespace } // namespace
DiceWebSigninInterceptionBubbleView::~DiceWebSigninInterceptionBubbleView() = DiceWebSigninInterceptionBubbleView::~DiceWebSigninInterceptionBubbleView() {
default; // Cancel if the bubble is destroyed without user interaction.
if (callback_)
std::move(callback_).Run(false);
}
// static // static
void DiceWebSigninInterceptionBubbleView::CreateBubble( void DiceWebSigninInterceptionBubbleView::CreateBubble(
content::BrowserContext* browser_context, content::BrowserContext* browser_context,
views::View* anchor_view) { views::View* anchor_view,
base::OnceCallback<void(bool)> callback) {
// The widget is owned by the views system. // The widget is owned by the views system.
views::Widget* widget = views::BubbleDialogDelegateView::CreateBubble( views::Widget* widget = views::BubbleDialogDelegateView::CreateBubble(
new DiceWebSigninInterceptionBubbleView(browser_context, anchor_view)); new DiceWebSigninInterceptionBubbleView(browser_context, anchor_view,
std::move(callback)));
// TODO(droger): Delay showing the bubble until the web view is loaded. // TODO(droger): Delay showing the bubble until the web view is loaded.
widget->Show(); widget->Show();
} }
DiceWebSigninInterceptionBubbleView::DiceWebSigninInterceptionBubbleView( DiceWebSigninInterceptionBubbleView::DiceWebSigninInterceptionBubbleView(
content::BrowserContext* browser_context, content::BrowserContext* browser_context,
views::View* anchor_view) views::View* anchor_view,
base::OnceCallback<void(bool)> callback)
: views::BubbleDialogDelegateView(anchor_view, : views::BubbleDialogDelegateView(anchor_view,
views::BubbleBorder::TOP_RIGHT) { views::BubbleBorder::TOP_RIGHT),
callback_(std::move(callback)) {
DCHECK(browser_context); DCHECK(browser_context);
// Create the web view in the native bubble. // Create the web view in the native bubble.
...@@ -50,6 +63,15 @@ DiceWebSigninInterceptionBubbleView::DiceWebSigninInterceptionBubbleView( ...@@ -50,6 +63,15 @@ DiceWebSigninInterceptionBubbleView::DiceWebSigninInterceptionBubbleView(
web_view->LoadInitialURL(GURL(chrome::kChromeUIDiceWebSigninInterceptURL)); web_view->LoadInitialURL(GURL(chrome::kChromeUIDiceWebSigninInterceptURL));
web_view->SetPreferredSize( web_view->SetPreferredSize(
gfx::Size(kInterceptionBubbleWidth, kInterceptionBubbleHeight)); gfx::Size(kInterceptionBubbleWidth, kInterceptionBubbleHeight));
DiceWebSigninInterceptUI* web_ui = web_view->GetWebContents()
->GetWebUI()
->GetController()
->GetAs<DiceWebSigninInterceptUI>();
DCHECK(web_ui);
// Unretained is fine because this outlives the inner web UI.
web_ui->Initialize(
base::BindOnce(&DiceWebSigninInterceptionBubbleView::OnWebUIUserChoice,
base::Unretained(this)));
AddChildView(std::move(web_view)); AddChildView(std::move(web_view));
set_margins(gfx::Insets()); set_margins(gfx::Insets());
...@@ -57,15 +79,23 @@ DiceWebSigninInterceptionBubbleView::DiceWebSigninInterceptionBubbleView( ...@@ -57,15 +79,23 @@ DiceWebSigninInterceptionBubbleView::DiceWebSigninInterceptionBubbleView(
SetLayoutManager(std::make_unique<views::FillLayout>()); SetLayoutManager(std::make_unique<views::FillLayout>());
} }
void DiceWebSigninInterceptionBubbleView::OnWebUIUserChoice(bool accept) {
std::move(callback_).Run(accept);
GetWidget()->CloseWithReason(
accept ? views::Widget::ClosedReason::kAcceptButtonClicked
: views::Widget::ClosedReason::kCancelButtonClicked);
}
// DiceWebSigninInterceptorDelegate -------------------------------------------- // DiceWebSigninInterceptorDelegate --------------------------------------------
void DiceWebSigninInterceptorDelegate::ShowSigninInterceptionBubbleInternal( void DiceWebSigninInterceptorDelegate::ShowSigninInterceptionBubbleInternal(
Browser* browser) { Browser* browser,
base::OnceCallback<void(bool)> callback) {
DCHECK(browser); DCHECK(browser);
views::View* anchor_view = BrowserView::GetBrowserViewForBrowser(browser) views::View* anchor_view = BrowserView::GetBrowserViewForBrowser(browser)
->toolbar_button_provider() ->toolbar_button_provider()
->GetAvatarToolbarButton(); ->GetAvatarToolbarButton();
DCHECK(anchor_view); DCHECK(anchor_view);
DiceWebSigninInterceptionBubbleView::CreateBubble(browser->profile(), DiceWebSigninInterceptionBubbleView::CreateBubble(
anchor_view); browser->profile(), anchor_view, std::move(callback));
} }
...@@ -7,6 +7,9 @@ ...@@ -7,6 +7,9 @@
#include "ui/views/bubble/bubble_dialog_delegate_view.h" #include "ui/views/bubble/bubble_dialog_delegate_view.h"
#include "base/callback.h"
#include "base/gtest_prod_util.h"
namespace content { namespace content {
class BrowserContext; class BrowserContext;
} }
...@@ -28,11 +31,22 @@ class DiceWebSigninInterceptionBubbleView ...@@ -28,11 +31,22 @@ class DiceWebSigninInterceptionBubbleView
const DiceWebSigninInterceptionBubbleView& other) = delete; const DiceWebSigninInterceptionBubbleView& other) = delete;
static void CreateBubble(content::BrowserContext* browser_context, static void CreateBubble(content::BrowserContext* browser_context,
views::View* anchor_view); views::View* anchor_view,
base::OnceCallback<void(bool)> callback);
private: private:
FRIEND_TEST_ALL_PREFIXES(DiceWebSigninInterceptionBubbleBrowserTest,
BubbleClosed);
DiceWebSigninInterceptionBubbleView(content::BrowserContext* browser_context, DiceWebSigninInterceptionBubbleView(content::BrowserContext* browser_context,
views::View* anchor_view); views::View* anchor_view,
base::OnceCallback<void(bool)> callback);
// This bubble has no native buttons. The user accepts or cancels through this
// method, which is called by the inner web UI.
void OnWebUIUserChoice(bool accept);
base::OnceCallback<void(bool)> callback_;
}; };
#endif // CHROME_BROWSER_UI_VIEWS_PROFILES_DICE_WEB_SIGNIN_INTERCEPTION_BUBBLE_VIEW_H_ #endif // CHROME_BROWSER_UI_VIEWS_PROFILES_DICE_WEB_SIGNIN_INTERCEPTION_BUBBLE_VIEW_H_
...@@ -6,12 +6,16 @@ ...@@ -6,12 +6,16 @@
#include <string> #include <string>
#include "base/optional.h"
#include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/test/test_browser_dialog.h" #include "chrome/browser/ui/test/test_browser_dialog.h"
#include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/browser/ui/views/frame/toolbar_button_provider.h" #include "chrome/browser/ui/views/frame/toolbar_button_provider.h"
#include "chrome/browser/ui/views/profiles/avatar_toolbar_button.h" #include "chrome/browser/ui/views/profiles/avatar_toolbar_button.h"
#include "content/public/test/browser_test.h" #include "content/public/test/browser_test.h"
#include "ui/views/bubble/bubble_dialog_delegate_view.h"
#include "ui/views/test/widget_test.h"
#include "ui/views/widget/widget.h"
class DiceWebSigninInterceptionBubbleBrowserTest : public DialogBrowserTest { class DiceWebSigninInterceptionBubbleBrowserTest : public DialogBrowserTest {
public: public:
...@@ -19,16 +23,51 @@ class DiceWebSigninInterceptionBubbleBrowserTest : public DialogBrowserTest { ...@@ -19,16 +23,51 @@ class DiceWebSigninInterceptionBubbleBrowserTest : public DialogBrowserTest {
// DialogBrowserTest: // DialogBrowserTest:
void ShowUi(const std::string& name) override { void ShowUi(const std::string& name) override {
BrowserView* browser_view = static_cast<BrowserView*>(browser()->window()); DiceWebSigninInterceptionBubbleView::CreateBubble(
browser()->profile(), GetAvatarButton(),
base::OnceCallback<void(bool)>());
}
// Returns the avatar button, which is the anchor view for the interception
// bubble.
views::View* GetAvatarButton() {
BrowserView* browser_view =
BrowserView::GetBrowserViewForBrowser(browser());
views::View* avatar_button = views::View* avatar_button =
browser_view->toolbar_button_provider()->GetAvatarToolbarButton(); browser_view->toolbar_button_provider()->GetAvatarToolbarButton();
DCHECK(avatar_button); DCHECK(avatar_button);
DiceWebSigninInterceptionBubbleView::CreateBubble(browser()->profile(), return avatar_button;
avatar_button);
} }
// Completion callback for the interception bubble.
void OnInterceptionComplete(bool accept) {
DCHECK(!callback_result_.has_value());
callback_result_ = accept;
}
base::Optional<bool> callback_result_;
}; };
IN_PROC_BROWSER_TEST_F(DiceWebSigninInterceptionBubbleBrowserTest, IN_PROC_BROWSER_TEST_F(DiceWebSigninInterceptionBubbleBrowserTest,
InvokeUi_default) { InvokeUi_default) {
ShowAndVerifyUi(); ShowAndVerifyUi();
} }
// Tests that the callback is called once when the bubble is closed.
IN_PROC_BROWSER_TEST_F(DiceWebSigninInterceptionBubbleBrowserTest,
BubbleClosed) {
views::Widget* widget = views::BubbleDialogDelegateView::CreateBubble(
new DiceWebSigninInterceptionBubbleView(
browser()->profile(), GetAvatarButton(),
base::BindOnce(&DiceWebSigninInterceptionBubbleBrowserTest::
OnInterceptionComplete,
base::Unretained(this))));
widget->Show();
EXPECT_FALSE(callback_result_.has_value());
views::test::WidgetDestroyedWaiter waiter(widget);
widget->CloseWithReason(views::Widget::ClosedReason::kUnspecified);
waiter.Wait();
ASSERT_TRUE(callback_result_.has_value());
EXPECT_FALSE(callback_result_.value());
}
...@@ -18,3 +18,10 @@ DiceWebSigninInterceptUI::DiceWebSigninInterceptUI(content::WebUI* web_ui) ...@@ -18,3 +18,10 @@ DiceWebSigninInterceptUI::DiceWebSigninInterceptUI(content::WebUI* web_ui)
} }
DiceWebSigninInterceptUI::~DiceWebSigninInterceptUI() = default; DiceWebSigninInterceptUI::~DiceWebSigninInterceptUI() = default;
void DiceWebSigninInterceptUI::Initialize(
base::OnceCallback<void(bool)> callback) {
// TODO(droger): add a handler and call the callback based on user action.
}
WEB_UI_CONTROLLER_TYPE_IMPL(DiceWebSigninInterceptUI)
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
#include "content/public/browser/web_ui_controller.h" #include "content/public/browser/web_ui_controller.h"
#include "base/callback.h"
namespace content { namespace content {
class WebUI; class WebUI;
} }
...@@ -18,6 +20,12 @@ class DiceWebSigninInterceptUI : public content::WebUIController { ...@@ -18,6 +20,12 @@ class DiceWebSigninInterceptUI : public content::WebUIController {
DiceWebSigninInterceptUI(const DiceWebSigninInterceptUI&) = delete; DiceWebSigninInterceptUI(const DiceWebSigninInterceptUI&) = delete;
DiceWebSigninInterceptUI& operator=(const DiceWebSigninInterceptUI&) = delete; DiceWebSigninInterceptUI& operator=(const DiceWebSigninInterceptUI&) = delete;
// Initializes the DiceWebSigninInterceptUI.
void Initialize(base::OnceCallback<void(bool)> callback);
private:
WEB_UI_CONTROLLER_TYPE_DECL();
}; };
#endif // CHROME_BROWSER_UI_WEBUI_SIGNIN_DICE_WEB_SIGNIN_INTERCEPT_UI_H_ #endif // CHROME_BROWSER_UI_WEBUI_SIGNIN_DICE_WEB_SIGNIN_INTERCEPT_UI_H_
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