Skip to content

Commit

Permalink
Parent access widget: create offline screen
Browse files Browse the repository at this point in the history
Create an "offline" screen for parent access widget and
show it when the dialog is displayed without network
connection.

Bug: b:258486265
Change-Id: If6d02b5e566215385328f288ad48b1746036ea80
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4031011
Reviewed-by: Aga Wronska <agawronska@chromium.org>
Reviewed-by: Dan S <danan@chromium.org>
Commit-Queue: Galen Corey <galenemco@chromium.org>
Reviewed-by: Kyle Horimoto <khorimoto@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1075280}
  • Loading branch information
Galen Corey authored and Chromium LUCI CQ committed Nov 23, 2022
1 parent 8f8f242 commit 18eba87
Show file tree
Hide file tree
Showing 12 changed files with 164 additions and 4 deletions.
6 changes: 6 additions & 0 deletions chrome/app/chromeos_strings.grdp
Expand Up @@ -5963,6 +5963,12 @@ You can manage this account’s settings by installing the Family Link app on yo
<message name="IDS_PARENT_ACCESS_ERROR_DESCRIPTION" desc="Message shown if the parent access dialog has failed to load for any reason.">
Please try again later
</message>
<message name="IDS_PARENT_ACCESS_OFFLINE_HEADING" desc="Heading string shown in the parent access flow when the network is not available.">
Can’t connect to the internet
</message>
<message name="IDS_PARENT_ACCESS_OFFLINE_DESCRIPTION" desc="Description shown in the parent access flow when the network is not available.">
Check your internet connection
</message>

<!-- Strings for gnubby U2FD authentication UI -->
<message name="IDS_GNUBBY_NOTIFICATION_TITLE" desc="Title for notification informing user to press power button for gnubby U2FD.">
Expand Down
@@ -0,0 +1 @@
51ee570fb62082b02ee0266f239ab986e2f3caa5
@@ -0,0 +1 @@
51ee570fb62082b02ee0266f239ab986e2f3caa5
1 change: 1 addition & 0 deletions chrome/browser/browser_resources.grd
Expand Up @@ -316,6 +316,7 @@
<include name="IDR_PARENT_ACCESS_AFTER_JS" file="${root_gen_dir}\chrome\browser\resources\chromeos\parent_access\parent_access_after.js" use_base_dir="false" type="BINDATA" />
<include name="IDR_PARENT_ACCESS_ERROR_JS" file="${root_gen_dir}\chrome\browser\resources\chromeos\parent_access\parent_access_error.js" use_base_dir="false" type="BINDATA" />
<include name="IDR_PARENT_ACCESS_WEBVIEW_MANAGER_JS" file="resources\chromeos\parent_access\webview_manager.js" type="BINDATA" />
<include name="IDR_PARENT_ACCESS_OFFLINE_JS" file="${root_gen_dir}\chrome\browser\resources\chromeos\parent_access\parent_access_offline.js" use_base_dir="false" type="BINDATA" />
<include name="IDR_LOCAL_WEB_APPROVALS_AFTER_JS" file="${root_gen_dir}\chrome\browser\resources\chromeos\parent_access\flows\local_web_approvals_after.js" use_base_dir="false" type="BINDATA" />
<include name="IDR_PARENT_ACCESS_CONTROLLER_JS" file="resources\chromeos\parent_access\parent_access_controller.js" type="BINDATA" />
<include name="IDR_PARENT_ACCESS_UI_HANDLER_JS" file="resources\chromeos\parent_access\parent_access_ui_handler.js" type="BINDATA" />
Expand Down
8 changes: 8 additions & 0 deletions chrome/browser/resources/chromeos/parent_access/BUILD.gn
Expand Up @@ -42,6 +42,7 @@ js_library("parent_access_app") {
deps = [
":parent_access_after",
":parent_access_error",
":parent_access_offline",
":parent_access_ui",
":parent_access_ui_handler",
"//chrome/browser/ui/webui/ash/parent_access:mojo_bindings_webui_js",
Expand All @@ -63,6 +64,12 @@ js_library("parent_access_error") {
]
}

js_library("parent_access_offline") {
deps = [
"//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
]
}

js_library("parent_access_ui") {
deps = [
":parent_access_controller",
Expand All @@ -89,6 +96,7 @@ html_to_js("web_components") {
js_files = [
"parent_access_after.js",
"parent_access_app.js",
"parent_access_offline.js",
"parent_access_error.js",
"parent_access_ui.js",
]
Expand Down
Expand Up @@ -5,4 +5,6 @@
</parent-access-after>
<parent-access-error id="parent-access-error" slot="view">
</parent-access-error>
<parent-access-offline id="parent-access-offline" slot="view">
</parent-access-offline>
</cr-view-manager>
Expand Up @@ -8,6 +8,7 @@
import './strings.m.js';
import './parent_access_after.js';
import './parent_access_error.js';
import './parent_access_offline.js';
import './parent_access_ui.js';
import 'chrome://resources/cr_elements/cr_view_manager/cr_view_manager.js';

Expand All @@ -21,6 +22,7 @@ export const Screens = {
ONLINE_FLOW: 'parent-access-ui',
AFTER_FLOW: 'parent-access-after',
ERROR: 'parent-access-error',
OFFLINE: 'parent-access-offline',
};

class ParentAccessApp extends PolymerElement {
Expand Down Expand Up @@ -59,8 +61,24 @@ class ParentAccessApp extends PolymerElement {
this.onError_();
});

// TODO(b/200187536): Show offline screen if device is offline.
this.currentScreen_ = Screens.ONLINE_FLOW;
window.addEventListener('online', () => {
if (this.currentScreen_ !== Screens.ERROR) {
this.currentScreen_ = Screens.ONLINE_FLOW;
/** @type {CrViewManagerElement} */ (this.$.viewManager)
.switchView(this.currentScreen_);
}
});

window.addEventListener('offline', () => {
if (this.currentScreen_ !== Screens.ERROR) {
this.currentScreen_ = Screens.OFFLINE;
/** @type {CrViewManagerElement} */ (this.$.viewManager)
.switchView(this.currentScreen_);
}
});

this.currentScreen_ =
navigator.onLine ? Screens.ONLINE_FLOW : Screens.OFFLINE;
/** @type {CrViewManagerElement} */ (this.$.viewManager)
.switchView(this.currentScreen_);
}
Expand Down
@@ -0,0 +1,37 @@
<style>
#offline-screen {
background-color: var(--cros-bg-color-elevation-1);
box-sizing: border-box;
display: flex;
flex-direction: column;
height: 100%;
justify-content: flex-start;
padding: 26px 24px 20px;
}

.google-logo {
width: 100px;
}

.offline-text {
align-items: center;
display: flex;
font-size: 14px;
margin-top: 26px;
}

.offline-title {
font-family: var(--cros-font-family-google-sans);
font-size: 24px;
font-weight: 500;
margin-top: 32px;
}
</style>

<div id="offline-screen">
<img class="google-logo" src="chrome://theme/IDR_LOGO_GOOGLE_COLOR_90"
alt="Google">
</img>
<div class="offline-title"> $i18n{offlineTitle} </div>
<div class="offline-text"> $i18n{offlineDescription} </div>
</div>
@@ -0,0 +1,18 @@
// Copyright 2022 The Chromium Authors
// 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/cr_view_manager/cr_view_manager.js';

import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';

class ParentAccessOffline extends PolymerElement {
static get is() {
return 'parent-access-offline';
}

static get template() {
return html`{__html_template__}`;
}
}
customElements.define(ParentAccessOffline.is, ParentAccessOffline);
4 changes: 4 additions & 0 deletions chrome/browser/ui/webui/ash/parent_access/parent_access_ui.cc
Expand Up @@ -81,6 +81,8 @@ void ParentAccessUI::SetUpResources() {
source->AddResourcePath("parent_access_error.js", IDR_PARENT_ACCESS_ERROR_JS);
source->AddResourcePath("flows/local_web_approvals_after.js",
IDR_LOCAL_WEB_APPROVALS_AFTER_JS);
source->AddResourcePath("parent_access_offline.js",
IDR_PARENT_ACCESS_OFFLINE_JS);
source->AddResourcePath("parent_access_ui.mojom-webui.js",
IDR_PARENT_ACCESS_UI_MOJOM_WEBUI_JS);
source->AddResourcePath("webview_manager.js",
Expand All @@ -100,6 +102,8 @@ void ParentAccessUI::SetUpResources() {
{"localWebApprovalsAfterDetails",
IDS_PARENT_ACCESS_LOCAL_WEB_APPROVALS_AFTER_DETAILS},
{"webviewLoadingMessage", IDS_PARENT_ACCESS_WEBVIEW_LOADING_MESSAGE},
{"offlineTitle", IDS_PARENT_ACCESS_OFFLINE_HEADING},
{"offlineDescription", IDS_PARENT_ACCESS_OFFLINE_DESCRIPTION},
{"errorTitle", IDS_PARENT_ACCESS_ERROR_TITLE},
{"errorDescription", IDS_PARENT_ACCESS_ERROR_DESCRIPTION},
};
Expand Down
Expand Up @@ -9,9 +9,8 @@ import 'chrome://parent-access/strings.m.js';
import {Screens} from 'chrome://parent-access/parent_access_app.js';
import {GetOAuthTokenStatus} from 'chrome://parent-access/parent_access_ui.mojom-webui.js';
import {setParentAccessUIHandlerForTest} from 'chrome://parent-access/parent_access_ui_handler.js';
import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';

import {assertEquals, assertNotEquals} from 'chrome://webui-test/chai_assert.js';
import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';

import {buildWebApprovalsParams} from './parent_access_test_utils.js';
import {TestParentAccessUIHandler} from './test_parent_access_ui_handler.js';
Expand All @@ -24,6 +23,10 @@ parent_access_app_tests.TestNames = {
TestShowWebApprovalsAfterFlow:
'Tests that the web approvals after flow is shown',
TestShowErrorScreenOnOAuthFailure: 'Tests that the error screen is shown',
TestWebApprovalsOffline:
'Tests that dialog switches in/out of offline screen',
TestErrorStateIsTerminal:
'Tests that going offline/online does not switch away from error screen',
};

suite(parent_access_app_tests.suiteName, function() {
Expand Down Expand Up @@ -77,4 +80,57 @@ suite(parent_access_app_tests.suiteName, function() {
// Verify error screen is showing.
assertEquals(parentAccessApp.currentScreen_, Screens.ERROR);
});

test(parent_access_app_tests.TestNames.TestWebApprovalsOffline, async () => {
// Set up the ParentAccessParams for the web approvals flow.
const handler = new TestParentAccessUIHandler();
handler.setParentAccessParams(buildWebApprovalsParams());
handler.setOAuthTokenStatus('token', GetOAuthTokenStatus.kSuccess);
setParentAccessUIHandlerForTest(handler);

// Create app element.
const parentAccessApp = document.createElement('parent-access-app');
document.body.appendChild(parentAccessApp);
await flushTasks();

// Verify online flow is showing
assertEquals(parentAccessApp.currentScreen_, Screens.ONLINE_FLOW);

// Verify offline screen shows when window triggers offline event
window.dispatchEvent(new Event('offline'));
await flushTasks();
assertEquals(parentAccessApp.currentScreen_, Screens.OFFLINE);

// Verify online screen shows when window triggers online event after being
// offline
window.dispatchEvent(new Event('online'));
await flushTasks();
assertEquals(parentAccessApp.currentScreen_, Screens.ONLINE_FLOW);
});

test(parent_access_app_tests.TestNames.TestErrorStateIsTerminal, async () => {
// Set up the TestParentAccessUIHandler
const handler = new TestParentAccessUIHandler();
handler.setParentAccessParams(buildWebApprovalsParams());
handler.setOAuthTokenStatus('token', GetOAuthTokenStatus.kError);
setParentAccessUIHandlerForTest(handler);

// Create app element.
const parentAccessApp = document.createElement('parent-access-app');
document.body.appendChild(parentAccessApp);
await flushTasks();

// Verify error screen is showing.
assertEquals(parentAccessApp.currentScreen_, Screens.ERROR);

// Verify error screen still showing after triggering offline event.
window.dispatchEvent(new Event('offline'));
await flushTasks();
assertEquals(parentAccessApp.currentScreen_, Screens.ERROR);

// Verify error screen still showing after triggering online event.
window.dispatchEvent(new Event('online'));
await flushTasks();
assertEquals(parentAccessApp.currentScreen_, Screens.ERROR);
});
});
Expand Up @@ -53,6 +53,14 @@ TEST_F('ParentAccessAppTest', 'TestShowErrorScreenOnOAuthFailure', function() {
parent_access_app_tests.TestNames.TestShowErrorScreenOnOAuthFailure);
});

TEST_F('ParentAccessAppTest', 'TestWebApprovalsOffline', function() {
this.runMochaTest(parent_access_app_tests.TestNames.TestWebApprovalsOffline);
});

TEST_F('ParentAccessAppTest', 'TestErrorStateIsTerminal', function() {
this.runMochaTest(parent_access_app_tests.TestNames.TestErrorStateIsTerminal);
});

var ParentAccessControllerTest = class extends testing.Test {
/** @override */
get browsePreload() {
Expand Down

0 comments on commit 18eba87

Please sign in to comment.