Index: chrome/browser/component_updater/component_unpacker.cc |
diff --git a/chrome/browser/component_updater/component_unpacker.cc b/chrome/browser/component_updater/component_unpacker.cc |
index ed7bf1fc02a9d3bb3e0f0ec0e3748a2a93eb97e0..7537f01e873c53bc286a9eddc4e1a9b564a98ef5 100644 |
--- a/chrome/browser/component_updater/component_unpacker.cc |
+++ b/chrome/browser/component_updater/component_unpacker.cc |
@@ -31,6 +31,15 @@ namespace component_updater { |
namespace { |
+const char kKeyNameFingerprint[] = "fingerprint"; |
+const char kKeyNamePublicKeyHash[] = "public_key_hash"; |
+const char kKeyNameInProcess[] = "in_process"; |
+ |
+const base::FilePath::CharType kCrxFileName[] = |
+ FILE_PATH_LITERAL("saved_installer.crx"); |
+const base::FilePath::CharType kInstallDataFileName[] = |
+ FILE_PATH_LITERAL("metadata.json"); |
+ |
// This class makes sure that the CRX digital signature is valid |
// and well formed. |
class CRXValidator { |
@@ -124,8 +133,7 @@ scoped_ptr<base::DictionaryValue> ReadManifest( |
if (!base::PathExists(manifest)) |
return scoped_ptr<base::DictionaryValue>(); |
JSONFileValueSerializer serializer(manifest); |
- std::string error; |
- scoped_ptr<base::Value> root(serializer.Deserialize(NULL, &error)); |
+ scoped_ptr<base::Value> root(serializer.Deserialize(NULL, NULL)); |
if (!root.get()) |
return scoped_ptr<base::DictionaryValue>(); |
if (!root->IsType(base::Value::TYPE_DICTIONARY)) |
@@ -264,6 +272,8 @@ void ComponentUnpacker::Install() { |
} |
DCHECK(error_ == kNone); |
if (!installer_->Install(*manifest, unpack_path_)) { |
+ installer_->OnInstallError( |
+ base::Bind(&ComponentUnpacker::SaveInstallSource, this)); |
error_ = kInstallerError; |
return; |
} |
@@ -280,4 +290,82 @@ void ComponentUnpacker::Finish() { |
ComponentUnpacker::~ComponentUnpacker() { |
} |
+bool ComponentUnpacker::SaveInstallSource( |
+ const base::FilePath& backup_path) const { |
+ if (!base::CreateDirectory(backup_path)) { |
+ return false; |
+ } |
+ |
+ const base::FilePath crx_path = backup_path.Append(kCrxFileName); |
+ if (!base::CopyFile(path_, crx_path)) { |
+ return false; |
+ } |
+ |
+ const base::FilePath install_data_file_path = |
+ backup_path.Append(kInstallDataFileName); |
+ JSONFileValueSerializer serializer(install_data_file_path); |
+ |
+ scoped_ptr<base::DictionaryValue> root(new base::DictionaryValue); |
+ root->SetString(kKeyNameFingerprint, fingerprint_); |
+ root->SetBoolean(kKeyNameInProcess, in_process_); |
+ scoped_ptr<base::ListValue> pk_hash_list_value(new base::ListValue); |
+ for (size_t i = 0; i < pk_hash_.size(); ++i) { |
+ pk_hash_list_value->Append(base::Value::CreateIntegerValue( |
+ static_cast<int>(pk_hash_[i]))); |
+ } |
+ root->Set(kKeyNamePublicKeyHash, pk_hash_list_value.release()); |
+ if (!serializer.Serialize(*root)) { |
+ return false; |
+ } |
+ |
+ return true; |
+} |
+ |
+scoped_refptr<ComponentUnpacker> ComponentUnpacker::CreateFromBackup( |
+ const base::FilePath& backup_path, |
+ ComponentInstaller* installer, |
+ scoped_refptr<base::SequencedTaskRunner> task_runner) { |
+ const base::FilePath crx_path = backup_path.Append(kCrxFileName); |
+ if (!base::PathExists(crx_path) || base::DirectoryExists(crx_path)) { |
+ return scoped_refptr<ComponentUnpacker>(); |
+ } |
+ |
+ std::string fingerprint; |
+ bool in_process = false; |
+ |
+ const base::FilePath install_data_file_path = |
+ backup_path.Append(kInstallDataFileName); |
+ if (!base::PathExists(install_data_file_path)) { |
+ return scoped_refptr<ComponentUnpacker>(); |
+ } |
+ |
+ JSONFileValueSerializer serializer(install_data_file_path); |
+ scoped_ptr<base::Value> root(serializer.Deserialize(NULL, NULL)); |
+ if (!root.get() || !root->IsType(base::Value::TYPE_DICTIONARY)) { |
+ return scoped_refptr<ComponentUnpacker>(); |
+ } |
+ |
+ scoped_ptr<base::DictionaryValue> install_metadata( |
+ static_cast<base::DictionaryValue*>(root.release())); |
+ |
+ base::ListValue* pk_hash_list_value = NULL; |
+ if (!install_metadata->GetStringASCII(kKeyNameFingerprint, &fingerprint) || |
+ !install_metadata->GetBoolean(kKeyNameInProcess, &in_process) || |
+ !install_metadata->GetList(kKeyNamePublicKeyHash, &pk_hash_list_value) || |
+ pk_hash_list_value == NULL) { |
+ return scoped_refptr<ComponentUnpacker>(); |
+ } |
+ |
+ std::vector<uint8> pk_hash; |
+ for (size_t i = 0; i < pk_hash_list_value->GetSize(); ++i) { |
+ int value = 0; |
+ if (pk_hash_list_value->GetInteger(i, &value)) { |
+ pk_hash.push_back(static_cast<uint8>(value)); |
+ } |
+ } |
+ |
+ return make_scoped_refptr(new ComponentUnpacker( |
+ pk_hash, crx_path, fingerprint, installer, in_process, task_runner)); |
+} |
+ |
} // namespace component_updater |