Commit 3a92ef52 authored by Yue Li's avatar Yue Li Committed by Commit Bot

Reland Migrate Assistant opt-in flow into CrOS OOBE

This is a reland for
https://chromium-review.googlesource.com/c/chromium/src/+/1195662
except for the wizard_controller changes

TBR=xiyuan@chromium.org, xiaohuic@chromium.org

Bug: b/78190629
Test: Manual Test
Change-Id: I9064ae4017a2b848e00522bcbecf8d93e5e99e4a
Reviewed-on: https://chromium-review.googlesource.com/1205208Reviewed-by: default avatarAlexander Alekseev <alemate@chromium.org>
Reviewed-by: default avatarXiyuan Xia <xiyuan@chromium.org>
Reviewed-by: default avatarYue Li <updowndota@chromium.org>
Commit-Queue: Yue Li <updowndota@chromium.org>
Cr-Commit-Position: refs/heads/master@{#588904}
parent a90551a9
......@@ -1093,6 +1093,9 @@ source_set("chromeos") {
"login/screens/arc_terms_of_service_screen.h",
"login/screens/arc_terms_of_service_screen_view.h",
"login/screens/arc_terms_of_service_screen_view_observer.h",
"login/screens/assistant_optin_flow_screen.cc",
"login/screens/assistant_optin_flow_screen.h",
"login/screens/assistant_optin_flow_screen_view.h",
"login/screens/base_screen.cc",
"login/screens/base_screen.h",
"login/screens/base_screen_delegate.h",
......
......@@ -21,11 +21,9 @@
#include "chrome/browser/signin/identity_manager_factory.h"
#include "chrome/browser/ui/extensions/app_launch_params.h"
#include "chrome/browser/ui/extensions/application_launch.h"
#include "chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/extension_constants.h"
#include "chrome/common/pref_names.h"
#include "chromeos/assistant/buildflags.h"
#include "chromeos/chromeos_switches.h"
#include "components/arc/arc_prefs.h"
#include "components/arc/arc_service_manager.h"
......@@ -135,16 +133,6 @@ class DialogLauncher : public content::NotificationObserver {
}
}
#if BUILDFLAG(ENABLE_CROS_LIBASSISTANT)
// Launch Assistant OOBE flow if Assistant is allowed.
if (arc::IsAssistantAllowedForProfile(profile_) ==
ash::mojom::AssistantAllowedState::ALLOWED) {
chromeos::AssistantOptInDialog::Show();
delete this;
return;
}
#endif
// If voice interaction value prop needs to be shown, the tutorial will be
// shown after the voice interaction OOBE flow.
if (account_supported && arc::IsArcPlayStoreEnabledForProfile(profile_) &&
......
......@@ -53,6 +53,7 @@ const char* kScreenNames[] = {
"voice-interaction-value-prop", // SCREEN_VOICE_INTERACTION_VALUE_PROP
"wait-for-container-ready", // SCREEN_WAIT_FOR_CONTAINTER_READY
"update-required", // SCREEN_UPDATE_REQUIRED
"assistant-optin-flow", // SCREEN_ASSISTANT_OPTIN_FLOW
"login", // SCREEN_SPECIAL_LOGIN
"oobe", // SCREEN_SPECIAL_OOBE
"test:nowindow", // SCREEN_TEST_NO_WINDOW
......
......@@ -50,6 +50,7 @@ enum class OobeScreen : unsigned int {
SCREEN_VOICE_INTERACTION_VALUE_PROP,
SCREEN_WAIT_FOR_CONTAINER_READY,
SCREEN_UPDATE_REQUIRED,
SCREEN_ASSISTANT_OPTIN_FLOW,
// Special "first screen" that initiates login flow.
SCREEN_SPECIAL_LOGIN,
......
// Copyright 2018 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/chromeos/login/screens/assistant_optin_flow_screen.h"
#include "chrome/browser/chromeos/login/screens/assistant_optin_flow_screen_view.h"
#include "chrome/browser/chromeos/login/screens/base_screen_delegate.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
namespace chromeos {
namespace {
constexpr const char kFlowFinished[] = "flow-finished";
} // namespace
AssistantOptInFlowScreen::AssistantOptInFlowScreen(
BaseScreenDelegate* base_screen_delegate,
AssistantOptInFlowScreenView* view)
: BaseScreen(base_screen_delegate, OobeScreen::SCREEN_ASSISTANT_OPTIN_FLOW),
view_(view) {
DCHECK(view_);
if (view_)
view_->Bind(this);
}
AssistantOptInFlowScreen::~AssistantOptInFlowScreen() {
if (view_)
view_->Unbind();
}
void AssistantOptInFlowScreen::Show() {
if (!view_)
return;
view_->Show();
}
void AssistantOptInFlowScreen::Hide() {
if (view_)
view_->Hide();
}
void AssistantOptInFlowScreen::OnViewDestroyed(
AssistantOptInFlowScreenView* view) {
if (view_ == view)
view_ = nullptr;
}
void AssistantOptInFlowScreen::OnUserAction(const std::string& action_id) {
if (action_id == kFlowFinished)
Finish(ScreenExitCode::ASSISTANT_OPTIN_FLOW_FINISHED);
else
BaseScreen::OnUserAction(action_id);
}
} // namespace chromeos
// Copyright 2018 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.
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_ASSISTANT_OPTIN_FLOW_SCREEN_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_ASSISTANT_OPTIN_FLOW_SCREEN_H_
#include <string>
#include "base/macros.h"
#include "chrome/browser/chromeos/login/screens/base_screen.h"
namespace chromeos {
class AssistantOptInFlowScreenView;
class BaseScreenDelegate;
class AssistantOptInFlowScreen : public BaseScreen {
public:
AssistantOptInFlowScreen(BaseScreenDelegate* base_screen_delegate,
AssistantOptInFlowScreenView* view);
~AssistantOptInFlowScreen() override;
// Called when view is destroyed so there's no dead reference to it.
void OnViewDestroyed(AssistantOptInFlowScreenView* view_);
// BaseScreen:
void Show() override;
void Hide() override;
void OnUserAction(const std::string& action_id) override;
private:
AssistantOptInFlowScreenView* view_;
DISALLOW_COPY_AND_ASSIGN(AssistantOptInFlowScreen);
};
} // namespace chromeos
#endif // CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_ASSISTANT_OPTIN_FLOW_SCREEN_H_
// Copyright 2018 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.
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_ASSISTANT_OPTIN_FLOW_SCREEN_VIEW_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_ASSISTANT_OPTIN_FLOW_SCREEN_VIEW_H_
#include "chrome/browser/chromeos/login/oobe_screen.h"
namespace chromeos {
class AssistantOptInFlowScreen;
// Interface for dependency injection between AssistantOptInFlowScreen
// and its WebUI representation.
class AssistantOptInFlowScreenView {
public:
constexpr static OobeScreen kScreenId =
OobeScreen::SCREEN_ASSISTANT_OPTIN_FLOW;
virtual ~AssistantOptInFlowScreenView() = default;
virtual void Bind(AssistantOptInFlowScreen* screen) = 0;
virtual void Unbind() = 0;
virtual void Show() = 0;
virtual void Hide() = 0;
protected:
AssistantOptInFlowScreenView() = default;
private:
DISALLOW_COPY_AND_ASSIGN(AssistantOptInFlowScreenView);
};
} // namespace chromeos
#endif // CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_ASSISTANT_OPTIN_FLOW_SCREEN_VIEW_H_
......@@ -71,6 +71,7 @@ enum class ScreenExitCode {
NETWORK_OFFLINE_DEMO_SETUP = 44,
FINGERPRINT_SETUP_FINISHED = 45,
MARKETING_OPT_IN_FINISHED = 46,
ASSISTANT_OPTIN_FLOW_FINISHED = 47,
EXIT_CODES_COUNT // not a real code, must be the last
};
......
......@@ -97,6 +97,7 @@
#include "chrome/common/chrome_switches.h"
#include "chrome/common/logging_chrome.h"
#include "chrome/common/pref_names.h"
#include "chromeos/assistant/buildflags.h"
#include "chromeos/cert_loader.h"
#include "chromeos/chromeos_switches.h"
#include "chromeos/cryptohome/cryptohome_parameters.h"
......@@ -147,6 +148,10 @@
#include "components/rlz/rlz_tracker.h"
#endif
#if BUILDFLAG(ENABLE_CROS_ASSISTANT)
#include "chrome/browser/ui/ash/assistant/assistant_client.h"
#endif
namespace chromeos {
namespace {
......@@ -1536,6 +1541,13 @@ bool UserSessionManager::InitializeUserSession(Profile* profile) {
ProfileHelper::Get()->ProfileStartup(profile);
if (start_session_type_ == PRIMARY_USER_SESSION) {
#if BUILDFLAG(ENABLE_CROS_ASSISTANT)
// Initialize Assistant early to be used in post login Oobe steps.
if (chromeos::switches::IsAssistantEnabled()) {
AssistantClient::Get()->MaybeInit(
content::BrowserContext::GetConnectorFor(profile));
}
#endif
UserFlow* user_flow = ChromeUserManager::Get()->GetCurrentUserFlow();
WizardController* oobe_controller = WizardController::default_controller();
base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
......
......@@ -2621,7 +2621,7 @@ IN_PROC_BROWSER_TEST_F(WizardControllerOobeConfigurationTest,
// TODO(fukino): Add tests for encryption migration UI.
// http://crbug.com/706017
// TODO(updowndota): Add tests for Voice Interaction OptIn flow.
// TODO(updowndota): Add tests for Voice Interaction/Assistant OptIn flow.
// TODO(alemate): Add tests for Sync Consent UI.
......@@ -2632,7 +2632,7 @@ IN_PROC_BROWSER_TEST_F(WizardControllerOobeConfigurationTest,
// TODO(xiaoyinh): Add tests for Fingerprint Setup UI.
// TODO(alemate): Add tests for Marketing Opt-In.
static_assert(static_cast<int>(ScreenExitCode::EXIT_CODES_COUNT) == 47,
static_assert(static_cast<int>(ScreenExitCode::EXIT_CODES_COUNT) == 48,
"tests for new control flow are missing");
} // namespace chromeos
......@@ -58,7 +58,7 @@ Polymer({
var emailOptedIn = toggle2 != null && toggle2.hasAttribute('checked');
// TODO(updowndota): Wrap chrome.send() calls with a proxy object.
chrome.send('hotwordResult', [hotword]);
chrome.send('assistantOptInFlow.hotwordResult', [hotword]);
chrome.send(
'assistant.GetMoreScreen.userActed', [screenContext, emailOptedIn]);
},
......
......@@ -60,7 +60,7 @@ Polymer({
* @private
*/
onSkipTap_: function() {
chrome.send('dialogClose');
chrome.send('assistantOptInFlow.flowFinished');
},
/**
......
......@@ -17,16 +17,10 @@
<link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
<link rel="import" href="chrome://resources/cr_elements/shared_style_css.html">
<include src="../login/hd-iron-icon.html">
<include src="../login/oobe_buttons.html">
<include src="../login/oobe_change_picture.html">
<include src="../login/oobe_dialog.html">
<include src="assistant_get_more.html">
<include src="assistant_loading.html">
<include src="assistant_ready.html">
<include src="assistant_third_party.html">
<include src="assistant_value_prop.html">
<include src="setting_zippy.html">
<include src="assistant_optin_flow.html">
<link rel="stylesheet" href="chrome://resources/css/chrome_shared.css">
<link rel="stylesheet" href="../login/oobe_flex_layout.css">
......@@ -42,20 +36,7 @@
</head>
<body>
<div id="consent-dialog" role="group">
<assistant-loading id="loading">
</assistant-loading>
<assistant-value-prop id="value-prop">
</assistant-value-prop>
<assistant-confirm-reject id="confirm-reject" hidden>
</assistant-confirm-reject>
<assistant-third-party id="third-party" hidden>
</assistant-third-party>
<assistant-get-more id="get-more" hidden>
</assistant-get-more>
<assistant-ready id="ready" hidden>
</assistant-ready>
</div>
<assistant-optin-flow id="assistant-optin-flow-card"></assistant-optin-flow>
<script src="chrome://resources/js/i18n_template.js"></script>
......
......@@ -8,30 +8,16 @@
// <include src="../login/oobe_change_picture.js">
// <include src="../login/oobe_dialog_host_behavior.js">
// <include src="../login/oobe_dialog.js">
// <include src="utils.js">
// <include src="setting_zippy.js">
// <include src="assistant_get_more.js">
// <include src="assistant_loading.js">
// <include src="assistant_ready.js">
// <include src="assistant_third_party.js">
// <include src="assistant_value_prop.js">
// <include src="assistant_optin_flow.js">
cr.define('assistantOptin', function() {
cr.define('assistantOptInFlow', function() {
return {
/**
* Starts the assistant opt-in flow.
*/
show: function() {
this.boundShowLoadingScreen = assistantOptin.showLoadingScreen.bind(this);
this.boundOnScreenLoadingError =
assistantOptin.onScreenLoadingError.bind(this);
this.boundOnScreenLoaded = assistantOptin.onScreenLoaded.bind(this);
$('loading').addEventListener(
'reload', assistantOptin.onReload.bind(this));
this.showScreen($('value-prop'));
chrome.send('initialized');
$('assistant-optin-flow-card').onShow();
},
/**
......@@ -39,12 +25,7 @@ cr.define('assistantOptin', function() {
* @param {!Object} data New dictionary with i18n values.
*/
reloadContent: function(data) {
// Reload global local strings, process DOM tree again.
loadTimeData.overrideValues(data);
i18nTemplate.process(document, loadTimeData);
$('value-prop').reloadContent(data);
$('third-party').reloadContent(data);
$('get-more').reloadContent(data);
$('assistant-optin-flow-card').reloadContent(data);
},
/**
......@@ -53,108 +34,22 @@ cr.define('assistantOptin', function() {
* @param {!Object} data String and url for the setting zippy.
*/
addSettingZippy: function(type, data) {
switch (type) {
case 'settings':
$('value-prop').addSettingZippy(data);
break;
case 'disclosure':
$('third-party').addSettingZippy(data);
break;
case 'get-more':
$('get-more').addSettingZippy(data);
break;
default:
console.error('Undefined zippy data type: ' + type);
}
$('assistant-optin-flow-card').addSettingZippy(type, data);
},
/**
* Show the next screen in the flow.
*/
showNextScreen: function() {
switch (this.currentScreen) {
case $('value-prop'):
this.showScreen($('third-party'));
break;
case $('third-party'):
this.showScreen($('get-more'));
break;
case $('get-more'):
this.showScreen($('ready'));
break;
default:
console.error('Undefined');
chrome.send('dialogClose');
}
$('assistant-optin-flow-card').showNextScreen();
},
closeDialog: function() {
chrome.send('dialogClose');
},
/**
* Show the given screen.
*
* @param {Element} screen The screen to be shown.
*/
showScreen: function(screen) {
if (this.currentScreen == screen) {
return;
}
screen.hidden = false;
screen.addEventListener('loading', this.boundShowLoadingScreen);
screen.addEventListener('error', this.boundOnScreenLoadingError);
screen.addEventListener('loaded', this.boundOnScreenLoaded);
if (this.currentScreen) {
this.currentScreen.hidden = true;
this.currentScreen.removeEventListener(
'loading', this.boundShowLoadingScreen);
this.currentScreen.removeEventListener(
'error', this.boundOnScreenLoadingError);
this.currentScreen.removeEventListener(
'loaded', this.boundOnScreenLoaded);
}
this.currentScreen = screen;
this.currentScreen.onShow();
},
/**
* Show the loading screen.
*/
showLoadingScreen: function() {
$('loading').hidden = false;
this.currentScreen.hidden = true;
$('loading').onShow();
},
/**
* Called when the screen failed to load.
*/
onScreenLoadingError: function() {
$('loading').hidden = false;
this.currentScreen.hidden = true;
$('loading').onErrorOccurred();
},
/**
* Called when all the content of current screen has been loaded.
*/
onScreenLoaded: function() {
this.currentScreen.hidden = false;
$('loading').hidden = true;
$('loading').onPageLoaded();
},
/**
* Called when user request the screen to be reloaded.
*/
onReload: function() {
this.currentScreen.reloadPage();
},
};
});
document.addEventListener('DOMContentLoaded', function() {
assistantOptin.show();
assistantOptInFlow.show();
});
<!-- Copyright 2018 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 src="assistant_get_more.html">
<include src="assistant_loading.html">
<include src="assistant_ready.html">
<include src="assistant_third_party.html">
<include src="assistant_value_prop.html">
<include src="setting_zippy.html">
<link rel="import" href="chrome://resources/cr_elements/cr_expand_button/cr_expand_button.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-collapse/iron-collapse.html">
<dom-module id="assistant-optin-flow">
<template>
<link rel="stylesheet" href="../login/oobe_flex_layout.css">
<link rel="stylesheet" href="../login/oobe_popup_overlay.css">
<link rel="stylesheet" href="assistant_shared_styles.css">
<link rel="stylesheet" href="assistant_value_prop.css">
<assistant-loading id="loading">
</assistant-loading>
<assistant-value-prop id="value-prop">
</assistant-value-prop>
<assistant-confirm-reject id="confirm-reject" hidden>
</assistant-confirm-reject>
<assistant-third-party id="third-party" hidden>
</assistant-third-party>
<assistant-get-more id="get-more" hidden>
</assistant-get-more>
<assistant-ready id="ready" hidden>
</assistant-ready>
</template>
</dom-module>
// Copyright 2018 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 src="utils.js">
// <include src="setting_zippy.js">
// <include src="assistant_get_more.js">
// <include src="assistant_loading.js">
// <include src="assistant_ready.js">
// <include src="assistant_third_party.js">
// <include src="assistant_value_prop.js">
/**
* @fileoverview Polymer element for displaying material design assistant
* ready screen.
*
*/
Polymer({
is: 'assistant-optin-flow',
behaviors: [OobeDialogHostBehavior],
/**
* Signal from host to show the screen.
*/
onShow: function() {
this.boundShowLoadingScreen = this.showLoadingScreen.bind(this);
this.boundOnScreenLoadingError = this.onScreenLoadingError.bind(this);
this.boundOnScreenLoaded = this.onScreenLoaded.bind(this);
this.$['loading'].onBeforeShow();
this.$['loading'].addEventListener('reload', this.onReload.bind(this));
this.showScreen(this.$['value-prop']);
chrome.send('assistantOptInFlow.initialized');
},
/**
* Reloads localized strings.
* @param {!Object} data New dictionary with i18n values.
*/
reloadContent: function(data) {
// Reload global local strings, process DOM tree again.
loadTimeData.overrideValues(data);
i18nTemplate.process(document, loadTimeData);
this.$['value-prop'].reloadContent(data);
this.$['third-party'].reloadContent(data);
this.$['get-more'].reloadContent(data);
},
/**
* Add a setting zippy object in the corresponding screen.
* @param {string} type type of the setting zippy.
* @param {!Object} data String and url for the setting zippy.
*/
addSettingZippy: function(type, data) {
switch (type) {
case 'settings':
this.$['value-prop'].addSettingZippy(data);
break;
case 'disclosure':
this.$['third-party'].addSettingZippy(data);
break;
case 'get-more':
this.$['get-more'].addSettingZippy(data);
break;
default:
console.error('Undefined zippy data type: ' + type);
}
},
/**
* Show the next screen in the flow.
*/
showNextScreen: function() {
switch (this.currentScreen) {
case this.$['value-prop']:
this.showScreen(this.$['third-party']);
break;
case this.$['third-party']:
this.showScreen(this.$['get-more']);
break;
case this.$['get-more']:
this.showScreen(this.$['ready']);
break;
default:
console.error('Undefined');
chrome.send('dialogClose');
}
},
/**
* Show the given screen.
*
* @param {Element} screen The screen to be shown.
*/
showScreen: function(screen) {
if (this.currentScreen == screen) {
return;
}
screen.hidden = false;
screen.addEventListener('loading', this.boundShowLoadingScreen);
screen.addEventListener('error', this.boundOnScreenLoadingError);
screen.addEventListener('loaded', this.boundOnScreenLoaded);
if (this.currentScreen) {
this.currentScreen.hidden = true;
this.currentScreen.removeEventListener(
'loading', this.boundShowLoadingScreen);
this.currentScreen.removeEventListener(
'error', this.boundOnScreenLoadingError);
this.currentScreen.removeEventListener(
'loaded', this.boundOnScreenLoaded);
}
this.currentScreen = screen;
this.currentScreen.onBeforeShow();
this.currentScreen.onShow();
},
/**
* Show the loading screen.
*/
showLoadingScreen: function() {
this.$['loading'].hidden = false;
this.currentScreen.hidden = true;
this.$['loading'].onShow();
},
/**
* Called when the screen failed to load.
*/
onScreenLoadingError: function() {
this.$['loading'].hidden = false;
this.currentScreen.hidden = true;
this.$['loading'].onErrorOccurred();
},
/**
* Called when all the content of current screen has been loaded.
*/
onScreenLoaded: function() {
this.currentScreen.hidden = false;
this.$['loading'].hidden = true;
this.$['loading'].onPageLoaded();
},
/**
* Called when user request the screen to be reloaded.
*/
onReload: function() {
this.currentScreen.reloadPage();
},
});
......@@ -35,5 +35,6 @@
<include src="app_downloading.html">
<include src="discover/discover_components.html">
<include src="marketing_opt_in.html">
<include src="../assistant_optin/assistant_optin_flow.html">
<script src="chrome://oobe/custom_elements.js"></script>
......@@ -40,3 +40,4 @@
// <include src="app_downloading.js">
// <include src="discover/discover_components.js">
// <include src="marketing_opt_in.js">
// <include src="../assistant_optin/assistant_optin_flow.js">
......@@ -46,5 +46,6 @@
<include src="app_downloading.html">
<include src="discover/discover_components.html">
<include src="marketing_opt_in.html">
<include src="../assistant_optin/assistant_optin_flow.html">
<script src="chrome://oobe/custom_elements.js"></script>
......@@ -56,3 +56,4 @@
// <include src="app_downloading.js">
// <include src="discover/discover_components.js">
// <include src="marketing_opt_in.js">
// <include src="../assistant_optin/assistant_optin_flow.js">
......@@ -62,6 +62,7 @@ cr.define('cr.ui.Oobe', function() {
login.DemoSetupScreen.register();
login.DiscoverScreen.register();
login.MarketingOptInScreen.register();
login.AssistantOptInFlowScreen.register();
cr.ui.Bubble.decorate($('bubble'));
login.HeaderBar.decorate($('login-header-bar'));
......
......@@ -15,6 +15,7 @@
// <include src="oobe_screen_user_image.js">
// <include src="oobe_screen_voice_interaction_value_prop.js">
// <include src="oobe_screen_wait_for_container_ready.js">
// <include src="oobe_screen_assistant_optin_flow.js">
// <include src="oobe_select.js">
// <include src="screen_app_launch_splash.js">
......
......@@ -5,6 +5,7 @@
<include src="oobe_screen_user_image.html">
<include src="oobe_screen_voice_interaction_value_prop.html">
<include src="oobe_screen_wait_for_container_ready.html">
<include src="oobe_screen_assistant_optin_flow.html">
<include src="../../../../../ui/login/account_picker/screen_account_picker.html">
<include src="screen_arc_terms_of_service.html">
<include src="screen_error_message.html">
......
......@@ -61,6 +61,7 @@ cr.define('cr.ui.Oobe', function() {
login.UpdateRequiredScreen.register();
login.DiscoverScreen.register();
login.MarketingOptInScreen.register();
login.AssistantOptInFlowScreen.register();
cr.ui.Bubble.decorate($('bubble-persistent'));
$('bubble-persistent').persistent = true;
......
......@@ -5,6 +5,7 @@
<include src="oobe_screen_user_image.html">
<include src="oobe_screen_voice_interaction_value_prop.html">
<include src="oobe_screen_wait_for_container_ready.html">
<include src="oobe_screen_assistant_optin_flow.html">
<include src="../../../../../ui/login/account_picker/md_screen_account_picker.html">
<include src="screen_arc_terms_of_service.html">
<include src="screen_error_message.html">
......
......@@ -68,6 +68,7 @@ cr.define('cr.ui.Oobe', function() {
login.DemoPreferencesScreen.register();
login.DiscoverScreen.register();
login.MarketingOptInScreen.register();
login.AssistantOptInFlowScreen.register();
cr.ui.Bubble.decorate($('bubble-persistent'));
$('bubble-persistent').persistent = true;
......
<!-- Copyright 2018 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. -->
<div class="step faded hidden no-logo" id="assistant-optin-flow"
role="group" hidden>
<assistant-optin-flow id="assistant-optin-flow-card"></assistant-optin-flow>
</div>
// Copyright 2018 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.
/**
* @fileoverview Oobe Assistant OptIn Flow screen implementation.
*/
login.createScreen(
'AssistantOptInFlowScreen', 'assistant-optin-flow', function() {
return {
EXTERNAL_API: ['reloadContent', 'addSettingZippy', 'showNextScreen'],
/** @Override */
onBeforeShow: function(data) {
Oobe.getInstance().headerHidden = true;
$('assistant-optin-flow-card').onShow();
},
/**
* Reloads localized strings.
* @param {!Object} data New dictionary with i18n values.
*/
reloadContent: function(data) {
$('assistant-optin-flow-card').reloadContent(data);
},
/**
* Add a setting zippy object in the corresponding screen.
* @param {string} type type of the setting zippy.
* @param {!Object} data String and url for the setting zippy.
*/
addSettingZippy: function(type, data) {
$('assistant-optin-flow-card').addSettingZippy(type, data);
},
/**
* Show the next screen in the flow.
*/
showNextScreen: function() {
$('assistant-optin-flow-card').showNextScreen();
},
};
});
......@@ -16,6 +16,7 @@
<include src="oobe_screen_wait_for_container_ready.html">
<include src="oobe_screen_demo_setup.html">
<include src="oobe_screen_demo_preferences.html">
<include src="oobe_screen_assistant_optin_flow.html">
<include src="../../../../../ui/login/account_picker/md_screen_account_picker.html">
<include src="screen_error_message.html">
<include src="screen_arc_terms_of_service.html">
......
......@@ -1959,6 +1959,8 @@ jumbo_split_static_library("ui") {
"webui/chromeos/login/arc_kiosk_splash_screen_handler.h",
"webui/chromeos/login/arc_terms_of_service_screen_handler.cc",
"webui/chromeos/login/arc_terms_of_service_screen_handler.h",
"webui/chromeos/login/assistant_optin_flow_screen_handler.cc",
"webui/chromeos/login/assistant_optin_flow_screen_handler.h",
"webui/chromeos/login/auto_enrollment_check_screen_handler.cc",
"webui/chromeos/login/auto_enrollment_check_screen_handler.h",
"webui/chromeos/login/base_screen_handler.cc",
......
......@@ -56,6 +56,7 @@ class AssistantOptInHandler
// Handler for JS WebUI message.
void HandleInitialized();
void HandleHotwordResult(bool enable_hotword);
void HandleFlowFinished();
// Consent token used to complete the opt-in.
std::string consent_token_;
......
......@@ -5,6 +5,17 @@
#include "chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_utils.h"
#include "base/metrics/histogram_macros.h"
#include "chrome/browser/consent_auditor/consent_auditor_factory.h"
#include "chrome/browser/signin/signin_manager_factory.h"
#include "chrome/browser/ui/webui/chromeos/user_image_source.h"
#include "chrome/grit/browser_resources.h"
#include "chrome/grit/generated_resources.h"
#include "components/arc/arc_prefs.h"
#include "components/consent_auditor/consent_auditor.h"
#include "components/signin/core/browser/signin_manager_base.h"
#include "components/user_manager/user_manager.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/webui/web_ui_util.h"
namespace chromeos {
......@@ -12,4 +23,203 @@ void RecordAssistantOptInStatus(AssistantOptInFlowStatus status) {
UMA_HISTOGRAM_ENUMERATION("Assistant.OptInFlowStatus", status, kMaxValue + 1);
}
// Construct SettingsUiSelector for the ConsentFlow UI.
assistant::SettingsUiSelector GetSettingsUiSelector() {
assistant::SettingsUiSelector selector;
assistant::ConsentFlowUiSelector* consent_flow_ui =
selector.mutable_consent_flow_ui_selector();
consent_flow_ui->set_flow_id(assistant::ActivityControlSettingsUiSelector::
ASSISTANT_SUW_ONBOARDING_ON_CHROME_OS);
selector.set_email_opt_in(true);
return selector;
}
// Construct SettingsUiUpdate for user opt-in.
assistant::SettingsUiUpdate GetSettingsUiUpdate(
const std::string& consent_token) {
assistant::SettingsUiUpdate update;
assistant::ConsentFlowUiUpdate* consent_flow_update =
update.mutable_consent_flow_ui_update();
consent_flow_update->set_flow_id(
assistant::ActivityControlSettingsUiSelector::
ASSISTANT_SUW_ONBOARDING_ON_CHROME_OS);
consent_flow_update->set_consent_token(consent_token);
return update;
}
// Construct SettingsUiUpdate for email opt-in.
assistant::SettingsUiUpdate GetEmailOptInUpdate(bool opted_in) {
assistant::SettingsUiUpdate update;
assistant::EmailOptInUpdate* email_optin_update =
update.mutable_email_opt_in_update();
email_optin_update->set_email_opt_in_update_state(
opted_in ? assistant::EmailOptInUpdate::OPT_IN
: assistant::EmailOptInUpdate::OPT_OUT);
return update;
}
// Helper method to create zippy data.
base::Value CreateZippyData(const SettingZippyList& zippy_list) {
base::Value zippy_data(base::Value::Type::LIST);
for (auto& setting_zippy : zippy_list) {
base::Value data(base::Value::Type::DICTIONARY);
data.SetKey("title", base::Value(setting_zippy.title()));
if (setting_zippy.description_paragraph_size()) {
data.SetKey("description",
base::Value(setting_zippy.description_paragraph(0)));
}
if (setting_zippy.additional_info_paragraph_size()) {
data.SetKey("additionalInfo",
base::Value(setting_zippy.additional_info_paragraph(0)));
}
data.SetKey("iconUri", base::Value(setting_zippy.icon_uri()));
data.SetKey("popupLink", base::Value(l10n_util::GetStringUTF16(
IDS_ASSISTANT_ACTIVITY_CONTROL_POPUP_LINK)));
zippy_data.GetList().push_back(std::move(data));
}
return zippy_data;
}
// Helper method to create disclosure data.
base::Value CreateDisclosureData(const SettingZippyList& disclosure_list) {
base::Value disclosure_data(base::Value::Type::LIST);
for (auto& disclosure : disclosure_list) {
base::Value data(base::Value::Type::DICTIONARY);
data.SetKey("title", base::Value(disclosure.title()));
if (disclosure.description_paragraph_size()) {
data.SetKey("description",
base::Value(disclosure.description_paragraph(0)));
}
if (disclosure.additional_info_paragraph_size()) {
data.SetKey("additionalInfo",
base::Value(disclosure.additional_info_paragraph(0)));
}
data.SetKey("iconUri", base::Value(disclosure.icon_uri()));
disclosure_data.GetList().push_back(std::move(data));
}
return disclosure_data;
}
// Helper method to create get more screen data.
base::Value CreateGetMoreData(bool email_optin_needed,
const assistant::EmailOptInUi& email_optin_ui) {
base::Value get_more_data(base::Value::Type::LIST);
// Process hotword data.
base::Value hotword_data(base::Value::Type::DICTIONARY);
hotword_data.SetKey(
"title",
base::Value(l10n_util::GetStringUTF16(IDS_ASSISTANT_HOTWORD_TITLE)));
hotword_data.SetKey(
"description",
base::Value(l10n_util::GetStringUTF16(IDS_ASSISTANT_HOTWORD_DESC)));
hotword_data.SetKey("defaultEnabled", base::Value(true));
hotword_data.SetKey(
"iconUri",
base::Value("https://www.gstatic.com/images/icons/material/system/"
"2x/mic_none_grey600_48dp.png"));
get_more_data.GetList().push_back(std::move(hotword_data));
// Process screen context data.
base::Value context_data(base::Value::Type::DICTIONARY);
context_data.SetKey("title", base::Value(l10n_util::GetStringUTF16(
IDS_ASSISTANT_SCREEN_CONTEXT_TITLE)));
context_data.SetKey("description", base::Value(l10n_util::GetStringUTF16(
IDS_ASSISTANT_SCREEN_CONTEXT_DESC)));
context_data.SetKey("defaultEnabled", base::Value(true));
context_data.SetKey(
"iconUri",
base::Value("https://www.gstatic.com/images/icons/material/system/"
"2x/laptop_chromebook_grey600_24dp.png"));
get_more_data.GetList().push_back(std::move(context_data));
// Process email optin data.
if (email_optin_needed) {
base::Value data(base::Value::Type::DICTIONARY);
data.SetKey("title", base::Value(email_optin_ui.title()));
data.SetKey("description", base::Value(email_optin_ui.description()));
data.SetKey("defaultEnabled",
base::Value(email_optin_ui.default_enabled()));
data.SetKey("iconUri", base::Value(email_optin_ui.icon_uri()));
data.SetKey("legalText", base::Value(email_optin_ui.legal_text()));
get_more_data.GetList().push_back(std::move(data));
}
return get_more_data;
}
// Get string constants for settings ui.
base::Value GetSettingsUiStrings(const assistant::SettingsUi& settings_ui,
bool activity_control_needed) {
auto consent_ui = settings_ui.consent_flow_ui().consent_ui();
auto activity_control_ui = consent_ui.activity_control_ui();
auto third_party_disclosure_ui = consent_ui.third_party_disclosure_ui();
base::Value dictionary(base::Value::Type::DICTIONARY);
// Add activity controll string constants.
if (activity_control_needed) {
scoped_refptr<base::RefCountedMemory> image =
chromeos::UserImageSource::GetUserImage(
user_manager::UserManager::Get()->GetActiveUser()->GetAccountId());
std::string icon_url = webui::GetPngDataUrl(image->front(), image->size());
dictionary.SetKey("valuePropUserImage", base::Value(icon_url));
dictionary.SetKey("valuePropIdentity",
base::Value(activity_control_ui.identity()));
dictionary.SetKey("valuePropTitle",
base::Value(activity_control_ui.title()));
if (activity_control_ui.intro_text_paragraph_size()) {
dictionary.SetKey(
"valuePropIntro",
base::Value(activity_control_ui.intro_text_paragraph(0)));
}
if (activity_control_ui.footer_paragraph_size()) {
dictionary.SetKey("valuePropFooter",
base::Value(activity_control_ui.footer_paragraph(0)));
}
dictionary.SetKey("valuePropNextButton",
base::Value(consent_ui.accept_button_text()));
dictionary.SetKey("valuePropSkipButton",
base::Value(consent_ui.reject_button_text()));
}
// Add third party string constants.
dictionary.SetKey("thirdPartyTitle",
base::Value(third_party_disclosure_ui.title()));
dictionary.SetKey("thirdPartyContinueButton",
base::Value(third_party_disclosure_ui.button_continue()));
dictionary.SetKey("thirdPartyFooter", base::Value(consent_ui.tos_pp_links()));
// Add get more screen string constants.
dictionary.SetKey("getMoreTitle", base::Value(l10n_util::GetStringUTF16(
IDS_ASSISTANT_GET_MORE_SCREEN_TITLE)));
dictionary.SetKey("getMoreIntro", base::Value(l10n_util::GetStringUTF16(
IDS_ASSISTANT_GET_MORE_SCREEN_INTRO)));
dictionary.SetKey(
"getMoreContinueButton",
base::Value(l10n_util::GetStringUTF16(IDS_ASSISTANT_CONTINUE_BUTTON)));
return dictionary;
}
using sync_pb::UserConsentTypes;
void RecordActivityControlConsent(Profile* profile,
std::string ui_audit_key,
bool opted_in) {
SigninManagerBase* signin_manager =
SigninManagerFactory::GetForProfile(profile);
DCHECK(signin_manager->IsAuthenticated());
std::string account_id = signin_manager->GetAuthenticatedAccountId();
UserConsentTypes::AssistantActivityControlConsent consent;
consent.set_ui_audit_key(ui_audit_key);
consent.set_status(opted_in ? UserConsentTypes::GIVEN
: UserConsentTypes::NOT_GIVEN);
ConsentAuditorFactory::GetForProfile(profile)
->RecordAssistantActivityControlConsent(account_id, consent);
}
} // namespace chromeos
......@@ -8,6 +8,11 @@
#include <string>
#include "base/callback.h"
#include "chrome/browser/profiles/profile.h"
#include "chromeos/services/assistant/public/mojom/constants.mojom.h"
#include "chromeos/services/assistant/public/proto/settings_ui.pb.h"
#include "components/prefs/pref_service.h"
#include "services/service_manager/public/cpp/connector.h"
namespace chromeos {
......@@ -45,6 +50,36 @@ using OnAssistantOptInScreenExitCallback =
void RecordAssistantOptInStatus(AssistantOptInFlowStatus);
// Construct SettingsUiSelector for the ConsentFlow UI.
assistant::SettingsUiSelector GetSettingsUiSelector();
// Construct SettingsUiUpdate for user opt-in.
assistant::SettingsUiUpdate GetSettingsUiUpdate(
const std::string& consent_token);
// Construct SettingsUiUpdate for email opt-in.
assistant::SettingsUiUpdate GetEmailOptInUpdate(bool opted_in);
using SettingZippyList = google::protobuf::RepeatedPtrField<
assistant::ClassicActivityControlUiTexts::SettingZippy>;
// Helper method to create zippy data.
base::Value CreateZippyData(const SettingZippyList& zippy_list);
// Helper method to create disclosure data.
base::Value CreateDisclosureData(const SettingZippyList& disclosure_list);
// Helper method to create get more screen data.
base::Value CreateGetMoreData(bool email_optin_needed,
const assistant::EmailOptInUi& email_optin_ui);
// Get string constants for settings ui.
base::Value GetSettingsUiStrings(const assistant::SettingsUi& settings_ui,
bool activity_control_needed);
void RecordActivityControlConsent(Profile* profile,
std::string ui_audit_key,
bool opted_in);
} // namespace chromeos
#endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_ASSISTANT_OPTIN_ASSISTANT_OPTIN_UTILS_H_
// Copyright 2018 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.
#ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_LOGIN_ASSISTANT_OPTIN_FLOW_SCREEN_HANDLER_H_
#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_LOGIN_ASSISTANT_OPTIN_FLOW_SCREEN_HANDLER_H_
#include <memory>
#include <string>
#include "base/macros.h"
#include "chrome/browser/chromeos/arc/voice_interaction/voice_interaction_controller_client.h"
#include "chrome/browser/chromeos/login/screens/assistant_optin_flow_screen_view.h"
#include "chrome/browser/ui/webui/chromeos/login/base_screen_handler.h"
#include "chromeos/services/assistant/public/mojom/settings.mojom.h"
namespace chromeos {
// TODO(updowndota): Refactor to reuse AssistantOptInHandler methods.
class AssistantOptInFlowScreenHandler
: public BaseScreenHandler,
public AssistantOptInFlowScreenView,
public arc::VoiceInteractionControllerClient::Observer {
public:
AssistantOptInFlowScreenHandler();
~AssistantOptInFlowScreenHandler() override;
// BaseScreenHandler:
void DeclareLocalizedValues(
::login::LocalizedValuesBuilder* builder) override;
void RegisterMessages() override;
// AssistantOptInFlowScreenView:
void Bind(AssistantOptInFlowScreen* screen) override;
void Unbind() override;
void Show() override;
void Hide() override;
// Send messages to the page.
void ShowNextScreen();
// Handle user opt-in result.
void OnActivityControlOptInResult(bool opted_in);
void OnEmailOptInResult(bool opted_in);
private:
// BaseScreenHandler:
void Initialize() override;
// arc::VoiceInteractionControllerClient::Observer overrides
void OnStateChanged(ash::mojom::VoiceInteractionState state) override;
// Connect to assistant settings manager.
void BindAssistantSettingsManager();
// Send GetSettings request for the opt-in UI.
void SendGetSettingsRequest();
// Send message and consent data to the page.
void ReloadContent(const base::Value& dict);
void AddSettingZippy(const std::string& type, const base::Value& data);
// Handle response from the settings manager.
void OnGetSettingsResponse(const std::string& settings);
void OnUpdateSettingsResponse(const std::string& settings);
// Handler for JS WebUI message.
void HandleLoadingScreenUserAction(const std::string& action);
void HandleValuePropScreenUserAction(const std::string& action);
void HandleThirdPartyScreenUserAction(const std::string& action);
void HandleGetMoreScreenUserAction(const bool screen_context,
const bool email_opted_in);
void HandleReadyScreenUserAction(const std::string& action);
void HandleValuePropScreenShown();
void HandleThirdPartyScreenShown();
void HandleGetMoreScreenShown();
void HandleReadyScreenShown();
void HandleHotwordResult(bool enable_hotword);
void HandleFlowFinished();
void HandleFlowInitialized();
AssistantOptInFlowScreen* screen_ = nullptr;
// Whether the screen should be shown right after initialization.
bool show_on_init_ = false;
// Consent token used to complete the opt-in.
std::string consent_token_;
// An opaque token for audit record.
std::string ui_audit_key_;
// Whether activity control is needed for user.
bool activity_control_needed_ = true;
// Whether email optin is needed for user.
bool email_optin_needed_ = false;
// Whether user chose to enable hotword.
bool enable_hotword_ = true;
assistant::mojom::AssistantSettingsManagerPtr settings_manager_;
base::WeakPtrFactory<AssistantOptInFlowScreenHandler> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(AssistantOptInFlowScreenHandler);
};
} // namespace chromeos
#endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_LOGIN_ASSISTANT_OPTIN_FLOW_SCREEN_HANDLER_H_
......@@ -38,6 +38,7 @@
#include "chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.h"
#include "chrome/browser/ui/webui/chromeos/login/arc_kiosk_splash_screen_handler.h"
#include "chrome/browser/ui/webui/chromeos/login/arc_terms_of_service_screen_handler.h"
#include "chrome/browser/ui/webui/chromeos/login/assistant_optin_flow_screen_handler.h"
#include "chrome/browser/ui/webui/chromeos/login/auto_enrollment_check_screen_handler.h"
#include "chrome/browser/ui/webui/chromeos/login/base_screen_handler.h"
#include "chrome/browser/ui/webui/chromeos/login/controller_pairing_screen_handler.h"
......@@ -424,6 +425,8 @@ void OobeUI::ConfigureOobeDisplay() {
AddScreenHandler(std::make_unique<UpdateRequiredScreenHandler>());
AddScreenHandler(std::make_unique<AssistantOptInFlowScreenHandler>());
// Initialize KioskAppMenuHandler. Note that it is NOT a screen handler.
auto kiosk_app_menu_handler =
std::make_unique<KioskAppMenuHandler>(network_state_informer_);
......@@ -599,6 +602,10 @@ UpdateRequiredView* OobeUI::GetUpdateRequiredScreenView() {
return GetView<UpdateRequiredScreenHandler>();
}
AssistantOptInFlowScreenView* OobeUI::GetAssistantOptInFlowScreenView() {
return GetView<AssistantOptInFlowScreenHandler>();
}
UserImageView* OobeUI::GetUserImageView() {
return GetView<UserImageScreenHandler>();
}
......
......@@ -29,6 +29,7 @@ class AppDownloadingScreenView;
class AppLaunchSplashScreenView;
class ArcKioskSplashScreenView;
class ArcTermsOfServiceScreenView;
class AssistantOptInFlowScreenView;
class AutoEnrollmentCheckScreenView;
class BaseScreenHandler;
class ControllerPairingScreenView;
......@@ -137,6 +138,7 @@ class OobeUI : public content::WebUIController,
VoiceInteractionValuePropScreenView* GetVoiceInteractionValuePropScreenView();
WaitForContainerReadyScreenView* GetWaitForContainerReadyScreenView();
UpdateRequiredView* GetUpdateRequiredScreenView();
AssistantOptInFlowScreenView* GetAssistantOptInFlowScreenView();
GaiaView* GetGaiaScreenView();
UserBoardView* GetUserBoardView();
DiscoverScreenView* GetDiscoverScreenView();
......
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