Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / component_updater / component_patcher_operation.cc
blob9880f42707dc571876e01aaee4fc41cb955fac21
1 // Copyright 2013 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.
5 #include "chrome/browser/component_updater/component_patcher_operation.h"
7 #include <string>
8 #include <vector>
10 #include "base/file_util.h"
11 #include "base/files/memory_mapped_file.h"
12 #include "base/json/json_file_value_serializer.h"
13 #include "base/memory/scoped_handle.h"
14 #include "base/path_service.h"
15 #include "base/strings/string_number_conversions.h"
16 #include "chrome/browser/component_updater/component_patcher.h"
17 #include "chrome/browser/component_updater/component_updater_service.h"
18 #include "chrome/common/extensions/extension_constants.h"
19 #include "crypto/secure_hash.h"
20 #include "crypto/sha2.h"
21 #include "crypto/signature_verifier.h"
22 #include "extensions/common/crx_file.h"
23 #include "third_party/zlib/google/zip.h"
25 using crypto::SecureHash;
27 namespace component_updater {
29 namespace {
31 const char kInput[] = "input";
32 const char kOp[] = "op";
33 const char kOutput[] = "output";
34 const char kPatch[] = "patch";
35 const char kSha256[] = "sha256";
37 } // namespace
39 DeltaUpdateOp* CreateDeltaUpdateOp(base::DictionaryValue* command) {
40 std::string operation;
41 if (!command->GetString(kOp, &operation))
42 return NULL;
43 if (operation == "copy")
44 return new DeltaUpdateOpCopy();
45 else if (operation == "create")
46 return new DeltaUpdateOpCreate();
47 else if (operation == "bsdiff")
48 return new DeltaUpdateOpPatchBsdiff();
49 else if (operation == "courgette")
50 return new DeltaUpdateOpPatchCourgette();
51 return NULL;
54 DeltaUpdateOp::DeltaUpdateOp() {}
56 DeltaUpdateOp::~DeltaUpdateOp() {}
58 ComponentUnpacker::Error DeltaUpdateOp::Run(base::DictionaryValue* command_args,
59 const base::FilePath& input_dir,
60 const base::FilePath& unpack_dir,
61 ComponentPatcher* patcher,
62 ComponentInstaller* installer,
63 int* error) {
64 std::string output_rel_path;
65 if (!command_args->GetString(kOutput, &output_rel_path) ||
66 !command_args->GetString(kSha256, &output_sha256_))
67 return ComponentUnpacker::kDeltaBadCommands;
69 output_abs_path_ = unpack_dir.Append(
70 base::FilePath::FromUTF8Unsafe(output_rel_path));
71 ComponentUnpacker::Error parse_result = DoParseArguments(
72 command_args, input_dir, installer);
73 if (parse_result != ComponentUnpacker::kNone)
74 return parse_result;
76 const base::FilePath parent = output_abs_path_.DirName();
77 if (!base::DirectoryExists(parent)) {
78 if (!base::CreateDirectory(parent))
79 return ComponentUnpacker::kIoError;
82 ComponentUnpacker::Error run_result = DoRun(patcher, error);
83 if (run_result != ComponentUnpacker::kNone)
84 return run_result;
86 return CheckHash();
89 // Uses the hash as a checksum to confirm that the file now residing in the
90 // output directory probably has the contents it should.
91 ComponentUnpacker::Error DeltaUpdateOp::CheckHash() {
92 std::vector<uint8> expected_hash;
93 if (!base::HexStringToBytes(output_sha256_, &expected_hash) ||
94 expected_hash.size() != crypto::kSHA256Length)
95 return ComponentUnpacker::kDeltaVerificationFailure;
97 base::MemoryMappedFile output_file_mmapped;
98 if (!output_file_mmapped.Initialize(output_abs_path_))
99 return ComponentUnpacker::kDeltaVerificationFailure;
101 uint8 actual_hash[crypto::kSHA256Length] = {0};
102 const scoped_ptr<SecureHash> hasher(SecureHash::Create(SecureHash::SHA256));
103 hasher->Update(output_file_mmapped.data(), output_file_mmapped.length());
104 hasher->Finish(actual_hash, sizeof(actual_hash));
105 if (memcmp(actual_hash, &expected_hash[0], sizeof(actual_hash)))
106 return ComponentUnpacker::kDeltaVerificationFailure;
108 return ComponentUnpacker::kNone;
111 DeltaUpdateOpCopy::DeltaUpdateOpCopy() {}
113 ComponentUnpacker::Error DeltaUpdateOpCopy::DoParseArguments(
114 base::DictionaryValue* command_args,
115 const base::FilePath& input_dir,
116 ComponentInstaller* installer) {
117 std::string input_rel_path;
118 if (!command_args->GetString(kInput, &input_rel_path))
119 return ComponentUnpacker::kDeltaBadCommands;
121 if (!installer->GetInstalledFile(input_rel_path, &input_abs_path_))
122 return ComponentUnpacker::kDeltaMissingExistingFile;
124 return ComponentUnpacker::kNone;
127 ComponentUnpacker::Error DeltaUpdateOpCopy::DoRun(ComponentPatcher*,
128 int* error) {
129 *error = 0;
130 if (!base::CopyFile(input_abs_path_, output_abs_path_))
131 return ComponentUnpacker::kDeltaOperationFailure;
133 return ComponentUnpacker::kNone;
136 DeltaUpdateOpCreate::DeltaUpdateOpCreate() {}
138 ComponentUnpacker::Error DeltaUpdateOpCreate::DoParseArguments(
139 base::DictionaryValue* command_args,
140 const base::FilePath& input_dir,
141 ComponentInstaller* installer) {
142 std::string patch_rel_path;
143 if (!command_args->GetString(kPatch, &patch_rel_path))
144 return ComponentUnpacker::kDeltaBadCommands;
146 patch_abs_path_ = input_dir.Append(
147 base::FilePath::FromUTF8Unsafe(patch_rel_path));
149 return ComponentUnpacker::kNone;
152 ComponentUnpacker::Error DeltaUpdateOpCreate::DoRun(ComponentPatcher*,
153 int* error) {
154 *error = 0;
155 if (!base::Move(patch_abs_path_, output_abs_path_))
156 return ComponentUnpacker::kDeltaOperationFailure;
158 return ComponentUnpacker::kNone;
161 DeltaUpdateOpPatchBsdiff::DeltaUpdateOpPatchBsdiff() {}
163 ComponentUnpacker::Error DeltaUpdateOpPatchBsdiff::DoParseArguments(
164 base::DictionaryValue* command_args,
165 const base::FilePath& input_dir,
166 ComponentInstaller* installer) {
167 std::string patch_rel_path;
168 std::string input_rel_path;
169 if (!command_args->GetString(kPatch, &patch_rel_path) ||
170 !command_args->GetString(kInput, &input_rel_path))
171 return ComponentUnpacker::kDeltaBadCommands;
173 if (!installer->GetInstalledFile(input_rel_path, &input_abs_path_))
174 return ComponentUnpacker::kDeltaMissingExistingFile;
176 patch_abs_path_ = input_dir.Append(
177 base::FilePath::FromUTF8Unsafe(patch_rel_path));
179 return ComponentUnpacker::kNone;
182 ComponentUnpacker::Error DeltaUpdateOpPatchBsdiff::DoRun(
183 ComponentPatcher* patcher,
184 int* error) {
185 *error = 0;
186 return patcher->Patch(ComponentPatcher::kPatchTypeBsdiff,
187 input_abs_path_,
188 patch_abs_path_,
189 output_abs_path_,
190 error);
193 DeltaUpdateOpPatchCourgette::DeltaUpdateOpPatchCourgette() {}
195 ComponentUnpacker::Error DeltaUpdateOpPatchCourgette::DoParseArguments(
196 base::DictionaryValue* command_args,
197 const base::FilePath& input_dir,
198 ComponentInstaller* installer) {
199 std::string patch_rel_path;
200 std::string input_rel_path;
201 if (!command_args->GetString(kPatch, &patch_rel_path) ||
202 !command_args->GetString(kInput, &input_rel_path))
203 return ComponentUnpacker::kDeltaBadCommands;
205 if (!installer->GetInstalledFile(input_rel_path, &input_abs_path_))
206 return ComponentUnpacker::kDeltaMissingExistingFile;
208 patch_abs_path_ = input_dir.Append(
209 base::FilePath::FromUTF8Unsafe(patch_rel_path));
211 return ComponentUnpacker::kNone;
214 ComponentUnpacker::Error DeltaUpdateOpPatchCourgette::DoRun(
215 ComponentPatcher* patcher,
216 int* error) {
217 *error = 0;
218 return patcher->Patch(ComponentPatcher::kPatchTypeCourgette,
219 input_abs_path_,
220 patch_abs_path_,
221 output_abs_path_,
222 error);
225 } // namespace component_updater