blob: 07a2f86a02b75b61e0f1bcce5838e6a9910ad9ea [file] [log] [blame]
// Copyright 2018 The Chromium OS 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 "shill/pending_activation_store.h"
#include <utility>
#include "shill/logging.h"
#include "shill/store_interface.h"
using base::FilePath;
using std::string;
namespace shill {
namespace Logging {
static auto kModuleLogScope = ScopeLogger::kCellular;
static string ObjectID(const PendingActivationStore* p) {
return "(pending_activation_store)";
}
}
const char PendingActivationStore::kIccidGroupId[] = "iccid_list";
const char PendingActivationStore::kMeidGroupId[] = "meid_list";
// We're keeping the old file name here for backwards compatibility.
const char PendingActivationStore::kStorageFileName[] =
"activating_iccid_store.profile";
PendingActivationStore::PendingActivationStore() {}
PendingActivationStore::~PendingActivationStore() {
if (storage_)
storage_->Flush(); // Make certain that everything is persisted.
}
namespace {
string StateToString(PendingActivationStore::State state) {
switch (state) {
case PendingActivationStore::kStateUnknown:
return "Unknown";
case PendingActivationStore::kStatePending:
return "Pending";
case PendingActivationStore::kStateActivated:
return "Activated";
default:
return "Invalid";
}
}
string FormattedIdentifier(PendingActivationStore::IdentifierType type,
const string& identifier) {
string label;
switch (type) {
case PendingActivationStore::kIdentifierICCID:
label = "ICCID";
break;
case PendingActivationStore::kIdentifierMEID:
label = "MEID";
break;
default:
NOTREACHED();
}
return "[" + label + "=" + identifier + "]";
}
} // namespace
// static
string PendingActivationStore::IdentifierTypeToGroupId(IdentifierType type) {
switch (type) {
case kIdentifierICCID:
return kIccidGroupId;
case kIdentifierMEID:
return kMeidGroupId;
default:
SLOG(Cellular, nullptr, 2) << "Incorrect identifier type: " << type;
return "";
}
}
bool PendingActivationStore::InitStorage(const FilePath& storage_path) {
// Close the current file.
if (storage_) {
storage_->Flush();
storage_.reset(); // KeyFileStore closes the file in its destructor.
}
if (storage_path.empty()) {
LOG(ERROR) << "Empty storage directory path provided.";
return false;
}
FilePath path = storage_path.Append(kStorageFileName);
std::unique_ptr<StoreInterface> storage = CreateStore(path);
bool already_exists = !storage->IsEmpty();
if (!storage->Open()) {
LOG(ERROR) << "Failed to open file at '" << path.AsUTF8Unsafe() << "'";
if (already_exists)
storage->MarkAsCorrupted();
return false;
}
if (!already_exists)
storage->SetHeader("Identifiers pending cellular activation.");
storage_ = std::move(storage);
return true;
}
PendingActivationStore::State PendingActivationStore::GetActivationState(
IdentifierType type,
const string& identifier) const {
string formatted_identifier = FormattedIdentifier(type, identifier);
SLOG(this, 2) << __func__ << ": " << formatted_identifier;
if (!storage_) {
LOG(ERROR) << "Underlying storage not initialized.";
return kStateUnknown;
}
int state = 0;
if (!storage_->GetInt(IdentifierTypeToGroupId(type), identifier, &state)) {
SLOG(this, 2) << "No entry exists for " << formatted_identifier;
return kStateUnknown;
}
if (state <= 0 || state >= kStateMax) {
SLOG(this, 2) << "State value read for " << formatted_identifier
<< " is invalid.";
return kStateUnknown;
}
return static_cast<State>(state);
}
bool PendingActivationStore::SetActivationState(
IdentifierType type,
const string& identifier,
State state) {
SLOG(this, 2) << __func__ << ": State=" << StateToString(state) << ", "
<< FormattedIdentifier(type, identifier);
if (!storage_) {
LOG(ERROR) << "Underlying storage not initialized.";
return false;
}
if (state == kStateUnknown) {
SLOG(this, 2) << "kStateUnknown cannot be used as a value.";
return false;
}
if (state < 0 || state >= kStateMax) {
SLOG(this, 2) << "Cannot set state to \"" << StateToString(state)
<< "\"";
return false;
}
if (!storage_->SetInt(
IdentifierTypeToGroupId(type), identifier, static_cast<int>(state))) {
SLOG(this, 2) << "Failed to store the given identifier and state "
<< "values.";
return false;
}
return storage_->Flush();
}
bool PendingActivationStore::RemoveEntry(IdentifierType type,
const std::string& identifier) {
SLOG(this, 2) << __func__ << ": "
<< FormattedIdentifier(type, identifier);
if (!storage_) {
LOG(ERROR) << "Underlying storage not initialized.";
return false;
}
if (!storage_->DeleteKey(IdentifierTypeToGroupId(type), identifier)) {
SLOG(this, 2) << "Failed to remove the given identifier.";
return false;
}
return storage_->Flush();
}
} // namespace shill