Commit b0823d3c authored by Maksim Moskvitin's avatar Maksim Moskvitin Committed by Commit Bot

[Sync:USS] Implement NigoriStorageImpl

We write NigoriLocalData in encrypted form to corresponding file using
ImportantFileWriter. Reading is just mirrored version of writing.

Bug: 922900
Change-Id: I299f55450e74edac29beaacf7b5dc659f5fd8f8a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1768424
Commit-Queue: Maksim Moskvitin <mmoskvitin@google.com>
Reviewed-by: default avatarMarc Treib <treib@chromium.org>
Cr-Commit-Position: refs/heads/master@{#690014}
parent 004070c0
...@@ -643,6 +643,7 @@ source_set("unit_tests") { ...@@ -643,6 +643,7 @@ source_set("unit_tests") {
"nigori/cryptographer_unittest.cc", "nigori/cryptographer_unittest.cc",
"nigori/nigori_key_bag_unittest.cc", "nigori/nigori_key_bag_unittest.cc",
"nigori/nigori_model_type_processor_unittest.cc", "nigori/nigori_model_type_processor_unittest.cc",
"nigori/nigori_storage_impl_unittest.cc",
"nigori/nigori_sync_bridge_impl_unittest.cc", "nigori/nigori_sync_bridge_impl_unittest.cc",
"nigori/nigori_unittest.cc", "nigori/nigori_unittest.cc",
"protocol/proto_enum_conversions_unittest.cc", "protocol/proto_enum_conversions_unittest.cc",
......
...@@ -6,11 +6,16 @@ ...@@ -6,11 +6,16 @@
#include <string> #include <string>
#include "base/files/file_util.h"
#include "base/files/important_file_writer.h"
#include "components/sync/base/encryptor.h"
namespace syncer { namespace syncer {
NigoriStorageImpl::NigoriStorageImpl(const base::FilePath& path, NigoriStorageImpl::NigoriStorageImpl(const base::FilePath& path,
const Encryptor* encryptor) { const Encryptor* encryptor)
NOTIMPLEMENTED(); : path_(path), encryptor_(encryptor) {
DCHECK(encryptor_);
} }
NigoriStorageImpl::~NigoriStorageImpl() { NigoriStorageImpl::~NigoriStorageImpl() {
...@@ -19,13 +24,48 @@ NigoriStorageImpl::~NigoriStorageImpl() { ...@@ -19,13 +24,48 @@ NigoriStorageImpl::~NigoriStorageImpl() {
void NigoriStorageImpl::StoreData(const sync_pb::NigoriLocalData& data) { void NigoriStorageImpl::StoreData(const sync_pb::NigoriLocalData& data) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
NOTIMPLEMENTED();
std::string serialized_data = data.SerializeAsString();
if (serialized_data.empty()) {
DLOG(ERROR) << "Failed to serialize NigoriLocalData.";
return;
}
std::string encrypted_data;
if (!encryptor_->EncryptString(serialized_data, &encrypted_data)) {
DLOG(ERROR) << "Failed to encrypt NigoriLocalData.";
return;
}
if (!base::ImportantFileWriter::WriteFileAtomically(path_, encrypted_data)) {
DLOG(ERROR) << "Failed to write NigoriLocalData into file.";
}
} }
base::Optional<sync_pb::NigoriLocalData> NigoriStorageImpl::RestoreData() { base::Optional<sync_pb::NigoriLocalData> NigoriStorageImpl::RestoreData() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
NOTIMPLEMENTED(); if (!base::PathExists(path_)) {
return base::nullopt; return base::nullopt;
}
std::string encrypted_data;
if (!base::ReadFileToString(path_, &encrypted_data)) {
DLOG(ERROR) << "Failed to read NigoriLocalData from file.";
return base::nullopt;
}
std::string serialized_data;
if (!encryptor_->DecryptString(encrypted_data, &serialized_data)) {
DLOG(ERROR) << "Failed to decrypt NigoriLocalData.";
return base::nullopt;
}
sync_pb::NigoriLocalData data;
if (!data.ParseFromString(serialized_data)) {
DLOG(ERROR) << "Failed to parse NigoriLocalData.";
return base::nullopt;
}
return data;
} }
} // namespace syncer } // namespace syncer
...@@ -15,6 +15,7 @@ class Encryptor; ...@@ -15,6 +15,7 @@ class Encryptor;
class NigoriStorageImpl : NigoriStorage { class NigoriStorageImpl : NigoriStorage {
public: public:
// |encryptor| must be not null and must outlive this object.
NigoriStorageImpl(const base::FilePath& path, const Encryptor* encryptor); NigoriStorageImpl(const base::FilePath& path, const Encryptor* encryptor);
~NigoriStorageImpl() override; ~NigoriStorageImpl() override;
...@@ -24,6 +25,9 @@ class NigoriStorageImpl : NigoriStorage { ...@@ -24,6 +25,9 @@ class NigoriStorageImpl : NigoriStorage {
base::Optional<sync_pb::NigoriLocalData> RestoreData() override; base::Optional<sync_pb::NigoriLocalData> RestoreData() override;
private: private:
base::FilePath path_;
const Encryptor* const encryptor_;
SEQUENCE_CHECKER(sequence_checker_); SEQUENCE_CHECKER(sequence_checker_);
DISALLOW_COPY_AND_ASSIGN(NigoriStorageImpl); DISALLOW_COPY_AND_ASSIGN(NigoriStorageImpl);
}; };
......
// Copyright 2019 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 "components/sync/nigori/nigori_storage_impl.h"
#include "base/files/scoped_temp_dir.h"
#include "components/sync/base/fake_encryptor.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace syncer {
namespace {
sync_pb::NigoriLocalData MakeSomeNigoriLocalData() {
sync_pb::NigoriLocalData result;
result.mutable_model_type_state()->set_initial_sync_done(true);
result.mutable_entity_metadata()->set_sequence_number(1);
result.mutable_nigori_model()->set_encrypt_everything(true);
return result;
}
class NigoriStorageImplTest : public testing::Test {
protected:
NigoriStorageImplTest() = default;
~NigoriStorageImplTest() override = default;
void SetUp() override { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); }
const Encryptor* encryptor() { return &encryptor_; }
base::FilePath GetFilePath() {
return temp_dir_.GetPath().Append(
base::FilePath(FILE_PATH_LITERAL("some_file")));
}
private:
FakeEncryptor encryptor_;
base::ScopedTempDir temp_dir_;
};
TEST_F(NigoriStorageImplTest, ShouldBeAbleToRestoreAfterWrite) {
NigoriStorageImpl writer_storage(GetFilePath(), encryptor());
sync_pb::NigoriLocalData write_data = MakeSomeNigoriLocalData();
writer_storage.StoreData(write_data);
// Use different NigoriStorageImpl when reading to avoid dependency on its
// state and emulate browser restart.
NigoriStorageImpl reader_storage(GetFilePath(), encryptor());
base::Optional<sync_pb::NigoriLocalData> read_data =
reader_storage.RestoreData();
EXPECT_NE(read_data, base::nullopt);
EXPECT_EQ(read_data->SerializeAsString(), write_data.SerializeAsString());
}
TEST_F(NigoriStorageImplTest, ShouldReturnNulloptWhenFileNotExists) {
NigoriStorageImpl storage(GetFilePath(), encryptor());
EXPECT_EQ(storage.RestoreData(), base::nullopt);
}
} // namespace
} // namespace syncer
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment