blob: 76a1aa5ac4be1d8abc43b5879cf5258bd0bc78da [file] [log] [blame]
Arman Uguray41cc6342013-03-29 16:34:39 -07001// Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "shill/pending_activation_store.h"
6
7#include "shill/key_file_store.h"
8#include "shill/logging.h"
9
10using base::FilePath;
11using std::string;
12
13namespace shill {
14
15const char PendingActivationStore::kIccidGroupId[] = "iccid_list";
16const char PendingActivationStore::kMeidGroupId[] = "meid_list";
17// We're keeping the old file name here for backwards compatibility.
18const char PendingActivationStore::kStorageFileName[] =
19 "activating_iccid_store.profile";
20
21PendingActivationStore::PendingActivationStore() {}
22
23PendingActivationStore::~PendingActivationStore() {
24 if (storage_.get())
25 storage_->Flush(); // Make certain that everything is persisted.
26}
27
28namespace {
29
30string StateToString(PendingActivationStore::State state) {
31 switch (state) {
32 case PendingActivationStore::kStateUnknown:
33 return "Unknown";
34 case PendingActivationStore::kStatePending:
35 return "Pending";
36 case PendingActivationStore::kStateActivated:
37 return "Activated";
Arman Uguray41cc6342013-03-29 16:34:39 -070038 default:
39 return "Invalid";
40 }
41}
42
43string FormattedIdentifier(PendingActivationStore::IdentifierType type,
44 const string &identifier) {
45 string label;
46 switch (type) {
47 case PendingActivationStore::kIdentifierICCID:
48 label = "ICCID";
49 break;
50 case PendingActivationStore::kIdentifierMEID:
51 label = "MEID";
52 break;
53 default:
54 NOTREACHED();
55 }
56 return "[" + label + "=" + identifier + "]";
57}
58
59} // namespace
60
61// static
62string PendingActivationStore::IdentifierTypeToGroupId(IdentifierType type) {
Alex Vakulenko8a532292014-06-16 17:18:44 -070063 switch (type) {
Arman Uguray41cc6342013-03-29 16:34:39 -070064 case kIdentifierICCID:
65 return kIccidGroupId;
66 case kIdentifierMEID:
67 return kMeidGroupId;
68 default:
69 SLOG(Cellular, 2) << "Incorrect identifier type: " << type;
70 return "";
71 }
72}
73
74bool PendingActivationStore::InitStorage(
75 GLib *glib,
76 const FilePath &storage_path) {
77 // Close the current file.
78 if (storage_.get()) {
79 storage_->Flush();
80 storage_.reset(); // KeyFileStore closes the file in its destructor.
81 }
82 if (!glib) {
83 LOG(ERROR) << "Null pointer passed for |glib|.";
84 return false;
85 }
86 if (storage_path.empty()) {
87 LOG(ERROR) << "Empty storage directory path provided.";
88 return false;
89 }
90 FilePath path = storage_path.Append(kStorageFileName);
91 scoped_ptr<KeyFileStore> storage(new KeyFileStore(glib));
92 storage->set_path(path);
93 bool already_exists = storage->IsNonEmpty();
94 if (!storage->Open()) {
95 LOG(ERROR) << "Failed to open file at '" << path.AsUTF8Unsafe() << "'";
96 if (already_exists)
97 storage->MarkAsCorrupted();
98 return false;
99 }
100 if (!already_exists)
101 storage->SetHeader("Identifiers pending cellular activation.");
102 storage_.reset(storage.release());
103 return true;
104}
105
106PendingActivationStore::State PendingActivationStore::GetActivationState(
107 IdentifierType type,
108 const string &identifier) const {
109 string formatted_identifier = FormattedIdentifier(type, identifier);
110 SLOG(Cellular, 2) << __func__ << ": " << formatted_identifier;
111 if (!storage_.get()) {
112 LOG(ERROR) << "Underlying storage not initialized.";
113 return kStateUnknown;
114 }
115 int state = 0;
116 if (!storage_->GetInt(IdentifierTypeToGroupId(type), identifier, &state)) {
117 SLOG(Cellular, 2) << "No entry exists for " << formatted_identifier;
118 return kStateUnknown;
119 }
120 if (state <= 0 || state >= kStateMax) {
121 SLOG(Cellular, 2) << "State value read for " << formatted_identifier
122 << " is invalid.";
123 return kStateUnknown;
124 }
125 return static_cast<State>(state);
126}
127
128bool PendingActivationStore::SetActivationState(
129 IdentifierType type,
130 const string &identifier,
131 State state) {
132 SLOG(Cellular, 2) << __func__ << ": State=" << StateToString(state) << ", "
133 << FormattedIdentifier(type, identifier);
134 if (!storage_.get()) {
135 LOG(ERROR) << "Underlying storage not initialized.";
136 return false;
137 }
138 if (state == kStateUnknown) {
139 SLOG(Cellular, 2) << "kStateUnknown cannot be used as a value.";
140 return false;
141 }
142 if (state < 0 || state >= kStateMax) {
143 SLOG(Cellular, 2) << "Cannot set state to \"" << StateToString(state)
144 << "\"";
145 return false;
146 }
147 if (!storage_->SetInt(
148 IdentifierTypeToGroupId(type), identifier, static_cast<int>(state))) {
149 SLOG(Cellular, 2) << "Failed to store the given identifier and state "
150 << "values.";
151 return false;
152 }
153 return storage_->Flush();
154}
155
156bool PendingActivationStore::RemoveEntry(IdentifierType type,
157 const std::string &identifier) {
158 SLOG(Cellular, 2) << __func__ << ": "
159 << FormattedIdentifier(type, identifier);
160 if (!storage_.get()) {
161 LOG(ERROR) << "Underlying storage not initialized.";
162 return false;
163 }
164 if (!storage_->DeleteKey(IdentifierTypeToGroupId(type), identifier)) {
165 SLOG(Cellular, 2) << "Failed to remove the given identifier.";
166 return false;
167 }
168 return storage_->Flush();
169}
170
171} // namespace shill