[CrOS Cellular] Add carrier provisioning page.
This CL loads the carrier page and handles any errors which may occur while interacting with it. Note that this CL makes use of a <webview>, so it modifies two JSON files to provide permission to chrome://cellular-setup to use that element. Bug: 991826 Change-Id: I6a3872dc5544ca387c01b9b4cb97bd7d1f4e9bb5 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1767601 Reviewed-by: Devlin <rdevlin.cronin@chromium.org> Reviewed-by: Steven Bennetts <stevenjb@chromium.org> Commit-Queue: Kyle Horimoto <khorimoto@chromium.org> Cr-Commit-Position: refs/heads/master@{#691855}
This commit is contained in:

committed by
Commit Bot

parent
4bf79f2d2e
commit
cfec9d675d
chrome
app
browser
ui
webui
chromeos
cellular_setup
common
extensions
extensions/common/api
ui/webui/resources/cr_components/chromeos/cellular_setup
@ -222,8 +222,17 @@
|
||||
<message name="IDS_CELLULAR_SETUP_SIM_DETECT_PAGE_ERROR_MESSAGE" desc="Message displayed under title in cellular setup when Chrome OS encounters an error preparing the cellular device for setup. Prompts user to insert SIM and try again.">
|
||||
Please insert your SIM and try again
|
||||
</message>
|
||||
<message name="IDS_CELLULAR_SETUP_PROVISIONING_PAGE_TITLE" desc="Title for cellular setup step in which the user uses the embedded carrier provisioning portal to make payment and activate the device." translateable="false">
|
||||
Provisioning Page
|
||||
<message name="IDS_CELLULAR_SETUP_PROVISIONING_PAGE_LOADING_TITLE" desc="Title for cellular setup step which indicates that a connection is in progress to the user's mobile data provider (e.g., Verizon).">
|
||||
Connecting to <ph name="CARRIER_NAME">$1<ex>Google Fi</ex></ph>
|
||||
</message>
|
||||
<message name="IDS_CELLULAR_SETUP_PROVISIONING_PAGE_ERROR_TITLE" desc="Title for cellular setup step which indicates that the Chromebook was unable to establish a connection to the user's mobile data provider (e.g., Verizon).">
|
||||
Couldn't connect to <ph name="CARRIER_NAME">$1<ex>Google Fi</ex></ph>
|
||||
</message>
|
||||
<message name="IDS_CELLULAR_SETUP_PROVISIONING_PAGE_ERROR_MESSAGE" desc="Message for the cellular setup step which indicates that the Chromebook was unable to establish a connection to the user's mobile data provider (e.g., Verizon).">
|
||||
Please try again. For technical support, contact <ph name="CARRIER_NAME">$1<ex>Google Fi</ex></ph>.
|
||||
</message>
|
||||
<message name="IDS_CELLULAR_SETUP_PROVISIONING_PAGE_ACTIVE_TITLE" desc="Title for cellular setup step which indicates that the Chromebook is in the process of connecting to a mobile network.">
|
||||
Connect to mobile network
|
||||
</message>
|
||||
<message name="IDS_CELLULAR_SETUP_FINAL_PAGE_TITLE" desc="Title for the final success screen of cellular setup that tells the user that setup is completed but service is being activated">
|
||||
Mobile data being activated
|
||||
|
@ -26,7 +26,14 @@ constexpr LocalizedString kLocalizedStringsWithoutPlaceholders[] = {
|
||||
{"simDetectPageErrorTitle", IDS_CELLULAR_SETUP_SIM_DETECT_PAGE_ERROR_TITLE},
|
||||
{"simDetectPageErrorMessage",
|
||||
IDS_CELLULAR_SETUP_SIM_DETECT_PAGE_ERROR_MESSAGE},
|
||||
{"provisioningPageTitle", IDS_CELLULAR_SETUP_PROVISIONING_PAGE_TITLE},
|
||||
{"provisioningPageLoadingTitle",
|
||||
IDS_CELLULAR_SETUP_PROVISIONING_PAGE_LOADING_TITLE},
|
||||
{"provisioningPageActiveTitle",
|
||||
IDS_CELLULAR_SETUP_PROVISIONING_PAGE_ACTIVE_TITLE},
|
||||
{"provisioningPageErrorTitle",
|
||||
IDS_CELLULAR_SETUP_PROVISIONING_PAGE_ERROR_TITLE},
|
||||
{"provisioningPageErrorMessage",
|
||||
IDS_CELLULAR_SETUP_PROVISIONING_PAGE_ERROR_MESSAGE},
|
||||
{"finalPageTitle", IDS_CELLULAR_SETUP_FINAL_PAGE_TITLE},
|
||||
{"finalPageMessage", IDS_CELLULAR_SETUP_FINAL_PAGE_MESSAGE},
|
||||
{"finalPageErrorTitle", IDS_CELLULAR_SETUP_FINAL_PAGE_ERROR_TITLE},
|
||||
|
@ -236,6 +236,7 @@
|
||||
"channel": "stable",
|
||||
"contexts": ["webui"],
|
||||
"matches": [
|
||||
"chrome://cellular-setup/*",
|
||||
"chrome://chrome-signin/*",
|
||||
"chrome://discards/*",
|
||||
"chrome://hats/*",
|
||||
|
@ -232,6 +232,7 @@
|
||||
"chrome://add-supervision/*",
|
||||
"chrome://assistant-optin/*",
|
||||
"chrome://cast/*",
|
||||
"chrome://cellular-setup/*",
|
||||
"chrome://discards/*",
|
||||
"chrome://extensions-frame/*", // TODO(dbeam): still needed?
|
||||
"chrome://extensions/*",
|
||||
@ -652,6 +653,7 @@
|
||||
"matches": [
|
||||
"chrome://add-supervision/*",
|
||||
"chrome://assistant-optin/*",
|
||||
"chrome://cellular-setup/*",
|
||||
"chrome://chrome-signin/*",
|
||||
"chrome://discards/*",
|
||||
"chrome://hats/*",
|
||||
@ -672,6 +674,7 @@
|
||||
"matches": [
|
||||
"chrome://add-supervision/*",
|
||||
"chrome://assistant-optin/*",
|
||||
"chrome://cellular-setup/*",
|
||||
"chrome://chrome-signin/*",
|
||||
"chrome://discards/*",
|
||||
"chrome://hats/*",
|
||||
@ -690,6 +693,7 @@
|
||||
"matches": [
|
||||
"chrome://add-supervision/*",
|
||||
"chrome://assistant-optin/*",
|
||||
"chrome://cellular-setup/*",
|
||||
"chrome://chrome-signin/*",
|
||||
"chrome://discards/*",
|
||||
"chrome://hats/*",
|
||||
|
@ -47,6 +47,11 @@ js_library("webview_post_util") {
|
||||
js_library("provisioning_page") {
|
||||
deps = [
|
||||
":base_page",
|
||||
":webview_post_util",
|
||||
]
|
||||
externs_list = [
|
||||
"$externs_path/chrome_extensions.js",
|
||||
"$externs_path/webview_tag.js",
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,11 @@
|
||||
selected="[[selectedPageName_]]"
|
||||
selected-item="{{selectedPage_}}">
|
||||
<sim-detect-page show-error="[[showError_]]"></sim-detect-page>
|
||||
<provisioning-page show-error="[[showError_]]"></provisioning-page>
|
||||
<provisioning-page show-error="{{showError_}}"
|
||||
cellular-metadata="[[cellularMetadata_]]"
|
||||
on-carrier-portal-loaded="onCarrierPortalLoaded_"
|
||||
on-carrier-portal-result="onCarrierPortalResult_">
|
||||
</provisioning-page>
|
||||
<final-page show-error="[[showError_]]"></final-page>
|
||||
</iron-pages>
|
||||
<button-bar show-try-again-button="[[showTryAgainButton_]]"
|
||||
|
@ -40,7 +40,7 @@ cr.define('cellularSetup', function() {
|
||||
|
||||
// The portal is a website served by the mobile carrier.
|
||||
if (state === State.WAITING_FOR_PORTAL_TO_LOAD) {
|
||||
return 5000; // 5 seconds.
|
||||
return 10000; // 10 seconds.
|
||||
}
|
||||
|
||||
// Finishing activation only requires sending a D-Bus message to Shill.
|
||||
@ -99,6 +99,16 @@ Polymer({
|
||||
*/
|
||||
showError_: {type: Boolean, value: false},
|
||||
|
||||
/**
|
||||
* Cellular metadata received via the onActivationStarted() callback. If
|
||||
* that callback has not occurred, this field is null.
|
||||
* @private {?chromeos.cellularSetup.mojom.CellularMetadata}
|
||||
*/
|
||||
cellularMetadata_: {
|
||||
type: Object,
|
||||
value: null,
|
||||
},
|
||||
|
||||
/**
|
||||
* Whether try again should be shown in the button bar.
|
||||
* @private {boolean}
|
||||
@ -149,13 +159,6 @@ Polymer({
|
||||
*/
|
||||
currentTimeoutId_: null,
|
||||
|
||||
/**
|
||||
* Cellular metadata received via the onActivationStarted() callback. If that
|
||||
* callback has not occurred, this field is null.
|
||||
* @private {?chromeos.cellularSetup.mojom.CellularMetadata}
|
||||
*/
|
||||
cellularMetadata_: null,
|
||||
|
||||
/**
|
||||
* Handler used to communicate state updates back to the CellularSetup
|
||||
* service.
|
||||
@ -320,6 +323,7 @@ Polymer({
|
||||
this.activationDelegateReceiver_.$.close();
|
||||
this.activationDelegateReceiver_ = null;
|
||||
this.carrierPortalHandler_ = null;
|
||||
this.cellularMetadata_ = null;
|
||||
},
|
||||
|
||||
/** @private */
|
||||
@ -330,6 +334,24 @@ Polymer({
|
||||
this.currentTimeoutId_ = null;
|
||||
},
|
||||
|
||||
/** @private */
|
||||
onCarrierPortalLoaded_: function() {
|
||||
this.state_ = cellularSetup.State.WAITING_FOR_USER_PAYMENT;
|
||||
this.carrierPortalHandler_.onCarrierPortalStatusChange(
|
||||
chromeos.cellularSetup.mojom.CarrierPortalStatus
|
||||
.kPortalLoadedWithoutPaidUser);
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {!CustomEvent<boolean>} event
|
||||
* @private
|
||||
*/
|
||||
onCarrierPortalResult_: function(event) {
|
||||
const success = event.detail;
|
||||
this.state_ = success ? cellularSetup.State.ACTIVATION_SUCCESS :
|
||||
cellularSetup.State.ACTIVATION_FAILURE;
|
||||
},
|
||||
|
||||
/** @private */
|
||||
onBackwardNavRequested_: function() {
|
||||
// TODO(azeemarshad): Add back navigation.
|
||||
|
@ -2,13 +2,47 @@
|
||||
|
||||
<link rel="import" href="chrome://resources/html/i18n_behavior.html">
|
||||
<link rel="import" href="chrome://resources/cr_components/chromeos/cellular_setup/base_page.html">
|
||||
<link rel="import" href="chrome://resources/cr_components/chromeos/cellular_setup/webview_post_util.html">
|
||||
<link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html">
|
||||
<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html">
|
||||
<link rel="import" href="chrome://resources/polymer/v1_0/paper-spinner/paper-spinner-lite.html">
|
||||
|
||||
<dom-module id="provisioning-page">
|
||||
<template>
|
||||
<base-page title="[[i18n('provisioningPageTitle')]]">
|
||||
<div slot="page-body">
|
||||
<!-- TODO(azeemarshad): Add webview and error screen -->
|
||||
[[i18n('provisioningPageTitle')]]
|
||||
<style include="iron-flex cr-hidden-style">
|
||||
paper-spinner-lite {
|
||||
height: 200px;
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
#portalContainer {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#error-icon-container {
|
||||
background-image: -webkit-image-set(
|
||||
url(error_1x.png) 1x,
|
||||
url(error_2x.png) 2x);
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
<base-page title="[[getPageTitle_(
|
||||
showError, carrierName_, hasCarrierPortalLoaded_)]]"
|
||||
message="[[getPageMessage_(showError)]]">
|
||||
<div slot="page-body" class="layout horizontal center-center">
|
||||
<paper-spinner-lite active
|
||||
hidden$="[[!shouldShowSpinner_(
|
||||
showError, hasCarrierPortalLoaded_)]]">
|
||||
</paper-spinner-lite>
|
||||
<div id="portalContainer"
|
||||
hidden$="[[!shouldShowPortal_(
|
||||
showError, hasCarrierPortalLoaded_)]]">
|
||||
</div>
|
||||
<div id="error-icon-container" hidden$="[[!showError]]"></div>
|
||||
</div>
|
||||
</base-page>
|
||||
</template>
|
||||
|
@ -21,6 +21,189 @@ Polymer({
|
||||
showError: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
notify: true,
|
||||
},
|
||||
|
||||
/**
|
||||
* Metadata used to open carrier provisioning portal. Expected to start as
|
||||
* null, then change to a valid object.
|
||||
* @type {?chromeos.cellularSetup.mojom.CellularMetadata}
|
||||
*/
|
||||
cellularMetadata: {
|
||||
type: Object,
|
||||
value: null,
|
||||
observer: 'onCellularMetadataChanged_',
|
||||
},
|
||||
|
||||
/**
|
||||
* Whether the carrier portal has completed being loaded.
|
||||
* @private {boolean}
|
||||
*/
|
||||
hasCarrierPortalLoaded_: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
|
||||
/**
|
||||
* The last carrier name provided via |cellularMetadata|.
|
||||
* @private {string}
|
||||
*/
|
||||
carrierName_: {
|
||||
type: String,
|
||||
value: '',
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* @return {string}
|
||||
* @private
|
||||
*/
|
||||
getPageTitle_: function() {
|
||||
if (this.showError) {
|
||||
return this.i18n('provisioningPageErrorTitle', this.carrierName_);
|
||||
}
|
||||
if (this.hasCarrierPortalLoaded_) {
|
||||
return this.i18n('provisioningPageActiveTitle');
|
||||
}
|
||||
return this.i18n('provisioningPageLoadingTitle', this.carrierName_);
|
||||
},
|
||||
|
||||
/**
|
||||
* @return {string}
|
||||
* @private
|
||||
*/
|
||||
getPageMessage_: function() {
|
||||
if (this.showError) {
|
||||
return this.i18n('provisioningPageErrorMessage', this.carrierName_);
|
||||
}
|
||||
return '';
|
||||
},
|
||||
|
||||
/**
|
||||
* @return {boolean}
|
||||
* @private
|
||||
*/
|
||||
shouldShowSpinner_: function() {
|
||||
return !this.showError && !this.hasCarrierPortalLoaded_;
|
||||
},
|
||||
|
||||
/**
|
||||
* @return {boolean}
|
||||
* @private
|
||||
*/
|
||||
shouldShowPortal_: function() {
|
||||
return !this.showError && this.hasCarrierPortalLoaded_;
|
||||
},
|
||||
|
||||
/**
|
||||
* @return {?WebView}
|
||||
* @private
|
||||
*/
|
||||
getPortalWebview: function() {
|
||||
return /** @type {?WebView} */ (this.$$('webview'));
|
||||
},
|
||||
|
||||
/** @private */
|
||||
onCellularMetadataChanged_: function() {
|
||||
// Once |cellularMetadata| has been set, load the carrier provisioning page.
|
||||
if (this.cellularMetadata) {
|
||||
this.carrierName_ = this.cellularMetadata.carrier;
|
||||
this.loadPortal_();
|
||||
return;
|
||||
}
|
||||
|
||||
// If |cellularMetadata| is now null, the page should be reset so that a new
|
||||
// attempt can begin.
|
||||
this.resetPage_();
|
||||
},
|
||||
|
||||
/** @private */
|
||||
loadPortal_: function() {
|
||||
assert(!!this.cellularMetadata);
|
||||
assert(!this.getPortalWebview());
|
||||
|
||||
const portalWebview =
|
||||
/** @type {!WebView} */ (document.createElement('webview'));
|
||||
this.$.portalContainer.appendChild(portalWebview);
|
||||
|
||||
portalWebview.addEventListener(
|
||||
'loadabort', this.onPortalLoadAbort_.bind(this));
|
||||
portalWebview.addEventListener(
|
||||
'loadstop', this.onPortalLoadStop_.bind(this));
|
||||
window.addEventListener('message', this.onMessageReceived_.bind(this));
|
||||
|
||||
// Setting a <webview>'s "src" attribute triggers a GET request, but some
|
||||
// carrier portals require a POST request instead. If data is provided for a
|
||||
// POST request body, use a utility function to load the webview.
|
||||
if (this.cellularMetadata.paymentPostData) {
|
||||
webviewPost.util.postDeviceDataToWebview(
|
||||
portalWebview, this.cellularMetadata.paymentUrl.url,
|
||||
this.cellularMetadata.paymentPostData);
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, use a normal GET request by specifying the "src".
|
||||
portalWebview.src = this.cellularMetadata.paymentUrl.url;
|
||||
},
|
||||
|
||||
/** @private */
|
||||
resetPage_: function() {
|
||||
this.hasCarrierPortalLoaded_ = false;
|
||||
|
||||
// Remove the portal from the DOM if it exists.
|
||||
const portalWebview = this.getPortalWebview();
|
||||
if (portalWebview) {
|
||||
portalWebview.remove();
|
||||
}
|
||||
},
|
||||
|
||||
/** @private */
|
||||
onPortalLoadAbort_: function(event) {
|
||||
this.showError = true;
|
||||
},
|
||||
|
||||
/** @private */
|
||||
onPortalLoadStop_: function() {
|
||||
if (this.hasCarrierPortalLoaded_) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.hasCarrierPortalLoaded_ = true;
|
||||
this.fire('carrier-portal-loaded');
|
||||
|
||||
// When the portal loads, it expects to receive a message from this frame
|
||||
// alerting it that loading has completed successfully.
|
||||
this.getPortalWebview().contentWindow.postMessage(
|
||||
{msg: 'loadedInWebview'}, this.cellularMetadata.paymentUrl.url);
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {!Event} event
|
||||
* @private
|
||||
*/
|
||||
onMessageReceived_: function(event) {
|
||||
const messageType = /** @type {string} */ (event.data.type);
|
||||
const status = /** @type {string} */ (event.data.status);
|
||||
|
||||
// The <webview> requested information about this device. Reply by posting a
|
||||
// message back to it.
|
||||
if (messageType == 'requestDeviceInfoMsg') {
|
||||
this.getPortalWebview().contentWindow.postMessage(
|
||||
{
|
||||
carrier: this.cellularMetadata.carrier,
|
||||
MEID: this.cellularMetadata.meid,
|
||||
IMEI: this.cellularMetadata.imei,
|
||||
MDN: this.cellularMetadata.mdn
|
||||
},
|
||||
this.cellularMetadata.paymentUrl.url);
|
||||
return;
|
||||
}
|
||||
|
||||
// The <webview> provided an update on the status of the activation attempt.
|
||||
if (messageType == 'reportTransactionStatusMsg') {
|
||||
const success = status == 'ok';
|
||||
this.fire('on-carrier-portal-result', success);
|
||||
return;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
Reference in New Issue
Block a user