blob: 97c8e175b1180c29a7dcaff9be05edb0d9e86395 [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";
38 case PendingActivationStore::kStatePendingTimeout:
39 return "PendingTimeout";
40 default:
41 return "Invalid";
42 }
43}
44
45string FormattedIdentifier(PendingActivationStore::IdentifierType type,
46 const string &identifier) {
47 string label;
48 switch (type) {
49 case PendingActivationStore::kIdentifierICCID:
50 label = "ICCID";
51 break;
52 case PendingActivationStore::kIdentifierMEID:
53 label = "MEID";
54 break;
55 default:
56 NOTREACHED();
57 }
58 return "[" + label + "=" + identifier + "]";
59}
60
61} // namespace
62
63// static
64string PendingActivationStore::IdentifierTypeToGroupId(IdentifierType type) {
65 switch(type) {
66 case kIdentifierICCID:
67 return kIccidGroupId;
68 case kIdentifierMEID:
69 return kMeidGroupId;
70 default:
71 SLOG(Cellular, 2) << "Incorrect identifier type: " << type;
72 return "";
73 }
74}
75
76bool PendingActivationStore::InitStorage(
77 GLib *glib,
78 const FilePath &storage_path) {
79 // Close the current file.
80 if (storage_.get()) {
81 storage_->Flush();
82 storage_.reset(); // KeyFileStore closes the file in its destructor.
83 }
84 if (!glib) {
85 LOG(ERROR) << "Null pointer passed for |glib|.";
86 return false;
87 }
88 if (storage_path.empty()) {
89 LOG(ERROR) << "Empty storage directory path provided.";
90 return false;
91 }
92 FilePath path = storage_path.Append(kStorageFileName);
93 scoped_ptr<KeyFileStore> storage(new KeyFileStore(glib));
94 storage->set_path(path);
95 bool already_exists = storage->IsNonEmpty();
96 if (!storage->Open()) {
97 LOG(ERROR) << "Failed to open file at '" << path.AsUTF8Unsafe() << "'";
98 if (already_exists)
99 storage->MarkAsCorrupted();
100 return false;
101 }
102 if (!already_exists)
103 storage->SetHeader("Identifiers pending cellular activation.");
104 storage_.reset(storage.release());
105 return true;
106}
107
108PendingActivationStore::State PendingActivationStore::GetActivationState(
109 IdentifierType type,
110 const string &identifier) const {
111 string formatted_identifier = FormattedIdentifier(type, identifier);
112 SLOG(Cellular, 2) << __func__ << ": " << formatted_identifier;
113 if (!storage_.get()) {
114 LOG(ERROR) << "Underlying storage not initialized.";
115 return kStateUnknown;
116 }
117 int state = 0;
118 if (!storage_->GetInt(IdentifierTypeToGroupId(type), identifier, &state)) {
119 SLOG(Cellular, 2) << "No entry exists for " << formatted_identifier;
120 return kStateUnknown;
121 }
122 if (state <= 0 || state >= kStateMax) {
123 SLOG(Cellular, 2) << "State value read for " << formatted_identifier
124 << " is invalid.";
125 return kStateUnknown;
126 }
127 return static_cast<State>(state);
128}
129
130bool PendingActivationStore::SetActivationState(
131 IdentifierType type,
132 const string &identifier,
133 State state) {
134 SLOG(Cellular, 2) << __func__ << ": State=" << StateToString(state) << ", "
135 << FormattedIdentifier(type, identifier);
136 if (!storage_.get()) {
137 LOG(ERROR) << "Underlying storage not initialized.";
138 return false;
139 }
140 if (state == kStateUnknown) {
141 SLOG(Cellular, 2) << "kStateUnknown cannot be used as a value.";
142 return false;
143 }
144 if (state < 0 || state >= kStateMax) {
145 SLOG(Cellular, 2) << "Cannot set state to \"" << StateToString(state)
146 << "\"";
147 return false;
148 }
149 if (!storage_->SetInt(
150 IdentifierTypeToGroupId(type), identifier, static_cast<int>(state))) {
151 SLOG(Cellular, 2) << "Failed to store the given identifier and state "
152 << "values.";
153 return false;
154 }
155 return storage_->Flush();
156}
157
158bool PendingActivationStore::RemoveEntry(IdentifierType type,
159 const std::string &identifier) {
160 SLOG(Cellular, 2) << __func__ << ": "
161 << FormattedIdentifier(type, identifier);
162 if (!storage_.get()) {
163 LOG(ERROR) << "Underlying storage not initialized.";
164 return false;
165 }
166 if (!storage_->DeleteKey(IdentifierTypeToGroupId(type), identifier)) {
167 SLOG(Cellular, 2) << "Failed to remove the given identifier.";
168 return false;
169 }
170 return storage_->Flush();
171}
172
173} // namespace shill