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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: extensions/browser/api/lock_screen_data/data_item.cc
diff --git a/extensions/browser/api/lock_screen_data/data_item.cc b/extensions/browser/api/lock_screen_data/data_item.cc
new file mode 100644
index 0000000000000000000000000000000000000000..af14d5a51b0a0a5fd7daa5b8f103b68ff379caf0
--- /dev/null
+++ b/extensions/browser/api/lock_screen_data/data_item.cc
@@ -0,0 +1,233 @@
+// Copyright 2017 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 "extensions/browser/api/lock_screen_data/data_item.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/files/file.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/location.h"
+#include "base/memory/ptr_util.h"
+#include "base/sequenced_task_runner.h"
+#include "base/task_scheduler/post_task.h"
+#include "base/values.h"
+#include "crypto/encryptor.h"
+#include "crypto/symmetric_key.h"
+#include "extensions/browser/api/lock_screen_data/operation_result.h"
+
+namespace extensions {
+namespace lock_screen_data {
+
+namespace {
+
+// Keys used to describe a data item in its dictionary value representation:
+const char kPrefKeyId[] = "id";
+const char kPrefKeyBackingFile[] = "backing_file";
+
+// Writes |data| to file specified by |path|. The written data will be encrypted
+// using symmetric AES key |encryption_key|.
+// |result| - set to the resulting write operation status.
+// Expected to be called on worker thread.
+void WriteImpl(const base::FilePath& path,
+ const std::vector<char>& data,
+ const std::string& encryption_key,
+ OperationResult* result) {
+ std::string iv(16, ' ');
+ std::unique_ptr<crypto::SymmetricKey> key =
+ crypto::SymmetricKey::Import(crypto::SymmetricKey::AES, encryption_key);
+ if (!key) {
+ *result = OperationResult::kInvalidKey;
+ return;
+ }
+
+ crypto::Encryptor encryptor;
+ if (!encryptor.Init(key.get(), crypto::Encryptor::CBC, iv)) {
+ *result = OperationResult::kInvalidKey;
+ return;
+ }
+
+ std::string encrypted;
+ if (!encryptor.Encrypt(std::string(data.data(), data.size()), &encrypted)) {
+ *result = OperationResult::kInvalidKey;
+ return;
+ }
+
+ base::File::Error error;
+ if (!base::DirectoryExists(path.DirName()) &&
+ !base::CreateDirectoryAndGetError(path.DirName(), &error)) {
+ *result = OperationResult::kFileCreationFailed;
+ return;
+ }
+
+ int write_size = base::WriteFile(path, encrypted.data(), encrypted.size());
+ *result = (write_size == static_cast<int>(encrypted.size()))
+ ? OperationResult::kSuccess
+ : OperationResult::kFileWriteFailed;
+}
+
+// Reads encrypted data from file specified by |path|. The read data will be
+// decrypted using using symmetric AES key |encryption_key| before being
+// returned.
+// |result| - set to the resulting write operation status.
+// |data| - set to the clear-text data read from the file.
+// Expected to be called on worker thread.
+void ReadImpl(const base::FilePath& path,
+ const std::string& decryption_key,
+ OperationResult* result,
+ std::vector<char>* data) {
+ std::string read_data;
+ if (!base::ReadFileToString(path, &read_data)) {
+ *result = base::PathExists(path) ? OperationResult::kFileReadFailed
+ : OperationResult::kNotFound;
+ return;
+ }
+
+ std::string iv(16, ' ');
+ std::unique_ptr<crypto::SymmetricKey> key =
+ crypto::SymmetricKey::Import(crypto::SymmetricKey::AES, decryption_key);
+ if (!key) {
+ *result = OperationResult::kInvalidKey;
+ return;
+ }
+
+ crypto::Encryptor encryptor;
+ if (!encryptor.Init(key.get(), crypto::Encryptor::CBC, iv)) {
+ *result = OperationResult::kInvalidKey;
+ return;
+ }
+
+ std::string decrypted;
+ if (!encryptor.Decrypt(read_data, &decrypted)) {
+ *result = OperationResult::kWrongKey;
+ return;
+ }
+
+ std::vector<char> result_data(decrypted.data(),
+ decrypted.data() + decrypted.size());
+ data->swap(result_data);
+ *result = OperationResult::kSuccess;
+}
+
+// Deletes file under |file_path|.
+void DeleteImpl(const base::FilePath& file_path,
+ bool recursive,
+ OperationResult* result) {
+ *result = base::DeleteFile(file_path, recursive)
+ ? OperationResult::kSuccess
+ : OperationResult::kFileDeleteFailed;
+}
+
+} // namespace
+
+DataItem::DataItem(const std::string& id) : id_(id), weak_ptr_factory_(this) {}
+
+DataItem::~DataItem() = default;
+
+std::unique_ptr<base::DictionaryValue> DataItem::ToValue() {
+ std::unique_ptr<base::DictionaryValue> result =
+ base::MakeUnique<base::DictionaryValue>();
+ result->SetString(kPrefKeyId, id_);
+ result->SetString(kPrefKeyBackingFile, backing_file_.value());
+ return result;
+}
+
+bool DataItem::InitFromValue(const base::Value& value) {
+ const base::DictionaryValue* dict_value = nullptr;
+ if (!value.GetAsDictionary(&dict_value))
+ return false;
+
+ std::string item_id;
+ if (!dict_value->GetString(kPrefKeyId, &item_id) || id() != item_id)
+ return false;
+
+ std::string backing_file;
+ if (dict_value->GetString(kPrefKeyBackingFile, &backing_file))
+ set_backing_file(base::FilePath(backing_file));
+
+ return true;
+}
+
+OperationResult DataItem::Write(
+ const std::vector<char>& data,
+ const std::string& crypto_key,
+ const scoped_refptr<base::SequencedTaskRunner>& task_runner,
+ const WriteCallback& callback) {
+ if (backing_file_.empty())
+ return OperationResult::kNoBackingFile;
+
+ std::unique_ptr<OperationResult> result =
+ base::MakeUnique<OperationResult>(OperationResult::kFailed);
+ OperationResult* result_ptr = result.get();
+
+ task_runner->PostTaskAndReply(
+ FROM_HERE,
+ base::Bind(&WriteImpl, backing_file_, data, crypto_key, result_ptr),
+ base::Bind(&DataItem::OnWriteDone, weak_ptr_factory_.GetWeakPtr(),
+ callback, base::Passed(&result)));
+ return OperationResult::kPending;
+}
+
+OperationResult DataItem::Read(
+ const std::string& crypto_key,
+ const scoped_refptr<base::SequencedTaskRunner>& task_runner,
+ const ReadCallback& callback) {
+ if (backing_file_.empty())
+ return OperationResult::kNoBackingFile;
+
+ std::unique_ptr<OperationResult> result =
+ base::MakeUnique<OperationResult>(OperationResult::kFailed);
+ OperationResult* result_ptr = result.get();
+
+ std::unique_ptr<std::vector<char>> data =
+ base::MakeUnique<std::vector<char>>();
+ std::vector<char>* data_ptr = data.get();
+
+ task_runner->PostTaskAndReply(
+ FROM_HERE,
+ base::Bind(&ReadImpl, backing_file_, crypto_key, result_ptr, data_ptr),
+ base::Bind(&DataItem::OnReadDone, weak_ptr_factory_.GetWeakPtr(),
+ callback, base::Passed(&result), base::Passed(&data)));
+ return OperationResult::kPending;
+}
+
+OperationResult DataItem::Delete(
+ const scoped_refptr<base::SequencedTaskRunner>& task_runner,
+ const DeleteCallback& callback) {
+ if (backing_file_.empty())
+ return OperationResult::kNoBackingFile;
+
+ std::unique_ptr<OperationResult> result =
+ base::MakeUnique<OperationResult>(OperationResult::kFailed);
+ OperationResult* result_ptr = result.get();
+
+ task_runner->PostTaskAndReply(
+ FROM_HERE, base::Bind(&DeleteImpl, backing_file_, false, result_ptr),
+ base::Bind(&DataItem::OnDeleteDone, weak_ptr_factory_.GetWeakPtr(),
+ callback, base::Passed(&result)));
+
+ backing_file_ = base::FilePath();
+ return OperationResult::kPending;
+}
+
+void DataItem::OnWriteDone(const DataItem::WriteCallback& callback,
+ std::unique_ptr<OperationResult> success) {
+ callback.Run(*success);
+}
+
+void DataItem::OnReadDone(const DataItem::ReadCallback& callback,
+ std::unique_ptr<OperationResult> success,
+ std::unique_ptr<std::vector<char>> data) {
+ callback.Run(*success, std::move(data));
+}
+
+void DataItem::OnDeleteDone(const DataItem::DeleteCallback& callback,
+ std::unique_ptr<OperationResult> success) {
+ callback.Run(*success);
+}
+
+} // namespace lock_screen_data
+} // namespace extensions

Powered by Google App Engine
This is Rietveld 408576698