Commit 260e2831 authored by Kyle Horimoto's avatar Kyle Horimoto Committed by Commit Bot

[CrOS Cellular] Add OtaActivator class.

This CL:
(1) Adds a base OtaActivator class along with an OtaActivatorImpl
    implementation and a FakeOtaActivator for tests.
(2) Adds a test for OtaActivatorImpl.
(3) Updates some definitions from cellular_setup.mojom; specifically,
    this CL changes the ActivationResult enum.
(4) Updates cellular_setup_service_unittest.cc to reflect the changes in
    part 3 above.

Bug: 961084
Change-Id: I2d4bd9cd454014106f120144e28238f07b32a318
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1604213Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarAzeem Arshad <azeemarshad@chromium.org>
Reviewed-by: default avatarSteven Bennetts <stevenjb@chromium.org>
Commit-Queue: Kyle Horimoto <khorimoto@chromium.org>
Auto-Submit: Kyle Horimoto <khorimoto@chromium.org>
Cr-Commit-Position: refs/heads/master@{#662907}
parent 12371733
...@@ -12,27 +12,51 @@ static_library("cellular_setup") { ...@@ -12,27 +12,51 @@ static_library("cellular_setup") {
"cellular_setup_impl.h", "cellular_setup_impl.h",
"cellular_setup_service.cc", "cellular_setup_service.cc",
"cellular_setup_service.h", "cellular_setup_service.h",
"ota_activator.cc",
"ota_activator.h",
"ota_activator_impl.cc",
"ota_activator_impl.h",
] ]
deps = [ deps = [
"//base", "//base",
"//chromeos/dbus/shill",
"//chromeos/network",
"//chromeos/services/cellular_setup/public/mojom", "//chromeos/services/cellular_setup/public/mojom",
"//dbus",
"//services/service_manager/public/cpp", "//services/service_manager/public/cpp",
"//services/service_manager/public/mojom", "//services/service_manager/public/mojom",
] ]
} }
static_library("test_support") {
testonly = true
sources = [
"fake_ota_activator.cc",
"fake_ota_activator.h",
]
deps = [
":cellular_setup",
"//base",
"//chromeos/services/cellular_setup/public/cpp:test_support",
]
}
source_set("unit_tests") { source_set("unit_tests") {
testonly = true testonly = true
sources = [ sources = [
"cellular_setup_service_unittest.cc", "cellular_setup_service_unittest.cc",
"ota_activator_impl_unittest.cc",
] ]
deps = [ deps = [
":cellular_setup", ":cellular_setup",
"//base", "//base",
"//base/test:test_support", "//base/test:test_support",
"//chromeos/network:test_support",
"//chromeos/services/cellular_setup/public/cpp:test_support", "//chromeos/services/cellular_setup/public/cpp:test_support",
"//services/service_manager/public/cpp/test:test_support", "//services/service_manager/public/cpp/test:test_support",
"//testing/gmock", "//testing/gmock",
......
include_rules = [ include_rules = [
"+dbus/object_path.h",
"+mojo/public/cpp/bindings", "+mojo/public/cpp/bindings",
"+services/service_manager/public", "+services/service_manager/public",
] ]
...@@ -31,6 +31,7 @@ using CarrierPortalHandlerPair = ...@@ -31,6 +31,7 @@ using CarrierPortalHandlerPair =
const char kTestCellularNetworkGuid[] = "testCellularNetworkGuid"; const char kTestCellularNetworkGuid[] = "testCellularNetworkGuid";
const char kTestPaymentUrl[] = "testPaymentUrl"; const char kTestPaymentUrl[] = "testPaymentUrl";
const char kTestPaymentPostData[] = "testPaymentPostData";
const char kTestCarrier[] = "testCarrier"; const char kTestCarrier[] = "testCarrier";
const char kTestMeid[] = "testMeid"; const char kTestMeid[] = "testMeid";
const char kTestImei[] = "testImei"; const char kTestImei[] = "testImei";
...@@ -130,7 +131,8 @@ class CellularSetupServiceTest : public testing::Test { ...@@ -130,7 +131,8 @@ class CellularSetupServiceTest : public testing::Test {
size_t num_elements_before_call = cellular_metadata_list.size(); size_t num_elements_before_call = cellular_metadata_list.size();
GetLastActivationDelegate()->OnActivationStarted( GetLastActivationDelegate()->OnActivationStarted(
mojom::CellularMetadata::New(GURL(kTestPaymentUrl), kTestCarrier, mojom::CellularMetadata::New(GURL(kTestPaymentUrl),
kTestPaymentPostData, kTestCarrier,
kTestMeid, kTestImei, kTestMdn)); kTestMeid, kTestImei, kTestMdn));
GetLastActivationDelegate().FlushForTesting(); GetLastActivationDelegate().FlushForTesting();
...@@ -222,7 +224,8 @@ TEST_F(CellularSetupServiceTest, StartActivation_Success) { ...@@ -222,7 +224,8 @@ TEST_F(CellularSetupServiceTest, StartActivation_Success) {
SendCarrierPortalStatusUpdate( SendCarrierPortalStatusUpdate(
mojom::CarrierPortalStatus::kPortalLoadedAndUserCompletedPayment, &pair); mojom::CarrierPortalStatus::kPortalLoadedAndUserCompletedPayment, &pair);
NotifyLastDelegateThatActivationFinished(mojom::ActivationResult::kSuccess, NotifyLastDelegateThatActivationFinished(
mojom::ActivationResult::kSuccessfullyStartedActivation,
fake_activation_delegate.get()); fake_activation_delegate.get());
} }
...@@ -259,23 +262,6 @@ TEST_F(CellularSetupServiceTest, StartActivation_ErrorDuringPayment) { ...@@ -259,23 +262,6 @@ TEST_F(CellularSetupServiceTest, StartActivation_ErrorDuringPayment) {
fake_activation_delegate.get()); fake_activation_delegate.get());
} }
TEST_F(CellularSetupServiceTest, StartActivation_TimedOut) {
auto fake_activation_delegate = std::make_unique<FakeActivationDelegate>();
CarrierPortalHandlerPair pair = CallStartActivation(
kTestCellularNetworkGuid, fake_activation_delegate.get());
NotifyLastDelegateThatActivationStarted(fake_activation_delegate.get());
SendCarrierPortalStatusUpdate(
mojom::CarrierPortalStatus::kPortalLoadedWithoutPaidUser, &pair);
SendCarrierPortalStatusUpdate(
mojom::CarrierPortalStatus::kPortalLoadedAndUserCompletedPayment, &pair);
NotifyLastDelegateThatActivationFinished(
mojom::ActivationResult::kTimedOutActivating,
fake_activation_delegate.get());
}
} // namespace cellular_setup } // namespace cellular_setup
} // namespace chromeos } // 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.
#include "chromeos/services/cellular_setup/fake_ota_activator.h"
#include <utility>
namespace chromeos {
namespace cellular_setup {
FakeOtaActivator::FakeOtaActivator(base::OnceClosure on_finished_callback)
: OtaActivator(std::move(on_finished_callback)) {}
FakeOtaActivator::~FakeOtaActivator() = default;
} // namespace cellular_setup
} // namespace chromeos
#endif // CHROMEOS_SERVICES_CELLULAR_SETUP_FAKE_OTA_ACTIVATOR_H_
// 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 CHROMEOS_SERVICES_CELLULAR_SETUP_FAKE_OTA_ACTIVATOR_H_
#define CHROMEOS_SERVICES_CELLULAR_SETUP_FAKE_OTA_ACTIVATOR_H_
#include "base/callback_forward.h"
#include "base/macros.h"
#include "chromeos/services/cellular_setup/ota_activator.h"
#include "chromeos/services/cellular_setup/public/cpp/fake_carrier_portal_handler.h"
namespace chromeos {
namespace cellular_setup {
// Test OtaActivator implementation.
class FakeOtaActivator : public OtaActivator, public FakeCarrierPortalHandler {
public:
explicit FakeOtaActivator(base::OnceClosure on_finished_callback);
~FakeOtaActivator();
using OtaActivator::InvokeOnFinishedCallback;
private:
DISALLOW_COPY_AND_ASSIGN(FakeOtaActivator);
};
} // namespace cellular_setup
} // namespace chromeos
#endif // CHROMEOS_SERVICES_CELLULAR_SETUP_FAKE_OTA_ACTIVATOR_H_
// 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 "chromeos/services/cellular_setup/ota_activator.h"
#include <utility>
namespace chromeos {
namespace cellular_setup {
OtaActivator::OtaActivator(base::OnceClosure on_finished_callback)
: on_finished_callback_(std::move(on_finished_callback)) {}
OtaActivator::~OtaActivator() = default;
mojom::CarrierPortalHandlerPtr OtaActivator::GenerateInterfacePtr() {
mojom::CarrierPortalHandlerPtr interface_ptr;
bindings_.AddBinding(this, mojo::MakeRequest(&interface_ptr));
return interface_ptr;
}
void OtaActivator::InvokeOnFinishedCallback() {
DCHECK(on_finished_callback_);
std::move(on_finished_callback_).Run();
}
} // namespace cellular_setup
} // 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 CHROMEOS_SERVICES_CELLULAR_SETUP_OTA_ACTIVATOR_H_
#define CHROMEOS_SERVICES_CELLULAR_SETUP_OTA_ACTIVATOR_H_
#include "base/callback.h"
#include "base/macros.h"
#include "chromeos/services/cellular_setup/public/mojom/cellular_setup.mojom.h"
#include "mojo/public/cpp/bindings/binding_set.h"
namespace chromeos {
namespace cellular_setup {
// Activates a cellular SIM using the OTA mechanism. This class makes a single
// attempt at activation, then fires a callback on completion, regardless of
// success or failure. An OtaActivator object can only be used for one
// attempt; to perform a new activation attempt, use a separate OtaActivator
// instance.
class OtaActivator : public mojom::CarrierPortalHandler {
public:
~OtaActivator() override;
mojom::CarrierPortalHandlerPtr GenerateInterfacePtr();
protected:
explicit OtaActivator(base::OnceClosure on_finished_callback);
void InvokeOnFinishedCallback();
base::OnceClosure on_finished_callback_;
mojo::BindingSet<mojom::CarrierPortalHandler> bindings_;
DISALLOW_COPY_AND_ASSIGN(OtaActivator);
};
} // namespace cellular_setup
} // namespace chromeos
#endif // CHROMEOS_SERVICES_CELLULAR_SETUP_OTA_ACTIVATOR_H_
This diff is collapsed.
// 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 CHROMEOS_SERVICES_CELLULAR_SETUP_OTA_ACTIVATOR_IMPL_H_
#define CHROMEOS_SERVICES_CELLULAR_SETUP_OTA_ACTIVATOR_IMPL_H_
#include <memory>
#include <ostream>
#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "chromeos/network/network_state_handler_observer.h"
#include "chromeos/services/cellular_setup/ota_activator.h"
#include "chromeos/services/cellular_setup/public/mojom/cellular_setup.mojom.h"
namespace base {
class DictionaryValue;
} // namespace base
namespace chromeos {
class NetworkActivationHandler;
class NetworkConnectionHandler;
class NetworkState;
class NetworkStateHandler;
namespace cellular_setup {
// Concrete OtaActivator implementation. This class activates a SIM using the
// following steps:
// (1) Find a valid SIM in the device. In this context, a SIM is only valid if
// it is present in the machine and has an associated carrier, MEID, IMEI,
// and MDN. If a valid SIM is not present, this class reboots the modem to
// see if the SIM can be detected after a restart.
// (2) Ensure an eligible cellular connection is active. In this context, a
// cellular network is only eligible for activation if it has associated
// payment metadata which can be provided to the carrier portal. If such
// a network is available, this class connects to that network.
// (3) Wait for carrier payment to complete. This class impelments
// CarrierPortalHandler to receive updates about the payment status.
// (4) Complete activation via Shill.
class OtaActivatorImpl : public OtaActivator,
public NetworkStateHandlerObserver {
public:
class Factory {
public:
static std::unique_ptr<OtaActivator> Create(
mojom::ActivationDelegatePtr activation_delegate,
base::OnceClosure on_finished_callback,
NetworkStateHandler* network_state_handler,
NetworkConnectionHandler* network_connection_handler,
NetworkActivationHandler* network_activation_handler);
static void SetFactoryForTesting(Factory* test_factory);
virtual ~Factory();
virtual std::unique_ptr<OtaActivator> BuildInstance(
mojom::ActivationDelegatePtr activation_delegate,
base::OnceClosure on_finished_callback,
NetworkStateHandler* network_state_handler,
NetworkConnectionHandler* network_connection_handler,
NetworkActivationHandler* network_activation_handler) = 0;
};
~OtaActivatorImpl() override;
private:
friend class CellularSetupOtaActivatorImplTest;
enum class State {
kNotYetStarted,
kWaitingForValidSimToBecomePresent,
kWaitingForCellularConnection,
kWaitingForCellularPayment,
kWaitingForActivation,
kFinished
};
friend std::ostream& operator<<(std::ostream& stream, const State& state);
OtaActivatorImpl(mojom::ActivationDelegatePtr activation_delegate,
base::OnceClosure on_finished_callback,
NetworkStateHandler* network_state_handler,
NetworkConnectionHandler* network_connection_handler,
NetworkActivationHandler* network_activation_handler);
// mojom::CarrierPortalHandler:
void OnCarrierPortalStatusChange(mojom::CarrierPortalStatus status) override;
// NetworkStateHandlerObserver:
void NetworkListChanged() override;
void DeviceListChanged() override;
void NetworkPropertiesUpdated(const NetworkState* network) override;
void DevicePropertiesUpdated(const DeviceState* device) override;
void OnShuttingDown() override;
const DeviceState* GetCellularDeviceState() const;
const NetworkState* GetCellularNetworkState() const;
void ChangeStateAndAttemptNextStep(State state);
void AttemptNextActivationStep();
void FinishActivationAttempt(mojom::ActivationResult activation_result);
void AttemptToDiscoverSim();
void AttemptConnectionToCellularNetwork();
void AttemptToSendMetadataToDelegate();
void AttemptToCompleteActivation();
void OnCompleteActivationError(
const std::string& error_name,
std::unique_ptr<base::DictionaryValue> error_data);
void FlushForTesting();
mojom::ActivationDelegatePtr activation_delegate_;
NetworkStateHandler* network_state_handler_;
NetworkConnectionHandler* network_connection_handler_;
NetworkActivationHandler* network_activation_handler_;
State state_ = State::kNotYetStarted;
base::Optional<mojom::CarrierPortalStatus> last_carrier_portal_status_;
bool has_sent_metadata_ = false;
bool has_called_complete_activation_ = false;
base::WeakPtrFactory<OtaActivatorImpl> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(OtaActivatorImpl);
};
std::ostream& operator<<(std::ostream& stream,
const OtaActivatorImpl::State& state);
} // namespace cellular_setup
} // namespace chromeos
#endif // CHROMEOS_SERVICES_CELLULAR_SETUP_OTA_ACTIVATOR_IMPL_H_
...@@ -18,6 +18,10 @@ mojom::ActivationDelegatePtr FakeActivationDelegate::GenerateInterfacePtr() { ...@@ -18,6 +18,10 @@ mojom::ActivationDelegatePtr FakeActivationDelegate::GenerateInterfacePtr() {
return interface_ptr; return interface_ptr;
} }
void FakeActivationDelegate::DisconnectBindings() {
bindings_.CloseAllBindings();
}
void FakeActivationDelegate::OnActivationStarted( void FakeActivationDelegate::OnActivationStarted(
mojom::CellularMetadataPtr cellular_metadata) { mojom::CellularMetadataPtr cellular_metadata) {
cellular_metadata_list_.push_back(std::move(cellular_metadata)); cellular_metadata_list_.push_back(std::move(cellular_metadata));
......
...@@ -22,6 +22,7 @@ class FakeActivationDelegate : public mojom::ActivationDelegate { ...@@ -22,6 +22,7 @@ class FakeActivationDelegate : public mojom::ActivationDelegate {
~FakeActivationDelegate() override; ~FakeActivationDelegate() override;
mojom::ActivationDelegatePtr GenerateInterfacePtr(); mojom::ActivationDelegatePtr GenerateInterfacePtr();
void DisconnectBindings();
const std::vector<mojom::CellularMetadataPtr>& cellular_metadata_list() const std::vector<mojom::CellularMetadataPtr>& cellular_metadata_list()
const { const {
......
...@@ -25,9 +25,16 @@ enum CarrierPortalStatus { ...@@ -25,9 +25,16 @@ enum CarrierPortalStatus {
// Potential results for an activation attempt. // Potential results for an activation attempt.
enum ActivationResult { enum ActivationResult {
kSuccess, // Activation was initiated successfully by the attempt. Note that the device
// may not be fully activated by the time this result occurs since the process
// completes in the background.
kSuccessfullyStartedActivation,
// Activation was unnecessary because the SIM is already activated.
kAlreadyActivated,
// Activation failed (e.g., due to a failure within Shill).
kFailedToActivate, kFailedToActivate,
kTimedOutActivating
}; };
// Metadata corresponding to a cellular activation request which allows the // Metadata corresponding to a cellular activation request which allows the
...@@ -37,6 +44,9 @@ struct CellularMetadata { ...@@ -37,6 +44,9 @@ struct CellularMetadata {
// carrier-based payment flow. // carrier-based payment flow.
url.mojom.Url payment_url; url.mojom.Url payment_url;
// Data to be passed to the payment portal to verify the SIM.
string payment_post_data;
// Human-readable name of the carrier associated with the SIM card. // Human-readable name of the carrier associated with the SIM card.
string carrier; string carrier;
...@@ -60,11 +70,11 @@ interface CarrierPortalHandler { ...@@ -60,11 +70,11 @@ interface CarrierPortalHandler {
// Delegate which is notified when activation starts and finishes. Used by the // Delegate which is notified when activation starts and finishes. Used by the
// service to notify the UI of the state of the activation flow. // service to notify the UI of the state of the activation flow.
interface ActivationDelegate { interface ActivationDelegate {
// Called when activation has started; provides relevant metadata for // Called when the flow has started; only called when the device is eligible
// activation. // for activation (i.e., has a valid, unactivated SIM).
OnActivationStarted(CellularMetadata metadata); OnActivationStarted(CellularMetadata metadata);
// Called when activation finishes, regardless of success or failure. // Called when the flow has finished, regardless of success or failure.
OnActivationFinished(ActivationResult result); OnActivationFinished(ActivationResult result);
}; };
......
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