Commit 2c44c780 authored by Kyle Horimoto's avatar Kyle Horimoto Committed by Commit Bot

[CrOS Celluar] Implement ActivationDelegate in setup flow UI.

ActivationDelegate is the primary interface from cellular_setup.mojom to
be implemented in JavaScript. This class deals with sending and
receiving status update messages to the service.

This CL implements this delegate and deals with routing between the
first page (SIM detect) and either the second page (provisioning) or the
third page (final) depending on the response received.

Note that the second page (provisioning) still isn't implemented as part
of this CL; this functionality is part of a follow-up CL.

Bug: 968858
Change-Id: I67d86647237dc47a1c4660bf7160e5e993f45f13
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1721042
Commit-Queue: Kyle Horimoto <khorimoto@chromium.org>
Commit-Queue: Ryan Hansberry <hansberry@chromium.org>
Reviewed-by: default avatarRyan Hansberry <hansberry@chromium.org>
Auto-Submit: Kyle Horimoto <khorimoto@chromium.org>
Cr-Commit-Position: refs/heads/master@{#683384}
parent ad8b22bd
......@@ -52,6 +52,7 @@ js_library("cellular_setup") {
":mojo_interface_provider",
":provisioning_page",
":sim_detect_page",
"//chromeos/services/cellular_setup/public/mojom:mojom_js_library_for_compile",
"//ui/webui/resources/js:i18n_behavior",
]
}
......
......@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
cr.define('cellular_setup', function() {
cr.define('cellularSetup', function() {
/** @enum{string} */
const PageName = {
SIM_DETECT: 'sim-detect-page',
......@@ -10,7 +10,53 @@ cr.define('cellular_setup', function() {
FINAL: 'final-page',
};
return {PageName: PageName};
/** @enum{string} */
const State = {
IDLE: 'idle',
STARTING_ACTIVATION: 'starting-activation',
WAITING_FOR_ACTIVATION_TO_START: 'waiting-for-activation-to-start',
TIMEOUT_START_ACTIVATION: 'timeout-start-activation',
WAITING_FOR_PORTAL_TO_LOAD: 'waiting-for-portal-to-load',
TIMEOUT_PORTAL_LOAD: 'timeout-portal-load',
WAITING_FOR_USER_PAYMENT: 'waiting-for-user-payment',
WAITING_FOR_ACTIVATION_TO_FINISH: 'waiting-for-activation-to-finish',
TIMEOUT_FINISH_ACTIVATION: 'timeout-finish-activation',
ACTIVATION_SUCCESS: 'activation-success',
ALREADY_ACTIVATED: 'already-activated',
ACTIVATION_FAILURE: 'activation-failure',
};
/**
* @param {!cellularSetup.State} state
* @return {?number} The time delta, in ms, for the timeout corresponding to
* |state|. If no timeout is applicable for this state, null is returned.
*/
function getTimeoutMsForState(state) {
// In some cases, starting activation may require power-cycling the device's
// modem, a process that can take several seconds.
if (state === State.STARTING_ACTIVATION) {
return 10000; // 10 seconds.
}
// The portal is a website served by the mobile carrier.
if (state === State.WAITING_FOR_PORTAL_TO_LOAD) {
return 5000; // 5 seconds.
}
// Finishing activation only requires sending a D-Bus message to Shill.
if (state === State.WAITING_FOR_ACTIVATION_TO_FINISH) {
return 1000; // 1 second.
}
// No other states require timeouts.
return null;
}
return {
PageName: PageName,
State: State,
getTimeoutMsForState: getTimeoutMsForState
};
});
/**
......@@ -24,13 +70,19 @@ Polymer({
behaviors: [I18nBehavior],
properties: {
/** @private {!cellularSetup.State} */
state_: {
type: String,
value: cellularSetup.State.IDLE,
},
/**
* Element name of the current selected sub-page.
* @private {!cellular_setup.PageName}
* @private {!cellularSetup.PageName}
*/
selectedPageName_: {
type: String,
value: cellular_setup.PageName.SIM_DETECT,
value: cellularSetup.PageName.SIM_DETECT,
notify: true,
},
......@@ -66,6 +118,12 @@ Polymer({
showCancelButton_: {type: Boolean, value: false}
},
observers: [
'updateShowError_(state_)',
'updateSelectedPage_(state_)',
'handleStateChange_(state_)',
],
listeners: {
'backward-nav-requested': 'onBackwardNavRequested_',
'retry-requested': 'onRetryRequested_',
......@@ -78,12 +136,187 @@ Polymer({
*/
mojoInterfaceProvider_: null,
/**
* Delegate responsible for routing activation started/finished events.
* @private {?chromeos.cellularSetup.mojom.ActivationDelegateReceiver}
*/
activationDelegateReceiver_: null,
/**
* The timeout ID corresponding to a timeout for the current state. If no
* timeout is active, this value is null.
* @private {?number}
*/
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,
/** @override */
created: function() {
this.mojoInterfaceProvider_ =
cellular_setup.MojoInterfaceProviderImpl.getInstance();
},
/** @override */
ready: function() {
this.state_ = cellularSetup.State.STARTING_ACTIVATION;
},
/**
* Overrides chromeos.cellularSetup.mojom.ActivationDelegateInterface.
* @param {!chromeos.cellularSetup.mojom.CellularMetadata} metadata
* @private
*/
onActivationStarted(metadata) {
this.clearTimer_();
this.cellularMetadata_ = metadata;
this.state_ = cellularSetup.State.WAITING_FOR_PORTAL_TO_LOAD;
},
/**
* Overrides chromeos.cellularSetup.mojom.ActivationDelegateInterface.
* @param {!chromeos.cellularSetup.mojom.ActivationResult} result
* @private
*/
onActivationFinished(result) {
this.closeActivationConnection_();
const ActivationResult = chromeos.cellularSetup.mojom.ActivationResult;
switch (result) {
case ActivationResult.kSuccessfullyStartedActivation:
this.state_ = cellularSetup.State.ALREADY_ACTIVATED;
break;
case ActivationResult.kAlreadyActivated:
this.state_ = cellularSetup.State.ACTIVATION_SUCCESS;
break;
case ActivationResult.kFailedToActivate:
this.state_ = cellularSetup.State.ACTIVATION_FAILURE;
break;
default:
assertNotReached();
}
},
/** @private */
updateShowError_: function() {
switch (this.state_) {
case cellularSetup.State.TIMEOUT_START_ACTIVATION:
case cellularSetup.State.TIMEOUT_PORTAL_LOAD:
case cellularSetup.State.TIMEOUT_FINISH_ACTIVATION:
case cellularSetup.State.ACTIVATION_FAILURE:
this.showError_ = true;
return;
default:
this.showError_ = false;
return;
}
},
/** @private */
updateSelectedPage_: function() {
switch (this.state_) {
case cellularSetup.State.IDLE:
case cellularSetup.State.STARTING_ACTIVATION:
case cellularSetup.State.WAITING_FOR_ACTIVATION_TO_START:
case cellularSetup.State.TIMEOUT_START_ACTIVATION:
this.selectedPageName_ = cellularSetup.PageName.SIM_DETECT;
return;
case cellularSetup.State.WAITING_FOR_PORTAL_TO_LOAD:
case cellularSetup.State.TIMEOUT_PORTAL_LOAD:
case cellularSetup.State.WAITING_FOR_USER_PAYMENT:
this.selectedPageName_ = cellularSetup.PageName.PROVISIONING;
return;
case cellularSetup.State.WAITING_FOR_ACTIVATION_TO_FINISH:
case cellularSetup.State.TIMEOUT_FINISH_ACTIVATION:
case cellularSetup.State.ACTIVATION_SUCCESS:
case cellularSetup.State.ALREADY_ACTIVATED:
case cellularSetup.State.ACTIVATION_FAILURE:
this.selectedPageName_ = cellularSetup.PageName.FINAL;
return;
default:
assertNotReached();
}
},
/** @private */
handleStateChange_: function() {
// Since the state has changed, the previous state did not time out, so
// clear any active timeout.
this.clearTimer_();
// If the new state has an associated timeout, set it.
const timeoutMs = cellularSetup.getTimeoutMsForState(this.state_);
if (timeoutMs !== null) {
this.currentTimeoutId_ =
setTimeout(this.onTimeout_.bind(this), timeoutMs);
}
if (this.state_ === cellularSetup.State.STARTING_ACTIVATION) {
this.startActivation_();
return;
}
},
/** @private */
onTimeout_: function() {
// The activation attempt failed, so close the connection to the service.
this.closeActivationConnection_();
switch (this.state_) {
case cellularSetup.State.STARTING_ACTIVATION:
this.state_ = cellularSetup.State.TIMEOUT_START_ACTIVATION;
return;
case cellularSetup.State.WAITING_FOR_PORTAL_TO_LOAD:
this.state_ = cellularSetup.State.TIMEOUT_PORTAL_LOAD;
return;
case cellularSetup.State.WAITING_FOR_ACTIVATION_TO_FINISH:
this.state_ = cellularSetup.State.TIMEOUT_FINISH_ACTIVATION;
return;
default:
// Only the above states are expected to time out.
assertNotReached();
}
},
/** @private */
startActivation_: function() {
assert(!this.activationDelegateReceiver_);
this.activationDelegateReceiver_ =
new chromeos.cellularSetup.mojom.ActivationDelegateReceiver(
/**
* @type {!chromeos.cellularSetup.mojom.ActivationDelegateInterface}
*/
(this));
this.mojoInterfaceProvider_.getMojoServiceRemote()
.startActivation(
this.activationDelegateReceiver_.$.bindNewPipeAndPassRemote())
.then((handler) => {
this.carrierPortalHandler_ = handler;
});
},
/** @private */
closeActivationConnection_: function() {
assert(!!this.activationDelegateReceiver_);
this.activationDelegateReceiver_.$.close();
this.activationDelegateReceiver_ = null;
this.carrierPortalHandler_ = null;
},
/** @private */
clearTimer_: function() {
if (this.currentTimeoutId_) {
clearTimeout(this.currentTimeoutId_);
}
this.currentTimeoutId_ = null;
},
/** @private */
onBackwardNavRequested_: function() {
// TODO(azeemarshad): Add back navigation.
......
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