Commit eb6a862b authored by Danan S's avatar Danan S Committed by Commit Bot

Add WebUI to integrate child account conversion webflow.

- Create WebUI
- Add PostMessageAPI* and AddSupervisionAPI* JS classes for communication
with web-content.
- Added switch to control the feature:  ChromeOSAddSupervision


Bug: 937995
Change-Id: I1e65b1a899776b5aa9028921d028030d147baaec
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1500832
Commit-Queue: Danan S <danan@chromium.org>
Reviewed-by: default avatarDominick Ng <dominickn@chromium.org>
Reviewed-by: default avatarRoger Tawa <rogerta@chromium.org>
Reviewed-by: default avatarMichael Giuffrida <michaelpg@chromium.org>
Reviewed-by: default avatarGreg Thompson <grt@chromium.org>
Reviewed-by: default avatarSteven Bennetts <stevenjb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#659120}
parent 1e1c95f8
......@@ -458,6 +458,7 @@ source_set("chrome_content_browser_overlay_manifest") {
deps += [
"//chrome/browser/chromeos/kiosk_next_home/mojom",
"//chrome/browser/chromeos/supervision/mojom",
"//chrome/browser/ui/webui/chromeos/add_supervision:mojo_bindings",
"//chrome/browser/ui/webui/chromeos/machine_learning:mojo_bindings",
"//chromeos/assistant:buildflags",
"//chromeos/services/cellular_setup/public/mojom",
......
......@@ -50,6 +50,7 @@
#if defined(OS_CHROMEOS)
#include "chrome/browser/chromeos/kiosk_next_home/mojom/kiosk_next_home_interface_broker.mojom.h" // nogncheck
#include "chrome/browser/chromeos/supervision/mojom/onboarding_controller.mojom.h"
#include "chrome/browser/ui/webui/chromeos/add_supervision/add_supervision.mojom.h"
#include "chrome/browser/ui/webui/chromeos/machine_learning/machine_learning_internals_page_handler.mojom.h"
#include "chromeos/assistant/buildflags.h" // nogncheck
#include "chromeos/services/cellular_setup/public/mojom/cellular_setup.mojom.h"
......@@ -259,6 +260,9 @@ const service_manager::Manifest& GetChromeContentBrowserOverlayManifest() {
defined(OS_CHROMEOS)
mojom::DiscardsDetailsProvider,
performance_manager::mojom::WebUIGraphDump,
#endif
#if defined(OS_CHROMEOS)
add_supervision::mojom::AddSupervisionHandler,
#endif
mojom::BluetoothInternalsHandler,
mojom::InterventionsInternalsPageHandler,
......
......@@ -3909,4 +3909,9 @@
<message name="IDS_TPM_AUTO_UPDATE_REBOOT_NOTIFICATION_MESSAGE" desc="Text for the notification informing the user that a TPM update will be performed after reboot which will result in local data being deleted.">
The next time you restart your device, your administrator will perform a one-time update that will delete your local data.
</message>
<!-- Strings for Add Supervision screen -->
<message name="IDS_ADD_SUPERVISION_PAGE_TITLE" desc="Title for the Chrome OS Add Supervision screen.">
Add Supervision
</message>
</grit-part>
......@@ -5136,6 +5136,7 @@ grit("resources") {
if (is_chromeos) {
deps += [
"//chrome/browser/ui/webui/chromeos/add_supervision:mojo_bindings_js",
"//chrome/browser/ui/webui/chromeos/machine_learning:mojo_bindings_js",
]
}
......
......@@ -698,6 +698,11 @@
<include name="IDR_SYS_INTERNALS_IMAGE_CPU_SVG" file="resources\chromeos\sys_internals\img\cpu.svg" type="BINDATA" />
<include name="IDR_SYS_INTERNALS_IMAGE_MEMORY_SVG" file="resources\chromeos\sys_internals\img\memory.svg" type="BINDATA" />
<include name="IDR_SYS_INTERNALS_IMAGE_ZRAM_SVG" file="resources\chromeos\sys_internals\img\zram.svg" type="BINDATA" />
<include name="IDR_ADD_SUPERVISION_HTML" file="resources\chromeos\add_supervision\add_supervision.html" compress="gzip" type="BINDATA" />
<include name="IDR_ADD_SUPERVISION_JS" file="resources\chromeos\add_supervision\add_supervision.js" compress="gzip" type="BINDATA" />
<include name="IDR_ADD_SUPERVISION_API_SERVER_JS" file="resources\chromeos\add_supervision\add_supervision_api_server.js" compress="gzip" type="BINDATA" />
<include name="IDR_ADD_SUPERVISION_POST_MESSAGE_API_JS" file="resources\chromeos\add_supervision\post_message_api.js" compress="gzip" type="BINDATA" />
<include name="IDR_ADD_SUPERVISION_MOJOM_LITE_JS" file="${root_gen_dir}\chrome\browser\ui\webui\chromeos\add_supervision\add_supervision.mojom-lite.js" compress="gzip" use_base_dir="false" type="BINDATA" />
</if>
<if expr="chromeos">
<include name="IDR_ASSISTANT_LOGO_PNG" file="resources\chromeos\assistant_optin\assistant_logo.png" type="BINDATA" />
......
......@@ -36,6 +36,7 @@ grit("multidevice_setup_resources") {
group("closure_compile") {
deps = [
"add_supervision:closure_compile",
"bluetooth_pairing_dialog:closure_compile",
"braille_ime:closure_compile",
"internet_config_dialog:closure_compile",
......
# Copyright 2019 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("//third_party/closure_compiler/compile_js.gni")
js_type_check("closure_compile") {
deps = [
":add_supervision",
":add_supervision_api_server",
":post_message_api",
]
}
js_library("post_message_api") {
deps = []
}
js_library("add_supervision_api_server") {
deps = [
":post_message_api",
"//chrome/browser/ui/webui/chromeos/add_supervision:mojo_bindings_js_library_for_compile",
]
}
js_library("add_supervision") {
deps = [
":add_supervision_api_server",
"//ui/webui/resources/js:load_time_data",
]
externs_list = [
"$externs_path/chrome_extensions.js",
"$externs_path/webview_tag.js",
]
}
<!doctype html>
<html dir="$i18n{textdirection}" lang="$i18n{language}">
<head>
<title>$i18n{pageTitle}</title>
<meta charset="utf-8">
<script src="chrome://resources/js/cr.js"></script>
<script src="chrome://resources/js/assert.js"></script>
<script src="chrome://resources/js/load_time_data.js"></script>
<script src="chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js"></script>
<script src="strings.js"></script>
<script src="chrome/browser/ui/webui/chromeos/add_supervision/add_supervision.mojom-lite.js"></script>
<script src="post_message_api.js"></script>
<script src="add_supervision_api_server.js"></script>
<script src="add_supervision.js"></script>
<link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
<style>
html,
body {
height: 100%;
}
</style>
</head>
<body>
<webview id="webview"></webview>
</body>
</html>
// Copyright 2019 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.
let server = null;
const proxy = addSupervision.mojom.AddSupervisionHandler.getProxy();
document.addEventListener('DOMContentLoaded', () => {
proxy.getOAuthToken().then((result) => {
const url = loadTimeData.getString('webviewUrl');
const eventOriginFilter = loadTimeData.getString('eventOriginFilter');
const webview =
/** @type {!WebView} */ (document.querySelector('#webview'));
const oauthToken = result.oauthToken;
// Block any requests to URLs other than one specified
// by eventOriginFilter.
webview.request.onBeforeRequest.addListener(function(details) {
return {cancel: !details.url.startsWith(eventOriginFilter)};
}, {urls: ['<all_urls>']}, ['blocking']);
// Add the Authorizaton header, but only for URLs that prefix match the
// eventOrigin filter.
webview.request.onBeforeSendHeaders.addListener(function(details) {
details.requestHeaders.push(
{name: 'Authorization', value: 'Bearer ' + oauthToken});
return {requestHeaders: details.requestHeaders};
}, {urls: [eventOriginFilter + '/*']}, ['blocking', 'requestHeaders']);
webview.src = url;
// Set up the server.
server = new AddSupervisionAPIServer(webview, url, eventOriginFilter);
});
});
// Copyright 2019 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.
const METHOD_LIST = ['logOut', 'getInstalledArcApps', 'uninstallArcApps'];
/**
* Class that implements the client side of the AddSupervision postMessage API.
* All of the actual functionality is in the superclass. Family Link uses
* its own implementation of this client library to meet their separate
* google dev and deployment processes and standards, so this file serves
* as a reference implementation, and can be used by end-to-end tests of the
* API's behavior. It is not used in the build, but it is included by
* webview-example.html and webview-example2.html, which demonstrate how
* to use the API from an embedded webview.
*/
class AddSupervisionAPIClient extends PostMessageAPIClient {
constructor() {
super(METHOD_LIST);
}
}
// Copyright 2019 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.
/**
* The methods to expose to the client.
*/
const METHOD_LIST = ['logOut', 'getInstalledArcApps', 'uninstallArcApps'];
/**
* Class that implements the server side of the AddSupervision postMessage
* API. In the case of this API, the Add Supervision WebUI is the server, and
* the remote website that calls the API is the client. This is the opposite
* of the normal browser/web-server client/server relationship.
*/
class AddSupervisionAPIServer extends PostMessageAPIServer {
/*
* @constructor
* @param {!Element} webviewElement The <webview> element to listen to as a
* client.
* @param {string} targetURL The target URL to use for outgoing messages.
* This should be the same as the URL loaded in the webview.
* @param {string} originURLPrefix The URL prefix to use to filter incoming
* messages via the postMessage API.
*/
constructor(webviewElement, targetURL, originURLPrefix) {
super(webviewElement, METHOD_LIST, targetURL, originURLPrefix);
this.proxy_ = addSupervision.mojom.AddSupervisionHandler.getProxy();
this.registerMethod('logOut', this.logOut.bind(this));
this.registerMethod(
'getInstalledArcApps', this.getInstalledArcApps.bind(this));
this.registerMethod('uninstallArcApps', this.uninstallArcApps.bind(this));
}
/**
* Logs out of the device.
* @param {!Array} unused Placeholder unused empty parameter.
* @return {Promise} This promise is never actually resolved.
*/
logOut(unused) {
return this.proxy_.logOut();
}
/**
* @param {!Array} unused Placeholder unused empty parameter.
* @return {Promise<{
* packageNames: !Array<string>,
* }>} a promise whose success result is an array of package names of ARC
* apps installed on the device.
*/
getInstalledArcApps(unused) {
return this.proxy_.getInstalledArcApps();
}
/**
* Uninstall the specified ARC apps.
* @param {!Array<!string>} apps List of app package names to uninstall.
* @return {Promise} a promise whose successful result indicates the apps were
* uninstalled.
*/
uninstallArcApps(apps) {
return this.proxy_.uninstallArcApps(apps);
}
}
// Copyright 2019 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.
/**
* Class that provides the functionality for talking to a client
* over the PostMessageAPI. This should be subclassed and the
* methods provided in methodList should be implemented as methods
* of the subclass.
*/
class PostMessageAPIServer {
constructor(clientElement, methodList, targetURL, messageOriginURLFilter) {
/**
* The Window type element to which this server will listen for messages,
* probably a <webview>, but also could be an <iframe> or a browser window
* object.
* @private @const {!Element}
*/
this.clientElement_ = clientElement;
/**
* The guest URL embedded in the element above. Used for message targeting.
* This should be same as the URL loaded in the clientElement, i.e. the
* "src" attribute of a <webview>.
* @private @const {!URL}
*/
this.targetURL_ = new URL(targetURL);
/**
* Incoming messages received from origin URLs without this prefix
* will not be accepted. This should be used to restrict the API access
* to the intended guest content.
* @private @const {!URL}
*/
this.messageOriginURLFilter_ = new URL(messageOriginURLFilter);
/**
* Map that stores references to the methods implemented by the API.
* @private {!Map<string, Function>}
*/
this.apiFns_ = new Map();
// Listen for the embedding element to finish loading, then
// tell it to initialize by sending it a message, which will include
// a handle for it to use to send messages back.
this.clientElement_.addEventListener('contentload', () => {
this.clientElement_.contentWindow.postMessage(
'init', this.targetURL_.toString());
});
// Listen for events.
window.addEventListener('message', (event) => {
this.onMessage_(event);
});
}
/**
* Registers the specified method name with the specified
* function.
*
* @param {!string} methodName name of the method to register.
* @param {!Function} method The function to associate with the name.
*/
registerMethod(methodName, method) {
this.apiFns_.set(methodName, method);
}
/**
* Determines if the specified origin matches the origin filter.
* @private
* @param {!string} origin The origin URL to match with the filter.
* @return {boolean} whether the specified origin matches the filter.
*/
originMatchesFilter_(origin) {
const originURL = new URL(origin);
// We allow the pathname portion of the URL to be a prefix filter,
// to permit for different paths communicating with this server.
return originURL.protocol == this.messageOriginURLFilter_.protocol &&
originURL.host == this.messageOriginURLFilter_.host &&
originURL.pathname.startsWith(this.messageOriginURLFilter_.pathname);
}
/**
* Handles postMessage events from the client.
* @private
* @param {Event} event The postMessage event to handle.
*/
onMessage_(event) {
if (!this.originMatchesFilter_(event.origin)) {
console.error(
'Message received from unauthorized origin: ' + event.origin);
return;
}
const fn = event.data.fn;
const args = event.data.args || [];
if (!this.apiFns_.has(fn)) {
console.error('Unknown function requested: ' + fn);
return;
}
this.apiFns_.get(fn)(args).then(result => {
this.clientElement_.contentWindow.postMessage(
{
methodId: event.data.methodId,
result: result,
},
this.targetURL_.toString());
});
}
}
/**
* Class that provides the functionality for talking to a PostMessageAPIServer
* over the postMessage API. This should be subclassed and the methods in the
* server that the client needs to access should be provided in methodList.
*/
class PostMessageAPIClient {
/**
* @param {!Array<string>} methodList The list of methods accessible via the
* client.
* @param {!string} serverOriginURLFilter Only messages from this origin
* will be accepted.
*/
constructor(methodList, serverOriginURLFilter) {
/**
* @private @const {!string} Filter to use to validate
* the origin of received messages. The origin of messages
* must exactly match this value.
*/
this.serverOriginURLFilter_ = serverOriginURLFilter;
/**
* The parent window.
* @private {Window}
*/
this.parentWindow_ = null;
/*
* @private {number}
*/
this.nextMethodId_ = 0;
/**
* Map of methods awaiting a response.
* @private {!Map}
*/
this.methodsAwaitingResponse_ = new Map;
/**
* Function property that tracks whether client has
* been initialized by the server.
* @private {Function}
*/
this.boundOnInitialize_ = null;
// Generate the client-callable methods.
this.generateAPIMethods_(methodList);
}
/*
* Generates methods for the specified method names.
* @private
* @param {!Array<string>} methods The names of the methods.
*/
generateAPIMethods_(methods) {
methods.forEach((method) => {
Object.getPrototypeOf(this)[method] = function(args) {
return this.callApiFn_(method, args);
};
});
}
initialize() {
this.boundOnInitialize_ = this.onInitialize_.bind(this);
// Wait for an init message from the server.
window.addEventListener('message', this.boundOnInitialize_);
}
//
// Private implementation:
//
/**
* Handles initialization event sent from the server to establish
* communication.
* @private
* @param {!Event} event An event received when the initialization message is
* sent from the server.
*/
onInitialize_(event) {
if (!this.originMatchesFilter_(event.origin)) {
console.error(
'Initialization event received from non-authorized origin: ' +
event.origin);
return;
}
this.parentWindow_ = event.source;
window.removeEventListener('message', this.boundOnInitialize_);
this.boundOnInitialize_ = null;
window.addEventListener('message', this.onMessage_.bind(this));
}
/**
* Determine if the specified server origin URL matches the origin filter.
* @param {!string} origin The origin URL to match with the filter.
* @return {boolean} whether the specified origin matches the filter.
*/
originMatchesFilter_(origin) {
return origin == this.serverOriginURLFilter_;
}
/**
* Handles postMessage events sent from the server.
* @param {Event} event An event received from the server via the postMessage
* API.
*/
onMessage_(event) {
if (!this.originMatchesFilter_(event.origin)) {
console.error(
'Message received from non-authorized origin: ' + event.origin);
return;
}
if (event.source != this.parentWindow_) {
console.error('discarding event whose source is not the parent window');
return;
}
if (!this.methodsAwaitingResponse_.has(event.data.methodId)) {
console.error('discarding event method is not waiting for a response');
return;
}
let method = this.methodsAwaitingResponse_.get(event.data.methodId);
this.methodsAwaitingResponse_.delete(event.data.methodId);
method(event.data.result);
}
/**
* Converts a function call with arguments into a postMessage event
* and sends it to the server via the postMessage API.
* @param {string} fn The function to call.
* @param {!Array<Object>} args The arguments to pass to the function.
* @return {!Promise} A promise capturing the executing of the function.
*/
callApiFn_(fn, args) {
let newMethodId = this.nextMethodId_++;
let promise = new Promise((resolve, reject) => {
if (!this.parentWindow_) {
reject('No parent window defined');
}
this.parentWindow_.postMessage(
{
methodId: newMethodId,
fn: fn,
args: args,
},
'*');
this.methodsAwaitingResponse_.set(newMethodId, resolve);
});
return promise;
}
}
<!doctype html>
<head>
<script src="post_message_api.js"></script>
<script src="add_supervision_api_client.js"></script>
<script>
/** @type {AddSupervisionAPIClient} */
let api = new AddSupervisionAPIClient();
api.initialize();
//
// UI implementation:
//
document.addEventListener('DOMContentLoaded', () => {
const logoutBtn = document.querySelector('#logout');
logoutBtn.addEventListener('click', () => {
api.logOut().then(() => {
// This won't get reached.
}, (error) => {
console.error(error.message);
});
});
const getArcAppsBtn = document.querySelector('#get_arc_apps');
getArcAppsBtn.addEventListener('click', () => {
api.getInstalledArcApps()
.then(result => {
console.error("Installed apps: " + result);
const arc_apps_text = document.querySelector('#arc_apps');
arc_apps_text.value = result.apps;
}, err => {
console.error(err);
})
});
const uninstallArcAppsBtn = document.querySelector('#uninstall_arc_apps');
uninstallArcAppsBtn.addEventListener('click', () => {
api.uninstallArcApps(
['com.netflix.mediaclient', 'com.google.android.videos'])
.then(() => {
console.log('uninstalled arc apps');
}, (error) => {
console.error(error.message);
});
});
});
</script>
</head>
<body>
<h2>Add Supervision Webview</h2>
<div>
<button id="logout">Logout</button>
</div>
<div>
<button id="get_arc_apps">Get ARC Apps</button>
</div>
<div>
<button id="uninstall_arc_apps">Uninstall ARC Apps</button>
</div>
<div>
<input type="text" id="arc_apps"
minlength="0" maxlength="128" size="128">
</div>
<div>
<a href="webview-example2.html">Link to another page</a>
</div>
</body>
<!doctype html>
<head>
<script src="post_message_api.js"></script>
<script src="add_supervision_api_client.js"></script>
<script>
/** @type {AddSupervisionAPIClient} */
let api = new AddSupervisionAPIClient();
api.initialize();
//
// UI implementation:
//
document.addEventListener('DOMContentLoaded', () => {
const logoutBtn = document.querySelector('#logout');
logoutBtn.addEventListener('click', () => {
api.logOut().then(() => {
// This won't get reached.
}, (error) => {
console.error(error.message);
});
});
const getArcAppsBtn = document.querySelector('#get_arc_apps');
getArcAppsBtn.addEventListener('click', () => {
api.getInstalledArcApps()
.then(result => {
console.error("Installed apps: " + result);
const arc_apps_text = document.querySelector('#arc_apps');
arc_apps_text.value = result.apps;
}, err => {
console.error(err);
})
});
const uninstallArcAppsBtn = document.querySelector('#uninstall_arc_apps');
uninstallArcAppsBtn.addEventListener('click', () => {
api.uninstallArcApps(
['com.netflix.mediaclient', 'com.google.android.videos'])
.then(() => {
console.log('uninstalled arc apps');
}, (error) => {
console.error(error.message);
});
});
});
</script>
</head>
<body>
<h2>Add Supervision Webview</h2>
<div>
<button id="logout">Logout</button>
</div>
<div>
<button id="get_arc_apps">Get ARC Apps</button>
</div>
<div>
<button id="uninstall_arc_apps">Uninstall ARC Apps</button>
</div>
<div>
<input type="text" id="arc_apps"
minlength="0" maxlength="128" size="128">
</div>
</body>
......@@ -1539,6 +1539,8 @@ jumbo_split_static_library("ui") {
"webui/chromeos/add_supervision/add_supervision_handler.h",
"webui/chromeos/add_supervision/add_supervision_handler_utils.cc",
"webui/chromeos/add_supervision/add_supervision_handler_utils.h",
"webui/chromeos/add_supervision/add_supervision_ui.cc",
"webui/chromeos/add_supervision/add_supervision_ui.h",
"webui/chromeos/arc_graphics_tracing/arc_graphics_tracing_handler.cc",
"webui/chromeos/arc_graphics_tracing/arc_graphics_tracing_handler.h",
"webui/chromeos/arc_graphics_tracing/arc_graphics_tracing_ui.cc",
......
......@@ -147,6 +147,7 @@
#include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_service.h"
#include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_factory.h"
#include "chrome/browser/chromeos/secure_channel/secure_channel_client_provider.h"
#include "chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_ui.h"
#include "chrome/browser/ui/webui/chromeos/arc_graphics_tracing/arc_graphics_tracing_ui.h"
#include "chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.h"
#include "chrome/browser/ui/webui/chromeos/bluetooth_pairing_dialog.h"
......@@ -174,6 +175,7 @@
#include "chromeos/components/multidevice/debug_webui/proximity_auth_ui.h"
#include "chromeos/components/multidevice/debug_webui/url_constants.h"
#include "chromeos/constants/chromeos_features.h"
#include "chromeos/constants/chromeos_switches.h"
#include "components/arc/arc_features.h"
#endif
......@@ -499,6 +501,10 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui,
}
if (url.host_piece() == chrome::kChromeUIAccountManagerWelcomeHost)
return &NewWebUI<chromeos::AccountManagerWelcomeUI>;
if (chromeos::switches::IsAddSupervisionEnabled()) {
if (url.host_piece() == chrome::kChromeUIAddSupervisionHost)
return &NewWebUI<chromeos::AddSupervisionUI>;
}
if (url.host_piece() == chrome::kChromeUIBluetoothPairingHost)
return &NewWebUI<chromeos::BluetoothPairingDialogUI>;
if (url.host_piece() == chrome::kChromeUICellularSetupHost)
......
// Copyright 2019 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/webui/chromeos/add_supervision/add_supervision_ui.h"
#include <memory>
#include <utility>
#include "base/bind.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_handler.h"
#include "chrome/common/webui_url_constants.h"
#include "chrome/grit/browser_resources.h"
#include "chrome/grit/generated_resources.h"
#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_data_source.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/resources/grit/ui_resources.h"
namespace chromeos {
const char kAddSupervisionURL[] =
"https://families.google.com/supervision/chrome";
const char kAddSupervisionEventOriginFilter[] = "https://families.google.com";
AddSupervisionUI::AddSupervisionUI(content::WebUI* web_ui)
: ui::MojoWebUIController(web_ui) {
// Register the Mojo API handler.
AddHandlerToRegistry(base::BindRepeating(
&AddSupervisionUI::BindAddSupervisionHandler, base::Unretained(this)));
// Set up the basic page framework.
SetupResources();
}
void AddSupervisionUI::SetupResources() {
Profile* profile = Profile::FromWebUI(web_ui());
std::unique_ptr<content::WebUIDataSource> source(
content::WebUIDataSource::Create(chrome::kChromeUIAddSupervisionHost));
source->AddResourcePath("post_message_api.js",
IDR_ADD_SUPERVISION_POST_MESSAGE_API_JS);
source->AddResourcePath("add_supervision_api_server.js",
IDR_ADD_SUPERVISION_API_SERVER_JS);
source->AddResourcePath("add_supervision.js", IDR_ADD_SUPERVISION_JS);
source->AddLocalizedString("pageTitle", IDS_ADD_SUPERVISION_PAGE_TITLE);
// Full paths (relative to src) are important for Mojom generated files.
source->AddResourcePath(
"chrome/browser/ui/webui/chromeos/add_supervision/"
"add_supervision.mojom-lite.js",
IDR_ADD_SUPERVISION_MOJOM_LITE_JS);
source->SetJsonPath("strings.js");
source->SetDefaultResource(IDR_ADD_SUPERVISION_HTML);
source->AddString("webviewUrl", kAddSupervisionURL);
source->AddString("eventOriginFilter", kAddSupervisionEventOriginFilter);
content::WebUIDataSource::Add(profile, source.release());
}
AddSupervisionUI::~AddSupervisionUI() = default;
void AddSupervisionUI::BindAddSupervisionHandler(
add_supervision::mojom::AddSupervisionHandlerRequest request) {
mojo_api_handler_.reset(
new AddSupervisionHandler(std::move(request), web_ui()));
}
} // namespace chromeos
// Copyright 2019 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_ADD_SUPERVISION_ADD_SUPERVISION_UI_H_
#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_ADD_SUPERVISION_ADD_SUPERVISION_UI_H_
#include <memory>
#include "base/macros.h"
#include "chrome/browser/ui/webui/chromeos/add_supervision/add_supervision.mojom.h"
#include "ui/webui/mojo_web_ui_controller.h"
namespace chromeos {
// Controller for chrome://add-supervision
class AddSupervisionUI : public ui::MojoWebUIController {
public:
explicit AddSupervisionUI(content::WebUI* web_ui);
~AddSupervisionUI() override;
private:
void BindAddSupervisionHandler(
add_supervision::mojom::AddSupervisionHandlerRequest request);
void SetupResources();
std::unique_ptr<add_supervision::mojom::AddSupervisionHandler>
mojo_api_handler_;
DISALLOW_COPY_AND_ASSIGN(AddSupervisionUI);
};
} // namespace chromeos
#endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_ADD_SUPERVISION_ADD_SUPERVISION_UI_H_
......@@ -241,7 +241,8 @@
"chrome://mobilesetup/*",
"chrome://oobe/*",
"chrome://password-change/*",
"chrome://assistant-optin/*"
"chrome://assistant-optin/*",
"chrome://add-supervision/*"
]
}],
"cloudPrintPrivate": {
......
......@@ -189,6 +189,8 @@ const char kChromeUIAccountManagerWelcomeHost[] = "account-manager-welcome";
const char kChromeUIAccountManagerWelcomeURL[] =
"chrome://account-manager-welcome";
const char kChromeUIActivationMessageHost[] = "activationmessage";
const char kChromeUIAddSupervisionHost[] = "add-supervision";
const char kChromeUIAddSupervisionURL[] = "chrome://add-supervision/";
const char kChromeUIArcGraphicsTracingHost[] = "arc-graphics-tracing";
const char kChromeUIArcGraphicsTracingURL[] = "chrome://arc-graphics-tracing/";
const char kChromeUIAssistantOptInHost[] = "assistant-optin";
......@@ -251,6 +253,7 @@ bool IsSystemWebUIHost(base::StringPiece host) {
static const char* const kHosts[] = {
kChromeUIAccountManagerWelcomeHost,
kChromeUIActivationMessageHost,
kChromeUIAddSupervisionHost,
kChromeUIAssistantOptInHost,
kChromeUIBluetoothPairingHost,
kChromeUICellularSetupHost,
......
......@@ -189,6 +189,8 @@ extern const char kChromeUIWebApksHost[];
extern const char kChromeUIAccountManagerWelcomeHost[];
extern const char kChromeUIAccountManagerWelcomeURL[];
extern const char kChromeUIActivationMessageHost[];
extern const char kChromeUIAddSupervisionHost[];
extern const char kChromeUIAddSupervisionURL[];
extern const char kChromeUIArcGraphicsTracingHost[];
extern const char kChromeUIArcGraphicsTracingURL[];
extern const char kChromeUIAssistantOptInHost[];
......
......@@ -39,6 +39,10 @@ const base::Feature kInstantTetheringBackgroundAdvertisementSupport{
const base::Feature kAccountManager{"ChromeOSAccountManager",
base::FEATURE_DISABLED_BY_DEFAULT};
// Controls whether to enable Chrome OS Add Child Account Supervision flow.
const base::Feature kAddSupervision{"ChromeOSAddSupervision",
base::FEATURE_DISABLED_BY_DEFAULT};
// Controls whether to enable Google Assistant feature.
const base::Feature kAssistantFeature{"ChromeOSAssistant",
base::FEATURE_DISABLED_BY_DEFAULT};
......@@ -570,6 +574,10 @@ bool IsAccountManagerEnabled() {
return base::FeatureList::IsEnabled(kAccountManager);
}
bool IsAddSupervisionEnabled() {
return base::FeatureList::IsEnabled(kAddSupervision);
}
bool IsAssistantFlagsEnabled() {
return base::FeatureList::IsEnabled(kAssistantFeature);
}
......
......@@ -200,6 +200,9 @@ COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const char kWakeOnWifiPacket[];
// Controls whether to enable Chrome OS Account Manager.
COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const base::Feature kAccountManager;
// Controls whether to enable Chrome OS Add Child Account Supervision flow.
COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const base::Feature kAddSupervision;
// Controls whether to enable Google Assistant feature.
COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
extern const base::Feature kAssistantFeature;
......@@ -242,6 +245,9 @@ COMPONENT_EXPORT(CHROMEOS_CONSTANTS) bool IsCellularFirstDevice();
// Returns true if Chrome OS Account Manager is enabled.
COMPONENT_EXPORT(CHROMEOS_CONSTANTS) bool IsAccountManagerEnabled();
// Returns true if Chrome OS Add Child Supervision flow is enabled.
COMPONENT_EXPORT(CHROMEOS_CONSTANTS) bool IsAddSupervisionEnabled();
// Returns true if Google Assistant flags are enabled.
COMPONENT_EXPORT(CHROMEOS_CONSTANTS) bool IsAssistantFlagsEnabled();
......
......@@ -229,6 +229,8 @@
"channel": "stable",
"contexts": ["webui"],
"matches": [
"chrome://add-supervision/*",
"chrome://assistant-optin/*",
"chrome://cast/*",
"chrome://discards/*",
"chrome://extensions-frame/*",
......@@ -239,8 +241,7 @@
"chrome://media-router/*",
"chrome://mobilesetup/*",
"chrome://oobe/*",
"chrome://password-change/*",
"chrome://assistant-optin/*"
"chrome://password-change/*"
]
}
],
......@@ -624,6 +625,8 @@
"internal": true,
"contexts": ["webui"],
"matches": [
"chrome://add-supervision/*",
"chrome://assistant-optin/*",
"chrome://chrome-signin/*",
"chrome://discards/*",
"chrome://hats/*",
......@@ -631,8 +634,7 @@
"chrome://media-router/*",
"chrome://mobilesetup/*",
"chrome://oobe/*",
"chrome://password-change/*",
"chrome://assistant-optin/*"
"chrome://password-change/*"
]
}],
"webViewInternal": [{
......@@ -644,6 +646,8 @@
"channel": "stable",
"contexts": ["webui"],
"matches": [
"chrome://add-supervision/*",
"chrome://assistant-optin/*",
"chrome://chrome-signin/*",
"chrome://discards/*",
"chrome://hats/*",
......@@ -651,8 +655,7 @@
"chrome://media-router/*",
"chrome://mobilesetup/*",
"chrome://oobe/*",
"chrome://password-change/*",
"chrome://assistant-optin/*"
"chrome://password-change/*"
]
}],
"webViewRequest": [{
......@@ -662,14 +665,15 @@
"channel": "stable",
"contexts": ["webui"],
"matches": [
"chrome://add-supervision/*",
"chrome://assistant-optin/*",
"chrome://chrome-signin/*",
"chrome://discards/*",
"chrome://hats/*",
"chrome://home/*",
"chrome://media-router/*",
"chrome://mobilesetup/*",
"chrome://oobe/*",
"chrome://assistant-optin/*"
"chrome://oobe/*"
]
}]
}
......@@ -44,7 +44,7 @@ const char kChromeSyncSupervisedOAuth2Scope[] =
// OAuth2 scope for access to Google Family Link kid scope.
const char kKidFamilyOAuth2Scope[] =
"https://www.googleapis.com/auth/kid.family";
"https://www.googleapis.com/auth/kid.family.readonly";
// OAuth2 scope for access to Google Talk APIs (XMPP).
const char kGoogleTalkOAuth2Scope[] =
......
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