Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1558)

Side by Side Diff: extensions/browser/api/lock_screen_data/data_item.cc

Issue 2934293003: The chrome.lockScreen.data API implementation (Closed)
Patch Set: remove FilePath*UTF8Unsafe methods Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 The Chromium 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 "extensions/browser/api/lock_screen_data/data_item.h"
6
7 #include <utility>
8
9 #include "base/bind.h"
10 #include "base/files/file.h"
11 #include "base/files/file_path.h"
12 #include "base/files/file_util.h"
13 #include "base/location.h"
14 #include "base/memory/ptr_util.h"
15 #include "base/sequenced_task_runner.h"
16 #include "base/task_scheduler/post_task.h"
17 #include "base/values.h"
18 #include "crypto/encryptor.h"
19 #include "crypto/symmetric_key.h"
20 #include "extensions/browser/api/lock_screen_data/operation_result.h"
21
22 namespace extensions {
23 namespace lock_screen_data {
24
25 namespace {
26
27 // Keys used to describe a data item in its dictionary value representation:
28 const char kPrefKeyId[] = "id";
29 const char kPrefKeyBackingFile[] = "backing_file";
30
31 // Writes |data| to file specified by |path|. The written data will be encrypted
32 // using symmetric AES key |encryption_key|.
33 // |result| - set to the resulting write operation status.
34 // Expected to be called on worker thread.
35 void WriteImpl(const base::FilePath& path,
36 const std::vector<char>& data,
37 const std::string& encryption_key,
38 OperationResult* result) {
39 std::string iv(16, ' ');
40 std::unique_ptr<crypto::SymmetricKey> key =
41 crypto::SymmetricKey::Import(crypto::SymmetricKey::AES, encryption_key);
42 if (!key) {
43 *result = OperationResult::kInvalidKey;
44 return;
45 }
46
47 crypto::Encryptor encryptor;
48 if (!encryptor.Init(key.get(), crypto::Encryptor::CBC, iv)) {
49 *result = OperationResult::kInvalidKey;
50 return;
51 }
52
53 std::string encrypted;
54 if (!encryptor.Encrypt(std::string(data.data(), data.size()), &encrypted)) {
55 *result = OperationResult::kInvalidKey;
56 return;
57 }
58
59 base::File::Error error;
60 if (!base::DirectoryExists(path.DirName()) &&
61 !base::CreateDirectoryAndGetError(path.DirName(), &error)) {
62 *result = OperationResult::kFileCreationFailed;
63 return;
64 }
65
66 int write_size = base::WriteFile(path, encrypted.data(), encrypted.size());
67 *result = (write_size == static_cast<int>(encrypted.size()))
68 ? OperationResult::kSuccess
69 : OperationResult::kFileWriteFailed;
70 }
71
72 // Reads encrypted data from file specified by |path|. The read data will be
73 // decrypted using using symmetric AES key |encryption_key| before being
74 // returned.
75 // |result| - set to the resulting write operation status.
76 // |data| - set to the clear-text data read from the file.
77 // Expected to be called on worker thread.
78 void ReadImpl(const base::FilePath& path,
79 const std::string& decryption_key,
80 OperationResult* result,
81 std::vector<char>* data) {
82 std::string read_data;
83 if (!base::ReadFileToString(path, &read_data)) {
84 *result = base::PathExists(path) ? OperationResult::kFileReadFailed
85 : OperationResult::kNotFound;
86 return;
87 }
88
89 std::string iv(16, ' ');
90 std::unique_ptr<crypto::SymmetricKey> key =
91 crypto::SymmetricKey::Import(crypto::SymmetricKey::AES, decryption_key);
92 if (!key) {
93 *result = OperationResult::kInvalidKey;
94 return;
95 }
96
97 crypto::Encryptor encryptor;
98 if (!encryptor.Init(key.get(), crypto::Encryptor::CBC, iv)) {
99 *result = OperationResult::kInvalidKey;
100 return;
101 }
102
103 std::string decrypted;
104 if (!encryptor.Decrypt(read_data, &decrypted)) {
105 *result = OperationResult::kWrongKey;
106 return;
107 }
108
109 std::vector<char> result_data(decrypted.data(),
110 decrypted.data() + decrypted.size());
111 data->swap(result_data);
112 *result = OperationResult::kSuccess;
113 }
114
115 // Deletes file under |file_path|.
116 void DeleteImpl(const base::FilePath& file_path,
117 bool recursive,
118 OperationResult* result) {
119 *result = base::DeleteFile(file_path, recursive)
120 ? OperationResult::kSuccess
121 : OperationResult::kFileDeleteFailed;
122 }
123
124 } // namespace
125
126 DataItem::DataItem(const std::string& id) : id_(id), weak_ptr_factory_(this) {}
127
128 DataItem::~DataItem() = default;
129
130 std::unique_ptr<base::DictionaryValue> DataItem::ToValue() {
131 std::unique_ptr<base::DictionaryValue> result =
132 base::MakeUnique<base::DictionaryValue>();
133 result->SetString(kPrefKeyId, id_);
134 result->SetString(kPrefKeyBackingFile, backing_file_.value());
135 return result;
136 }
137
138 bool DataItem::InitFromValue(const base::Value& value) {
139 const base::DictionaryValue* dict_value = nullptr;
140 if (!value.GetAsDictionary(&dict_value))
141 return false;
142
143 std::string item_id;
144 if (!dict_value->GetString(kPrefKeyId, &item_id) || id() != item_id)
145 return false;
146
147 std::string backing_file;
148 if (dict_value->GetString(kPrefKeyBackingFile, &backing_file))
149 set_backing_file(base::FilePath(backing_file));
150
151 return true;
152 }
153
154 OperationResult DataItem::Write(
155 const std::vector<char>& data,
156 const std::string& crypto_key,
157 const scoped_refptr<base::SequencedTaskRunner>& task_runner,
158 const WriteCallback& callback) {
159 if (backing_file_.empty())
160 return OperationResult::kNoBackingFile;
161
162 std::unique_ptr<OperationResult> result =
163 base::MakeUnique<OperationResult>(OperationResult::kFailed);
164 OperationResult* result_ptr = result.get();
165
166 task_runner->PostTaskAndReply(
167 FROM_HERE,
168 base::Bind(&WriteImpl, backing_file_, data, crypto_key, result_ptr),
169 base::Bind(&DataItem::OnWriteDone, weak_ptr_factory_.GetWeakPtr(),
170 callback, base::Passed(&result)));
171 return OperationResult::kPending;
172 }
173
174 OperationResult DataItem::Read(
175 const std::string& crypto_key,
176 const scoped_refptr<base::SequencedTaskRunner>& task_runner,
177 const ReadCallback& callback) {
178 if (backing_file_.empty())
179 return OperationResult::kNoBackingFile;
180
181 std::unique_ptr<OperationResult> result =
182 base::MakeUnique<OperationResult>(OperationResult::kFailed);
183 OperationResult* result_ptr = result.get();
184
185 std::unique_ptr<std::vector<char>> data =
186 base::MakeUnique<std::vector<char>>();
187 std::vector<char>* data_ptr = data.get();
188
189 task_runner->PostTaskAndReply(
190 FROM_HERE,
191 base::Bind(&ReadImpl, backing_file_, crypto_key, result_ptr, data_ptr),
192 base::Bind(&DataItem::OnReadDone, weak_ptr_factory_.GetWeakPtr(),
193 callback, base::Passed(&result), base::Passed(&data)));
194 return OperationResult::kPending;
195 }
196
197 OperationResult DataItem::Delete(
198 const scoped_refptr<base::SequencedTaskRunner>& task_runner,
199 const DeleteCallback& callback) {
200 if (backing_file_.empty())
201 return OperationResult::kNoBackingFile;
202
203 std::unique_ptr<OperationResult> result =
204 base::MakeUnique<OperationResult>(OperationResult::kFailed);
205 OperationResult* result_ptr = result.get();
206
207 task_runner->PostTaskAndReply(
208 FROM_HERE, base::Bind(&DeleteImpl, backing_file_, false, result_ptr),
209 base::Bind(&DataItem::OnDeleteDone, weak_ptr_factory_.GetWeakPtr(),
210 callback, base::Passed(&result)));
211
212 backing_file_ = base::FilePath();
213 return OperationResult::kPending;
214 }
215
216 void DataItem::OnWriteDone(const DataItem::WriteCallback& callback,
217 std::unique_ptr<OperationResult> success) {
218 callback.Run(*success);
219 }
220
221 void DataItem::OnReadDone(const DataItem::ReadCallback& callback,
222 std::unique_ptr<OperationResult> success,
223 std::unique_ptr<std::vector<char>> data) {
224 callback.Run(*success, std::move(data));
225 }
226
227 void DataItem::OnDeleteDone(const DataItem::DeleteCallback& callback,
228 std::unique_ptr<OperationResult> success) {
229 callback.Run(*success);
230 }
231
232 } // namespace lock_screen_data
233 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698