Commit 11484015 authored by Istiaque Ahmed's avatar Istiaque Ahmed Committed by Commit Bot

[Extensions] Add a static factory to create VerifiedContents.

This CL combines VerifiedContents class instantiation and initializing
it from a file to a single static factory. Consumer of
VerifiedContents always requires both, so it's slightly better with
the factory.

Bug: None
Test: None, internal cleanup.
Change-Id: I8938433c7f95b93425c25f5fda0299d23cfa65e3
Reviewed-on: https://chromium-review.googlesource.com/1149411Reviewed-by: default avatarDevlin <rdevlin.cronin@chromium.org>
Commit-Queue: Istiaque Ahmed <lazyboy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#578000}
parent 26ed203c
...@@ -47,10 +47,11 @@ std::unique_ptr<VerifiedContents> GetVerifiedContents( ...@@ -47,10 +47,11 @@ std::unique_ptr<VerifiedContents> GetVerifiedContents(
bool delete_invalid_file) { bool delete_invalid_file) {
base::AssertBlockingAllowed(); base::AssertBlockingAllowed();
DCHECK(GetExtensionFileTaskRunner()->RunsTasksInCurrentSequence()); DCHECK(GetExtensionFileTaskRunner()->RunsTasksInCurrentSequence());
auto verified_contents = std::make_unique<VerifiedContents>(key.verifier_key);
base::FilePath verified_contents_path = base::FilePath verified_contents_path =
file_util::GetVerifiedContentsPath(key.extension_root); file_util::GetVerifiedContentsPath(key.extension_root);
if (!verified_contents->InitFrom(verified_contents_path)) { std::unique_ptr<VerifiedContents> verified_contents =
VerifiedContents::Create(key.verifier_key, verified_contents_path);
if (!verified_contents) {
if (delete_invalid_file && if (delete_invalid_file &&
!base::DeleteFile(verified_contents_path, false)) { !base::DeleteFile(verified_contents_path, false)) {
LOG(WARNING) << "Failed to delete " << verified_contents_path.value(); LOG(WARNING) << "Failed to delete " << verified_contents_path.value();
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "base/base64url.h" #include "base/base64url.h"
#include "base/files/file_util.h" #include "base/files/file_util.h"
#include "base/json/json_reader.h" #include "base/json/json_reader.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h" #include "base/metrics/histogram_macros.h"
#include "base/strings/string_util.h" #include "base/strings/string_util.h"
#include "base/timer/elapsed_timer.h" #include "base/timer/elapsed_timer.h"
...@@ -142,39 +143,44 @@ VerifiedContents::~VerifiedContents() { ...@@ -142,39 +143,44 @@ VerifiedContents::~VerifiedContents() {
// } // }
// ] // ]
// } // }
bool VerifiedContents::InitFrom(const base::FilePath& path) { // static.
std::unique_ptr<VerifiedContents> VerifiedContents::Create(
base::span<const uint8_t> public_key,
const base::FilePath& path) {
ScopedUMARecorder uma_recorder; ScopedUMARecorder uma_recorder;
// Note: VerifiedContents constructor is private.
auto verified_contents = base::WrapUnique(new VerifiedContents(public_key));
std::string payload; std::string payload;
if (!GetPayload(path, &payload)) if (!verified_contents->GetPayload(path, &payload))
return false; return nullptr;
std::unique_ptr<base::Value> value(base::JSONReader::Read(payload)); std::unique_ptr<base::Value> value(base::JSONReader::Read(payload));
if (!value.get() || !value->is_dict()) if (!value.get() || !value->is_dict())
return false; return nullptr;
DictionaryValue* dictionary = static_cast<DictionaryValue*>(value.get()); DictionaryValue* dictionary = static_cast<DictionaryValue*>(value.get());
std::string item_id; std::string item_id;
if (!dictionary->GetString(kItemIdKey, &item_id) || if (!dictionary->GetString(kItemIdKey, &item_id) ||
!crx_file::id_util::IdIsValid(item_id)) { !crx_file::id_util::IdIsValid(item_id)) {
return false; return nullptr;
} }
extension_id_ = item_id; verified_contents->extension_id_ = item_id;
std::string version_string; std::string version_string;
if (!dictionary->GetString(kItemVersionKey, &version_string)) if (!dictionary->GetString(kItemVersionKey, &version_string))
return false; return nullptr;
version_ = base::Version(version_string); verified_contents->version_ = base::Version(version_string);
if (!version_.IsValid()) if (!verified_contents->version_.IsValid())
return false; return nullptr;
ListValue* hashes_list = NULL; ListValue* hashes_list = nullptr;
if (!dictionary->GetList(kContentHashesKey, &hashes_list)) if (!dictionary->GetList(kContentHashesKey, &hashes_list))
return false; return nullptr;
for (size_t i = 0; i < hashes_list->GetSize(); i++) { for (size_t i = 0; i < hashes_list->GetSize(); i++) {
DictionaryValue* hashes = NULL; DictionaryValue* hashes = nullptr;
if (!hashes_list->GetDictionary(i, &hashes)) if (!hashes_list->GetDictionary(i, &hashes))
return false; return nullptr;
std::string format; std::string format;
if (!hashes->GetString(kFormatKey, &format) || format != kTreeHash) if (!hashes->GetString(kFormatKey, &format) || format != kTreeHash)
continue; continue;
...@@ -183,23 +189,23 @@ bool VerifiedContents::InitFrom(const base::FilePath& path) { ...@@ -183,23 +189,23 @@ bool VerifiedContents::InitFrom(const base::FilePath& path) {
int hash_block_size = 0; int hash_block_size = 0;
if (!hashes->GetInteger(kBlockSizeKey, &block_size) || if (!hashes->GetInteger(kBlockSizeKey, &block_size) ||
!hashes->GetInteger(kHashBlockSizeKey, &hash_block_size)) { !hashes->GetInteger(kHashBlockSizeKey, &hash_block_size)) {
return false; return nullptr;
} }
block_size_ = block_size; verified_contents->block_size_ = block_size;
// We don't support using a different block_size and hash_block_size at // We don't support using a different block_size and hash_block_size at
// the moment. // the moment.
if (block_size_ != hash_block_size) if (verified_contents->block_size_ != hash_block_size)
return false; return nullptr;
ListValue* files = NULL; ListValue* files = nullptr;
if (!hashes->GetList(kFilesKey, &files)) if (!hashes->GetList(kFilesKey, &files))
return false; return nullptr;
for (size_t j = 0; j < files->GetSize(); j++) { for (size_t j = 0; j < files->GetSize(); ++j) {
DictionaryValue* data = NULL; DictionaryValue* data = nullptr;
if (!files->GetDictionary(j, &data)) if (!files->GetDictionary(j, &data))
return false; return nullptr;
std::string file_path_string; std::string file_path_string;
std::string encoded_root_hash; std::string encoded_root_hash;
std::string root_hash; std::string root_hash;
...@@ -209,13 +215,13 @@ bool VerifiedContents::InitFrom(const base::FilePath& path) { ...@@ -209,13 +215,13 @@ bool VerifiedContents::InitFrom(const base::FilePath& path) {
!base::Base64UrlDecode(encoded_root_hash, !base::Base64UrlDecode(encoded_root_hash,
base::Base64UrlDecodePolicy::IGNORE_PADDING, base::Base64UrlDecodePolicy::IGNORE_PADDING,
&root_hash)) { &root_hash)) {
return false; return nullptr;
} }
base::FilePath file_path = base::FilePath file_path =
base::FilePath::FromUTF8Unsafe(file_path_string); base::FilePath::FromUTF8Unsafe(file_path_string);
base::FilePath::StringType lowercase_file_path = base::FilePath::StringType lowercase_file_path =
base::ToLowerASCII(file_path.value()); base::ToLowerASCII(file_path.value());
RootHashes::iterator i = root_hashes_.insert( RootHashes::iterator i = verified_contents->root_hashes_.insert(
std::make_pair(lowercase_file_path, std::string())); std::make_pair(lowercase_file_path, std::string()));
i->second.swap(root_hash); i->second.swap(root_hash);
...@@ -225,14 +231,15 @@ bool VerifiedContents::InitFrom(const base::FilePath& path) { ...@@ -225,14 +231,15 @@ bool VerifiedContents::InitFrom(const base::FilePath& path) {
// HasTreeHashRoot() and TreeHashRootEquals(). // HasTreeHashRoot() and TreeHashRootEquals().
base::FilePath::StringType trimmed_path; base::FilePath::StringType trimmed_path;
if (TrimDotSpaceSuffix(lowercase_file_path, &trimmed_path)) if (TrimDotSpaceSuffix(lowercase_file_path, &trimmed_path))
root_hashes_.insert(std::make_pair(trimmed_path, i->second)); verified_contents->root_hashes_.insert(
std::make_pair(trimmed_path, i->second));
#endif // defined(OS_WIN) #endif // defined(OS_WIN)
} }
break; break;
} }
uma_recorder.RecordSuccess(); uma_recorder.RecordSuccess();
return true; return verified_contents;
} }
bool VerifiedContents::HasTreeHashRoot( bool VerifiedContents::HasTreeHashRoot(
......
...@@ -24,13 +24,16 @@ namespace extensions { ...@@ -24,13 +24,16 @@ namespace extensions {
// corruption of extension files on local disk. // corruption of extension files on local disk.
class VerifiedContents { class VerifiedContents {
public: public:
// Note: the public_key must remain valid for the lifetime of this object.
explicit VerifiedContents(base::span<const uint8_t> public_key);
~VerifiedContents(); ~VerifiedContents();
// Returns true if we successfully parsed the verified_contents.json file at // Returns verified contents after successfully parsing verified_contents.json
// |path| and validated the enclosed signature. The // file at |path| and validating the enclosed signature. Returns nullptr on
bool InitFrom(const base::FilePath& path); // failure.
// Note: |public_key| must remain valid for the lifetime of the returned
// object.
static std::unique_ptr<VerifiedContents> Create(
base::span<const uint8_t> public_key,
const base::FilePath& path);
int block_size() const { return block_size_; } int block_size() const { return block_size_; }
const std::string& extension_id() const { return extension_id_; } const std::string& extension_id() const { return extension_id_; }
...@@ -46,6 +49,9 @@ class VerifiedContents { ...@@ -46,6 +49,9 @@ class VerifiedContents {
bool valid_signature() { return valid_signature_; } bool valid_signature() { return valid_signature_; }
private: private:
// Note: the public_key must remain valid for the lifetime of this object.
explicit VerifiedContents(base::span<const uint8_t> public_key);
// Returns the base64url-decoded "payload" field from the json at |path|, if // Returns the base64url-decoded "payload" field from the json at |path|, if
// the signature was valid. // the signature was valid.
bool GetPayload(const base::FilePath& path, std::string* payload); bool GetPayload(const base::FilePath& path, std::string* payload);
......
...@@ -71,13 +71,10 @@ std::unique_ptr<VerifiedContents> CreateTestVerifiedContents( ...@@ -71,13 +71,10 @@ std::unique_ptr<VerifiedContents> CreateTestVerifiedContents(
if (!GetPublicKey(path.AppendASCII(kPublicKeyPem), &public_key)) if (!GetPublicKey(path.AppendASCII(kPublicKeyPem), &public_key))
return nullptr; return nullptr;
auto contents = std::make_unique<VerifiedContents>(
base::as_bytes(base::make_span(public_key)));
base::FilePath verified_contents_path = base::FilePath verified_contents_path =
path.AppendASCII(verified_contents_filename); path.AppendASCII(verified_contents_filename);
if (!contents->InitFrom(verified_contents_path)) return VerifiedContents::Create(base::as_bytes(base::make_span(public_key)),
return nullptr; verified_contents_path);
return contents;
} }
} // namespace } // namespace
......
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