Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / component_updater / component_patcher_operation.cc
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.
4
5 #include "chrome/browser/component_updater/component_patcher_operation.h"
6
7 #include <string>
8 #include <vector>
9
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"
24
25 using crypto::SecureHash;
26
27 namespace component_updater {
28
29 namespace {
30
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";
36
37 }  // namespace
38
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;
52 }
53
54 DeltaUpdateOp::DeltaUpdateOp() {}
55
56 DeltaUpdateOp::~DeltaUpdateOp() {}
57
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;
68
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;
75
76   const base::FilePath parent = output_abs_path_.DirName();
77   if (!base::DirectoryExists(parent)) {
78     if (!base::CreateDirectory(parent))
79       return ComponentUnpacker::kIoError;
80   }
81
82   ComponentUnpacker::Error run_result = DoRun(patcher, error);
83   if (run_result != ComponentUnpacker::kNone)
84     return run_result;
85
86   return CheckHash();
87 }
88
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;
96
97   base::MemoryMappedFile output_file_mmapped;
98   if (!output_file_mmapped.Initialize(output_abs_path_))
99     return ComponentUnpacker::kDeltaVerificationFailure;
100
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;
107
108   return ComponentUnpacker::kNone;
109 }
110
111 DeltaUpdateOpCopy::DeltaUpdateOpCopy() {}
112
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;
120
121   if (!installer->GetInstalledFile(input_rel_path, &input_abs_path_))
122     return ComponentUnpacker::kDeltaMissingExistingFile;
123
124   return ComponentUnpacker::kNone;
125 }
126
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;
132
133   return ComponentUnpacker::kNone;
134 }
135
136 DeltaUpdateOpCreate::DeltaUpdateOpCreate() {}
137
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;
145
146   patch_abs_path_ = input_dir.Append(
147       base::FilePath::FromUTF8Unsafe(patch_rel_path));
148
149   return ComponentUnpacker::kNone;
150 }
151
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;
157
158   return ComponentUnpacker::kNone;
159 }
160
161 DeltaUpdateOpPatchBsdiff::DeltaUpdateOpPatchBsdiff() {}
162
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;
172
173   if (!installer->GetInstalledFile(input_rel_path, &input_abs_path_))
174     return ComponentUnpacker::kDeltaMissingExistingFile;
175
176   patch_abs_path_ = input_dir.Append(
177       base::FilePath::FromUTF8Unsafe(patch_rel_path));
178
179   return ComponentUnpacker::kNone;
180 }
181
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);
191 }
192
193 DeltaUpdateOpPatchCourgette::DeltaUpdateOpPatchCourgette() {}
194
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;
204
205   if (!installer->GetInstalledFile(input_rel_path, &input_abs_path_))
206     return ComponentUnpacker::kDeltaMissingExistingFile;
207
208   patch_abs_path_ = input_dir.Append(
209       base::FilePath::FromUTF8Unsafe(patch_rel_path));
210
211   return ComponentUnpacker::kNone;
212 }
213
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);
223 }
224
225 }  // namespace component_updater