Commit 389dca5a authored by David Roger's avatar David Roger Committed by Commit Bot

[signin] Add avatar to signin interception bubble

This CL:
- plumbs the account info from C++ to javascript
- updates the javascript to show the avatar and name
- implements the WebUI handler and listen to account changes

Screenshot:
https://drive.google.com/file/d/1um4ddQvSLoDidpdOWKjk5gHDmfWG5vSy/view?usp=sharing

Screenshot in dark mode:
https://drive.google.com/file/d/1GstEo8oYBI7wLuTdxprIwJGlH4yiYWyR/view?usp=sharing
(Note that the account name does not have enough contrast, this will be
fixed later)

Bug: 1076880
Change-Id: I81f2b90723fafa25b33b4e326e6b2a17fc28dbb0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2315136
Commit-Queue: David Roger <droger@chromium.org>
Commit-Queue: Rebekah Potter <rbpotter@chromium.org>
Reviewed-by: default avatarRebekah Potter <rbpotter@chromium.org>
Reviewed-by: default avatarMonica Basta <msalama@chromium.org>
Auto-Submit: David Roger <droger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#792521}
parent 09143c2d
......@@ -9,7 +9,9 @@
<release seq="1">
<structures>
<if expr="is_win or is_macosx or desktop_linux or chromeos">
<structure name="IDR_SIGNIN_ICONS_JS" file="resources\signin\signin_icons.js" type="chrome_html" />
<structure name="IDR_SIGNIN_SHARED_CSS_JS" file="${root_gen_dir}\chrome\browser\resources\signin\signin_shared_css.js" use_base_dir="false" preprocess="true" type="chrome_html" />
<structure name="IDR_SIGNIN_VARS_CSS_JS" file="${root_gen_dir}\chrome\browser\resources\signin\signin_vars_css.js" use_base_dir="false" type="chrome_html" />
</if>
<if expr="not is_android">
<!-- New Tab Page WebUI. -->
......
......@@ -33,5 +33,8 @@ group("web_components") {
}
html_to_js("web_components_local") {
js_files = [ "signin_shared_css.js" ]
js_files = [
"signin_shared_css.js",
"signin_vars_css.js",
]
}
......@@ -16,7 +16,9 @@ js_type_check("closure_compile") {
js_library("dice_web_signin_intercept_app") {
deps = [
":dice_web_signin_intercept_browser_proxy",
"//third_party/polymer/v3_0/components-chromium/iron-icon",
"//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
"//ui/webui/resources/js:web_ui_listener_behavior.m",
]
}
......
......@@ -7,6 +7,7 @@
}
#header {
--avatar-position: 84px;
/**
* TODO(crbug.com/1076880): replace the hardcoded background color with the
* browser-provided one.
......@@ -15,6 +16,50 @@
border-radius: 8px;
margin: 8px;
min-height: 128px;
position: relative;
}
#accountName {
font-size: 15px;
font-weight: bold;
line-height: 18px;
margin: 16px auto 9px;
overflow: hidden;
text-align: center;
text-overflow: ellipsis;
white-space: nowrap;
}
.avatar {
--avatar-size: 60px;
border-radius: 50%;
height: var(--avatar-size);
position: absolute;
top: 43px;
width: var(--avatar-size);
}
#workBadge {
background-color: var(--signin-work-badge-background-color);
display: flex;
left: var(--avatar-position);
/** Ensure the work badge is on top */
z-index: 1;
}
#workBadge > iron-icon {
--work-icon-size: 36px;
/** Use dark color for dark mode */
color: var(--md-background-color);
height: var(--work-icon-size);
margin: auto;
width: var(--work-icon-size);
}
#userAvatar {
/** The user avatar may be transparent, add a background */
background-color: var(--md-background-color);
right: var(--avatar-position);
}
#body {
......@@ -35,7 +80,14 @@
font-size: 12px;
}
</style>
<div id="header"></div>
<div id="header">
<div id="accountName">[[accountInfo_.name]]</div>
<div class="avatar" id="workBadge">
<iron-icon class="icon" icon="signin:work"></iron-icon>
</div>
<img class="avatar" id="userAvatar" src="[[accountInfo_.pictureUrl]]">
</div>
<div id="body">
<div id="title">$i18n{diceWebSigninInterceptTitle}</div>
......
......@@ -3,18 +3,31 @@
// found in the LICENSE file.
import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
import './strings.m.js';
import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
import './signin_icons.js';
import './signin_shared_css.js';
import './signin_vars_css.js';
import './strings.m.js';
import {WebUIListenerBehavior} from 'chrome://resources/js/web_ui_listener_behavior.m.js';
import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
import {DiceWebSigninInterceptBrowserProxy, DiceWebSigninInterceptBrowserProxyImpl} from './dice_web_signin_intercept_browser_proxy.js';
import {AccountInfo, DiceWebSigninInterceptBrowserProxy, DiceWebSigninInterceptBrowserProxyImpl} from './dice_web_signin_intercept_browser_proxy.js';
Polymer({
is: 'dice-web-signin-intercept-app',
_template: html`{__html_template__}`,
behaviors: [
WebUIListenerBehavior,
],
properties: {
/** @private {AccountInfo} */
accountInfo_: Object,
},
/** @private {?DiceWebSigninInterceptBrowserProxy} */
diceWebSigninInterceptBrowserProxy_: null,
......@@ -22,6 +35,10 @@ Polymer({
attached() {
this.diceWebSigninInterceptBrowserProxy_ =
DiceWebSigninInterceptBrowserProxyImpl.getInstance();
this.diceWebSigninInterceptBrowserProxy_.pageLoaded().then(
info => this.handleAccountInfoChanged_(info));
this.addWebUIListener(
'account-info-changed', this.handleAccountInfoChanged_.bind(this));
},
/** @private */
......@@ -33,4 +50,13 @@ Polymer({
onCancel_() {
this.diceWebSigninInterceptBrowserProxy_.cancel();
},
/**
* Called when the account image changes.
* @param {!AccountInfo} info
* @private
*/
handleAccountInfoChanged_(info) {
this.accountInfo_ = info;
},
});
......@@ -6,7 +6,16 @@
* @fileoverview A helper object used by the dice web signin intercept bubble to
* interact with the browser.
*/
import {addSingletonGetter} from 'chrome://resources/js/cr.m.js';
import {addSingletonGetter, sendWithPromise} from 'chrome://resources/js/cr.m.js';
/**
* Account information sent from C++.
* @typedef {{
* name: string,
* pictureUrl: string,
* }}
*/
export let AccountInfo;
/** @interface */
export class DiceWebSigninInterceptBrowserProxy {
......@@ -15,6 +24,12 @@ export class DiceWebSigninInterceptBrowserProxy {
/** Called when the user cancels the interception. */
cancel() {}
/**
* Called when the page is loaded.
* @return {!Promise<!AccountInfo>}
* */
pageLoaded() {}
}
/** @implements {DiceWebSigninInterceptBrowserProxy} */
......@@ -28,6 +43,11 @@ export class DiceWebSigninInterceptBrowserProxyImpl {
cancel() {
chrome.send('cancel');
}
/** @override */
pageLoaded() {
return sendWithPromise('pageLoaded');
}
}
addSingletonGetter(DiceWebSigninInterceptBrowserProxyImpl);
// Copyright 2020 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.
import 'chrome://resources/polymer/v3_0/iron-iconset-svg/iron-iconset-svg.js';
const element = document.createElement('iron-iconset-svg');
element.name = 'signin';
element.innerHTML = `
<svg>
<defs>
<!-- Copied from iron-icons. -->
<g id="work">
<path d="M20 6h-4V4c0-1.11-.89-2-2-2h-4c-1.11 0-2 .89-2 2v2H4c-1.11 0-1.99.89-1.99 2L2 19c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V8c0-1.11-.89-2-2-2zm-6 0h-4V4h4v2z">
</path>
</g>
</defs>
</svg>`;
document.head.appendChild(element);
<custom-style>
<style>
html {
--signin-work-badge-background-color: rgb(242, 153, 0);
}
</style>
</custom-style>
// Copyright 2020 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.
import 'chrome://resources/cr_elements/shared_vars_css.m.js';
import 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
const $_documentContainer = document.createElement('template');
$_documentContainer.innerHTML = `{__html_template__}`;
document.head.appendChild($_documentContainer.content);
......@@ -31,5 +31,6 @@ void DiceWebSigninInterceptorDelegate::ShowSigninInterceptionBubble(
}
ShowSigninInterceptionBubbleInternal(
chrome::FindBrowserWithWebContents(web_contents), std::move(callback));
chrome::FindBrowserWithWebContents(web_contents), account_info,
std::move(callback));
}
......@@ -33,6 +33,7 @@ class DiceWebSigninInterceptorDelegate
// Implemented in dice_web_signin_interception_bubble_view.cc
void ShowSigninInterceptionBubbleInternal(
Browser* browser,
const AccountInfo& account_info,
base::OnceCallback<void(bool)> callback);
};
......
......@@ -39,11 +39,12 @@ DiceWebSigninInterceptionBubbleView::~DiceWebSigninInterceptionBubbleView() {
void DiceWebSigninInterceptionBubbleView::CreateBubble(
content::BrowserContext* browser_context,
views::View* anchor_view,
const AccountInfo& account_info,
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,
std::move(callback)));
new DiceWebSigninInterceptionBubbleView(
browser_context, anchor_view, account_info, std::move(callback)));
// TODO(droger): Delay showing the bubble until the web view is loaded.
widget->Show();
}
......@@ -51,6 +52,7 @@ void DiceWebSigninInterceptionBubbleView::CreateBubble(
DiceWebSigninInterceptionBubbleView::DiceWebSigninInterceptionBubbleView(
content::BrowserContext* browser_context,
views::View* anchor_view,
const AccountInfo& account_info,
base::OnceCallback<void(bool)> callback)
: views::BubbleDialogDelegateView(anchor_view,
views::BubbleBorder::TOP_RIGHT),
......@@ -70,6 +72,7 @@ DiceWebSigninInterceptionBubbleView::DiceWebSigninInterceptionBubbleView(
DCHECK(web_ui);
// Unretained is fine because this outlives the inner web UI.
web_ui->Initialize(
account_info,
base::BindOnce(&DiceWebSigninInterceptionBubbleView::OnWebUIUserChoice,
base::Unretained(this)));
AddChildView(std::move(web_view));
......@@ -90,6 +93,7 @@ void DiceWebSigninInterceptionBubbleView::OnWebUIUserChoice(bool accept) {
void DiceWebSigninInterceptorDelegate::ShowSigninInterceptionBubbleInternal(
Browser* browser,
const AccountInfo& account_info,
base::OnceCallback<void(bool)> callback) {
DCHECK(browser);
views::View* anchor_view = BrowserView::GetBrowserViewForBrowser(browser)
......@@ -97,5 +101,5 @@ void DiceWebSigninInterceptorDelegate::ShowSigninInterceptionBubbleInternal(
->GetAvatarToolbarButton();
DCHECK(anchor_view);
DiceWebSigninInterceptionBubbleView::CreateBubble(
browser->profile(), anchor_view, std::move(callback));
browser->profile(), anchor_view, account_info, std::move(callback));
}
......@@ -18,6 +18,8 @@ namespace views {
class View;
} // namespace views
struct AccountInfo;
// Bubble shown as part of Dice web signin interception. This bubble is
// implemented as a WebUI page rendered inside a native bubble.
class DiceWebSigninInterceptionBubbleView
......@@ -32,6 +34,7 @@ class DiceWebSigninInterceptionBubbleView
static void CreateBubble(content::BrowserContext* browser_context,
views::View* anchor_view,
const AccountInfo& account_info,
base::OnceCallback<void(bool)> callback);
private:
......@@ -40,6 +43,7 @@ class DiceWebSigninInterceptionBubbleView
DiceWebSigninInterceptionBubbleView(content::BrowserContext* browser_context,
views::View* anchor_view,
const AccountInfo& account_info,
base::OnceCallback<void(bool)> callback);
// This bubble has no native buttons. The user accepts or cancels through this
......
......@@ -12,6 +12,7 @@
#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 "components/signin/public/identity_manager/account_info.h"
#include "content/public/test/browser_test.h"
#include "ui/views/bubble/bubble_dialog_delegate_view.h"
#include "ui/views/test/widget_test.h"
......@@ -24,7 +25,7 @@ class DiceWebSigninInterceptionBubbleBrowserTest : public DialogBrowserTest {
// DialogBrowserTest:
void ShowUi(const std::string& name) override {
DiceWebSigninInterceptionBubbleView::CreateBubble(
browser()->profile(), GetAvatarButton(),
browser()->profile(), GetAvatarButton(), AccountInfo(),
base::OnceCallback<void(bool)>());
}
......@@ -58,7 +59,7 @@ IN_PROC_BROWSER_TEST_F(DiceWebSigninInterceptionBubbleBrowserTest,
BubbleClosed) {
views::Widget* widget = views::BubbleDialogDelegateView::CreateBubble(
new DiceWebSigninInterceptionBubbleView(
browser()->profile(), GetAvatarButton(),
browser()->profile(), GetAvatarButton(), AccountInfo(),
base::BindOnce(&DiceWebSigninInterceptionBubbleBrowserTest::
OnInterceptionComplete,
base::Unretained(this))));
......
......@@ -5,11 +5,18 @@
#include "chrome/browser/ui/webui/signin/dice_web_signin_intercept_handler.h"
#include "base/bind.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_avatar_icon_util.h"
#include "chrome/browser/signin/identity_manager_factory.h"
#include "content/public/browser/web_ui.h"
#include "ui/base/webui/web_ui_util.h"
#include "ui/gfx/image/image.h"
#include "url/gurl.h"
DiceWebSigninInterceptHandler::DiceWebSigninInterceptHandler(
const AccountInfo& account_info,
base::OnceCallback<void(bool)> callback)
: callback_(std::move(callback)) {
: account_info_(account_info), callback_(std::move(callback)) {
DCHECK(callback_);
}
......@@ -24,6 +31,28 @@ void DiceWebSigninInterceptHandler::RegisterMessages() {
"cancel",
base::BindRepeating(&DiceWebSigninInterceptHandler::HandleCancel,
base::Unretained(this)));
web_ui()->RegisterMessageCallback(
"pageLoaded",
base::BindRepeating(&DiceWebSigninInterceptHandler::HandlePageLoaded,
base::Unretained(this)));
}
void DiceWebSigninInterceptHandler::OnJavascriptAllowed() {
signin::IdentityManager* identity_manager =
IdentityManagerFactory::GetForProfile(Profile::FromWebUI(web_ui()));
identity_observer_.Add(identity_manager);
}
void DiceWebSigninInterceptHandler::OnJavascriptDisallowed() {
identity_observer_.RemoveAll();
}
void DiceWebSigninInterceptHandler::OnExtendedAccountInfoUpdated(
const AccountInfo& info) {
if (info.account_id == account_info_.account_id) {
account_info_ = info;
FireWebUIListener("account-info-changed", GetAccountInfoValue());
}
}
void DiceWebSigninInterceptHandler::HandleAccept(const base::ListValue* args) {
......@@ -35,3 +64,31 @@ void DiceWebSigninInterceptHandler::HandleCancel(const base::ListValue* args) {
if (callback_)
std::move(callback_).Run(false);
}
void DiceWebSigninInterceptHandler::HandlePageLoaded(
const base::ListValue* args) {
AllowJavascript();
// Update the account info and the image.
signin::IdentityManager* identity_manager =
IdentityManagerFactory::GetForProfile(Profile::FromWebUI(web_ui()));
base::Optional<AccountInfo> info =
identity_manager->FindExtendedAccountInfoForAccountWithRefreshToken(
account_info_);
if (info)
account_info_ = info.value();
const base::Value& callback_id = args->GetList()[0];
ResolveJavascriptCallback(callback_id, GetAccountInfoValue());
}
base::Value DiceWebSigninInterceptHandler::GetAccountInfoValue() {
std::string picture_url_to_load =
account_info_.account_image.IsEmpty()
? profiles::GetPlaceholderAvatarIconUrl()
: webui::GetBitmapDataUrl(account_info_.account_image.AsBitmap());
base::Value account_info_value(base::Value::Type::DICTIONARY);
account_info_value.SetStringKey("pictureUrl", picture_url_to_load);
account_info_value.SetStringKey("name", account_info_.given_name);
return account_info_value;
}
......@@ -8,16 +8,21 @@
#include "content/public/browser/web_ui_message_handler.h"
#include "base/callback.h"
#include "base/scoped_observer.h"
#include "base/values.h"
#include "components/signin/public/identity_manager/account_info.h"
#include "components/signin/public/identity_manager/identity_manager.h"
namespace base {
class ListValue;
}
// WebUI message handler for the Dice web signin intercept bubble.
class DiceWebSigninInterceptHandler : public content::WebUIMessageHandler {
class DiceWebSigninInterceptHandler : public content::WebUIMessageHandler,
public signin::IdentityManager::Observer {
public:
explicit DiceWebSigninInterceptHandler(
base::OnceCallback<void(bool)> callback);
DiceWebSigninInterceptHandler(const AccountInfo& account_info,
base::OnceCallback<void(bool)> callback);
~DiceWebSigninInterceptHandler() override;
DiceWebSigninInterceptHandler(const DiceWebSigninInterceptHandler&) = delete;
......@@ -26,11 +31,24 @@ class DiceWebSigninInterceptHandler : public content::WebUIMessageHandler {
// content::WebUIMessageHandler:
void RegisterMessages() override;
void OnJavascriptAllowed() override;
void OnJavascriptDisallowed() override;
// signin::IdentityManager::Observer
void OnExtendedAccountInfoUpdated(const AccountInfo& info) override;
private:
void HandleAccept(const base::ListValue* args);
void HandleCancel(const base::ListValue* args);
void HandlePageLoaded(const base::ListValue* args);
// Gets the AccountInfo javascript value.
base::Value GetAccountInfoValue();
ScopedObserver<signin::IdentityManager, signin::IdentityManager::Observer>
identity_observer_{this};
AccountInfo account_info_;
base::OnceCallback<void(bool)> callback_;
};
......
......@@ -5,6 +5,7 @@
#include "chrome/browser/ui/webui/signin/dice_web_signin_intercept_ui.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_avatar_icon_util.h"
#include "chrome/browser/ui/webui/signin/dice_web_signin_intercept_handler.h"
#include "chrome/browser/ui/webui/webui_util.h"
#include "chrome/common/webui_url_constants.h"
......@@ -26,7 +27,9 @@ DiceWebSigninInterceptUI::DiceWebSigninInterceptUI(content::WebUI* web_ui)
IDR_SIGNIN_DICE_WEB_INTERCEPT_APP_JS);
source->AddResourcePath("dice_web_signin_intercept_browser_proxy.js",
IDR_SIGNIN_DICE_WEB_INTERCEPT_BROWSER_PROXY_JS);
source->AddResourcePath("signin_icons.js", IDR_SIGNIN_ICONS_JS);
source->AddResourcePath("signin_shared_css.js", IDR_SIGNIN_SHARED_CSS_JS);
source->AddResourcePath("signin_vars_css.js", IDR_SIGNIN_VARS_CSS_JS);
// Localized strings.
source->UseStringsJs();
......@@ -56,9 +59,10 @@ DiceWebSigninInterceptUI::DiceWebSigninInterceptUI(content::WebUI* web_ui)
DiceWebSigninInterceptUI::~DiceWebSigninInterceptUI() = default;
void DiceWebSigninInterceptUI::Initialize(
const AccountInfo& account_info,
base::OnceCallback<void(bool)> callback) {
web_ui()->AddMessageHandler(
std::make_unique<DiceWebSigninInterceptHandler>(std::move(callback)));
web_ui()->AddMessageHandler(std::make_unique<DiceWebSigninInterceptHandler>(
account_info, std::move(callback)));
}
WEB_UI_CONTROLLER_TYPE_IMPL(DiceWebSigninInterceptUI)
......@@ -13,6 +13,8 @@ namespace content {
class WebUI;
}
struct AccountInfo;
class DiceWebSigninInterceptUI : public content::WebUIController {
public:
explicit DiceWebSigninInterceptUI(content::WebUI* web_ui);
......@@ -22,7 +24,8 @@ class DiceWebSigninInterceptUI : public content::WebUIController {
DiceWebSigninInterceptUI& operator=(const DiceWebSigninInterceptUI&) = delete;
// Initializes the DiceWebSigninInterceptUI.
void Initialize(base::OnceCallback<void(bool)> callback);
void Initialize(const AccountInfo& account_info,
base::OnceCallback<void(bool)> callback);
private:
WEB_UI_CONTROLLER_TYPE_DECL();
......
......@@ -25,6 +25,7 @@ js_library("dice_web_signin_intercept_test") {
"..:chai_assert",
"..:test_util.m",
"//chrome/browser/resources/signin/dice_web_signin_intercept:dice_web_signin_intercept_app",
"//ui/webui/resources/js:cr.m",
]
externs_list = [ "$externs_path/mocha-2.5.js" ]
}
......
......@@ -4,13 +4,19 @@
import 'chrome://signin-dice-web-intercept/dice_web_signin_intercept_app.js';
import {DiceWebSigninInterceptBrowserProxyImpl} from 'chrome://signin-dice-web-intercept/dice_web_signin_intercept_browser_proxy.js';
import {webUIListenerCallback} from 'chrome://resources/js/cr.m.js';
import {AccountInfo, DiceWebSigninInterceptBrowserProxyImpl} from 'chrome://signin-dice-web-intercept/dice_web_signin_intercept_browser_proxy.js';
import {assertTrue} from '../chai_assert.js';
import {assertEquals, assertFalse, assertTrue} from '../chai_assert.js';
import {isChildVisible} from '../test_util.m.js';
import {TestDiceWebSigninInterceptBrowserProxy} from './test_dice_web_signin_intercept_browser_proxy.js';
/** @param {!AccountInfo} account_info */
function fireAccountInfoChanged(account_info) {
webUIListenerCallback('account-info-changed', account_info);
}
suite('DiceWebSigninInterceptTest', function() {
/** @type {!DiceWebSigninInterceptAppElement} */
let app;
......@@ -18,13 +24,19 @@ suite('DiceWebSigninInterceptTest', function() {
/** @type {!TestDiceWebSigninInterceptBrowserProxy} */
let browserProxy;
/** @type {string} */
const PLACEHOLDER_AVATAR =
'chrome://theme/IDR_PROFILE_AVATAR_PLACEHOLDER_LARGE';
setup(function() {
browserProxy = new TestDiceWebSigninInterceptBrowserProxy();
browserProxy.setAccountInfo({pictureUrl: PLACEHOLDER_AVATAR, name: ''});
DiceWebSigninInterceptBrowserProxyImpl.instance_ = browserProxy;
document.body.innerHTML = '';
app = /** @type {!DiceWebSigninInterceptAppElement} */ (
document.createElement('dice-web-signin-intercept-app'));
document.body.append(app);
return browserProxy.whenCalled('pageLoaded');
});
test('ClickAccept', function() {
......@@ -38,4 +50,18 @@ suite('DiceWebSigninInterceptTest', function() {
app.$$('#cancelButton').click();
return browserProxy.whenCalled('cancel');
});
test('AccountInfo', function() {
assertTrue(isChildVisible(app, '#userAvatar'));
assertFalse(isChildVisible(app, '#accountName'));
const userImg = app.$$('#userAvatar');
const accountNameElement = app.$$('#accountName');
assertEquals(PLACEHOLDER_AVATAR, userImg.src);
const avatarUrl = 'chrome://theme/IDR_PROFILE_AVATAR_0';
const accountName = 'Foo';
fireAccountInfoChanged({pictureUrl: avatarUrl, name: accountName});
assertEquals(avatarUrl, userImg.src);
assertEquals(accountName, accountNameElement.textContent);
assertTrue(isChildVisible(app, '#accountName'));
});
});
......@@ -2,14 +2,21 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import {DiceWebSigninInterceptBrowserProxy} from 'chrome://signin-dice-web-intercept/dice_web_signin_intercept_browser_proxy.js';
import {AccountInfo, DiceWebSigninInterceptBrowserProxy} from 'chrome://signin-dice-web-intercept/dice_web_signin_intercept_browser_proxy.js';
import {TestBrowserProxy} from '../test_browser_proxy.m.js';
/** @implements {DiceWebSigninInterceptBrowserProxy} */
export class TestDiceWebSigninInterceptBrowserProxy extends TestBrowserProxy {
constructor() {
super(['accept', 'cancel']);
super(['accept', 'cancel', 'pageLoaded']);
/** @private {!AccountInfo} */
this.accountInfo_ = {pictureUrl: '', name: ''};
}
/** @param {!AccountInfo} info */
setAccountInfo(info) {
this.accountInfo_ = info;
}
/** @override */
......@@ -21,4 +28,10 @@ export class TestDiceWebSigninInterceptBrowserProxy extends TestBrowserProxy {
cancel() {
this.methodCalled('cancel');
}
/** @override */
pageLoaded() {
this.methodCalled('pageLoaded');
return Promise.resolve(this.accountInfo_);
}
}
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