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(
}
ShowSigninInterceptionBubbleInternal(
chrome::FindBrowserWithWebContents(web_contents));
chrome::FindBrowserWithWebContents(web_contents), std::move(callback));
}
......@@ -31,7 +31,9 @@ class DiceWebSigninInterceptorDelegate
private:
// 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_
......@@ -6,6 +6,8 @@
#include <memory>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/check.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
......@@ -13,35 +15,46 @@
#include "chrome/browser/ui/views/frame/browser_view.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/webui/signin/dice_web_signin_intercept_ui.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/controls/webview/webview.h"
#include "ui/views/layout/fill_layout.h"
#include "ui/views/widget/widget.h"
namespace {
constexpr int kInterceptionBubbleHeight = 362;
constexpr int kInterceptionBubbleWidth = 290;
} // namespace
DiceWebSigninInterceptionBubbleView::~DiceWebSigninInterceptionBubbleView() =
default;
DiceWebSigninInterceptionBubbleView::~DiceWebSigninInterceptionBubbleView() {
// Cancel if the bubble is destroyed without user interaction.
if (callback_)
std::move(callback_).Run(false);
}
// static
void DiceWebSigninInterceptionBubbleView::CreateBubble(
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.
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.
widget->Show();
}
DiceWebSigninInterceptionBubbleView::DiceWebSigninInterceptionBubbleView(
content::BrowserContext* browser_context,
views::View* anchor_view)
views::View* anchor_view,
base::OnceCallback<void(bool)> callback)
: views::BubbleDialogDelegateView(anchor_view,
views::BubbleBorder::TOP_RIGHT) {
views::BubbleBorder::TOP_RIGHT),
callback_(std::move(callback)) {
DCHECK(browser_context);
// Create the web view in the native bubble.
......@@ -50,6 +63,15 @@ DiceWebSigninInterceptionBubbleView::DiceWebSigninInterceptionBubbleView(
web_view->LoadInitialURL(GURL(chrome::kChromeUIDiceWebSigninInterceptURL));
web_view->SetPreferredSize(
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));
set_margins(gfx::Insets());
......@@ -57,15 +79,23 @@ DiceWebSigninInterceptionBubbleView::DiceWebSigninInterceptionBubbleView(
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 --------------------------------------------
void DiceWebSigninInterceptorDelegate::ShowSigninInterceptionBubbleInternal(
Browser* browser) {
Browser* browser,
base::OnceCallback<void(bool)> callback) {
DCHECK(browser);
views::View* anchor_view = BrowserView::GetBrowserViewForBrowser(browser)
->toolbar_button_provider()
->GetAvatarToolbarButton();
DCHECK(anchor_view);
DiceWebSigninInterceptionBubbleView::CreateBubble(browser->profile(),
anchor_view);
DiceWebSigninInterceptionBubbleView::CreateBubble(
browser->profile(), anchor_view, std::move(callback));
}
......@@ -7,6 +7,9 @@
#include "ui/views/bubble/bubble_dialog_delegate_view.h"
#include "base/callback.h"
#include "base/gtest_prod_util.h"
namespace content {
class BrowserContext;
}
......@@ -28,11 +31,22 @@ class DiceWebSigninInterceptionBubbleView
const DiceWebSigninInterceptionBubbleView& other) = delete;
static void CreateBubble(content::BrowserContext* browser_context,
views::View* anchor_view);
views::View* anchor_view,
base::OnceCallback<void(bool)> callback);
private:
FRIEND_TEST_ALL_PREFIXES(DiceWebSigninInterceptionBubbleBrowserTest,
BubbleClosed);
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_
......@@ -6,12 +6,16 @@
#include <string>
#include "base/optional.h"
#include "chrome/browser/ui/browser.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/toolbar_button_provider.h"
#include "chrome/browser/ui/views/profiles/avatar_toolbar_button.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 {
public:
......@@ -19,16 +23,51 @@ class DiceWebSigninInterceptionBubbleBrowserTest : public DialogBrowserTest {
// DialogBrowserTest:
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 =
browser_view->toolbar_button_provider()->GetAvatarToolbarButton();
DCHECK(avatar_button);
DiceWebSigninInterceptionBubbleView::CreateBubble(browser()->profile(),
avatar_button);
return 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,
InvokeUi_default) {
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)
}
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 @@
#include "content/public/browser/web_ui_controller.h"
#include "base/callback.h"
namespace content {
class WebUI;
}
......@@ -18,6 +20,12 @@ class DiceWebSigninInterceptUI : public content::WebUIController {
DiceWebSigninInterceptUI(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_
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