Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(718)

Side by Side Diff: extensions/browser/sandboxed_unpacker.cc

Issue 864093002: Move sandboxed_unpacker.{h,cc} from chrome/ to extensions/ (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix compile errors Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/extensions/sandboxed_unpacker.h" 5 #include "extensions/browser/sandboxed_unpacker.h"
6 6
7 #include <set> 7 #include <set>
8 8
9 #include "base/base64.h" 9 #include "base/base64.h"
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/command_line.h" 11 #include "base/command_line.h"
12 #include "base/files/file_util.h" 12 #include "base/files/file_util.h"
13 #include "base/files/file_util_proxy.h" 13 #include "base/files/file_util_proxy.h"
14 #include "base/files/scoped_file.h" 14 #include "base/files/scoped_file.h"
15 #include "base/json/json_string_value_serializer.h" 15 #include "base/json/json_string_value_serializer.h"
16 #include "base/message_loop/message_loop.h" 16 #include "base/message_loop/message_loop.h"
17 #include "base/metrics/histogram.h" 17 #include "base/metrics/histogram.h"
18 #include "base/numerics/safe_conversions.h" 18 #include "base/numerics/safe_conversions.h"
19 #include "base/path_service.h" 19 #include "base/path_service.h"
20 #include "base/sequenced_task_runner.h" 20 #include "base/sequenced_task_runner.h"
21 #include "base/strings/utf_string_conversions.h" 21 #include "base/strings/utf_string_conversions.h"
22 #include "base/threading/sequenced_worker_pool.h" 22 #include "base/threading/sequenced_worker_pool.h"
23 #include "chrome/browser/extensions/extension_service.h"
24 #include "chrome/common/chrome_paths.h"
25 #include "chrome/common/chrome_switches.h"
26 #include "chrome/common/chrome_utility_messages.h"
27 #include "chrome/common/extensions/chrome_utility_extensions_messages.h"
28 #include "chrome/grit/generated_resources.h"
29 #include "components/crx_file/constants.h" 23 #include "components/crx_file/constants.h"
30 #include "components/crx_file/crx_file.h" 24 #include "components/crx_file/crx_file.h"
31 #include "components/crx_file/id_util.h" 25 #include "components/crx_file/id_util.h"
32 #include "content/public/browser/browser_thread.h" 26 #include "content/public/browser/browser_thread.h"
33 #include "content/public/browser/utility_process_host.h" 27 #include "content/public/browser/utility_process_host.h"
34 #include "content/public/common/common_param_traits.h" 28 #include "content/public/common/common_param_traits.h"
35 #include "crypto/signature_verifier.h" 29 #include "crypto/signature_verifier.h"
36 #include "extensions/common/constants.h" 30 #include "extensions/common/constants.h"
37 #include "extensions/common/extension.h" 31 #include "extensions/common/extension.h"
38 #include "extensions/common/extension_l10n_util.h" 32 #include "extensions/common/extension_l10n_util.h"
39 #include "extensions/common/extension_utility_messages.h" 33 #include "extensions/common/extension_utility_messages.h"
40 #include "extensions/common/extensions_client.h" 34 #include "extensions/common/extensions_client.h"
41 #include "extensions/common/file_util.h" 35 #include "extensions/common/file_util.h"
42 #include "extensions/common/manifest_constants.h" 36 #include "extensions/common/manifest_constants.h"
43 #include "extensions/common/manifest_handlers/icons_handler.h" 37 #include "extensions/common/manifest_handlers/icons_handler.h"
38 #include "grit/extensions_strings.h"
44 #include "third_party/skia/include/core/SkBitmap.h" 39 #include "third_party/skia/include/core/SkBitmap.h"
45 #include "ui/base/l10n/l10n_util.h" 40 #include "ui/base/l10n/l10n_util.h"
46 #include "ui/gfx/codec/png_codec.h" 41 #include "ui/gfx/codec/png_codec.h"
47 42
48 using base::ASCIIToUTF16; 43 using base::ASCIIToUTF16;
49 using content::BrowserThread; 44 using content::BrowserThread;
50 using content::UtilityProcessHost; 45 using content::UtilityProcessHost;
51 using crx_file::CrxFile; 46 using crx_file::CrxFile;
52 47
53 // The following macro makes histograms that record the length of paths 48 // The following macro makes histograms that record the length of paths
54 // in this file much easier to read. 49 // in this file much easier to read.
55 // Windows has a short max path length. If the path length to a 50 // Windows has a short max path length. If the path length to a
56 // file being unpacked from a CRX exceeds the max length, we might 51 // file being unpacked from a CRX exceeds the max length, we might
57 // fail to install. To see if this is happening, see how long the 52 // fail to install. To see if this is happening, see how long the
58 // path to the temp unpack directory is. See crbug.com/69693 . 53 // path to the temp unpack directory is. See crbug.com/69693 .
59 #define PATH_LENGTH_HISTOGRAM(name, path) \ 54 #define PATH_LENGTH_HISTOGRAM(name, path) \
60 UMA_HISTOGRAM_CUSTOM_COUNTS(name, path.value().length(), 0, 500, 100) 55 UMA_HISTOGRAM_CUSTOM_COUNTS(name, path.value().length(), 0, 500, 100)
61 56
62 // Record a rate (kB per second) at which extensions are unpacked. 57 // Record a rate (kB per second) at which extensions are unpacked.
63 // Range from 1kB/s to 100mB/s. 58 // Range from 1kB/s to 100mB/s.
64 #define UNPACK_RATE_HISTOGRAM(name, rate) \ 59 #define UNPACK_RATE_HISTOGRAM(name, rate) \
65 UMA_HISTOGRAM_CUSTOM_COUNTS(name, rate, 1, 100000, 100); 60 UMA_HISTOGRAM_CUSTOM_COUNTS(name, rate, 1, 100000, 100);
66 61
67 namespace extensions { 62 namespace extensions {
68 namespace { 63 namespace {
69 64
70 void RecordSuccessfulUnpackTimeHistograms( 65 void RecordSuccessfulUnpackTimeHistograms(const base::FilePath& crx_path,
71 const base::FilePath& crx_path, const base::TimeDelta unpack_time) { 66 const base::TimeDelta unpack_time) {
72
73 const int64 kBytesPerKb = 1024; 67 const int64 kBytesPerKb = 1024;
74 const int64 kBytesPerMb = 1024 * 1024; 68 const int64 kBytesPerMb = 1024 * 1024;
75 69
76 UMA_HISTOGRAM_TIMES("Extensions.SandboxUnpackSuccessTime", unpack_time); 70 UMA_HISTOGRAM_TIMES("Extensions.SandboxUnpackSuccessTime", unpack_time);
77 71
78 // To get a sense of how CRX size impacts unpack time, record unpack 72 // To get a sense of how CRX size impacts unpack time, record unpack
79 // time for several increments of CRX size. 73 // time for several increments of CRX size.
80 int64 crx_file_size; 74 int64 crx_file_size;
81 if (!base::GetFileSize(crx_path, &crx_file_size)) { 75 if (!base::GetFileSize(crx_path, &crx_file_size)) {
82 UMA_HISTOGRAM_COUNTS("Extensions.SandboxUnpackSuccessCantGetCrxSize", 1); 76 UMA_HISTOGRAM_COUNTS("Extensions.SandboxUnpackSuccessCantGetCrxSize", 1);
83 return; 77 return;
84 } 78 }
85 79
86 // Cast is safe as long as the number of bytes in the CRX is less than 80 // Cast is safe as long as the number of bytes in the CRX is less than
87 // 2^31 * 2^10. 81 // 2^31 * 2^10.
88 int crx_file_size_kb = static_cast<int>(crx_file_size / kBytesPerKb); 82 int crx_file_size_kb = static_cast<int>(crx_file_size / kBytesPerKb);
89 UMA_HISTOGRAM_COUNTS( 83 UMA_HISTOGRAM_COUNTS("Extensions.SandboxUnpackSuccessCrxSize",
90 "Extensions.SandboxUnpackSuccessCrxSize", crx_file_size_kb); 84 crx_file_size_kb);
91 85
92 // We have time in seconds and file size in bytes. We want the rate bytes are 86 // We have time in seconds and file size in bytes. We want the rate bytes are
93 // unpacked in kB/s. 87 // unpacked in kB/s.
94 double file_size_kb = 88 double file_size_kb =
95 static_cast<double>(crx_file_size) / static_cast<double>(kBytesPerKb); 89 static_cast<double>(crx_file_size) / static_cast<double>(kBytesPerKb);
96 int unpack_rate_kb_per_s = 90 int unpack_rate_kb_per_s =
97 static_cast<int>(file_size_kb / unpack_time.InSecondsF()); 91 static_cast<int>(file_size_kb / unpack_time.InSecondsF());
98 UNPACK_RATE_HISTOGRAM("Extensions.SandboxUnpackRate", unpack_rate_kb_per_s); 92 UNPACK_RATE_HISTOGRAM("Extensions.SandboxUnpackRate", unpack_rate_kb_per_s);
99 93
100 if (crx_file_size < 50.0 * kBytesPerKb) { 94 if (crx_file_size < 50.0 * kBytesPerKb) {
101 UNPACK_RATE_HISTOGRAM( 95 UNPACK_RATE_HISTOGRAM("Extensions.SandboxUnpackRateUnder50kB",
102 "Extensions.SandboxUnpackRateUnder50kB", unpack_rate_kb_per_s); 96 unpack_rate_kb_per_s);
103 97
104 } else if (crx_file_size < 1 * kBytesPerMb) { 98 } else if (crx_file_size < 1 * kBytesPerMb) {
105 UNPACK_RATE_HISTOGRAM( 99 UNPACK_RATE_HISTOGRAM("Extensions.SandboxUnpackRate50kBTo1mB",
106 "Extensions.SandboxUnpackRate50kBTo1mB", unpack_rate_kb_per_s); 100 unpack_rate_kb_per_s);
107 101
108 } else if (crx_file_size < 2 * kBytesPerMb) { 102 } else if (crx_file_size < 2 * kBytesPerMb) {
109 UNPACK_RATE_HISTOGRAM( 103 UNPACK_RATE_HISTOGRAM("Extensions.SandboxUnpackRate1To2mB",
110 "Extensions.SandboxUnpackRate1To2mB", unpack_rate_kb_per_s); 104 unpack_rate_kb_per_s);
111 105
112 } else if (crx_file_size < 5 * kBytesPerMb) { 106 } else if (crx_file_size < 5 * kBytesPerMb) {
113 UNPACK_RATE_HISTOGRAM( 107 UNPACK_RATE_HISTOGRAM("Extensions.SandboxUnpackRate2To5mB",
114 "Extensions.SandboxUnpackRate2To5mB", unpack_rate_kb_per_s); 108 unpack_rate_kb_per_s);
115 109
116 } else if (crx_file_size < 10 * kBytesPerMb) { 110 } else if (crx_file_size < 10 * kBytesPerMb) {
117 UNPACK_RATE_HISTOGRAM( 111 UNPACK_RATE_HISTOGRAM("Extensions.SandboxUnpackRate5To10mB",
118 "Extensions.SandboxUnpackRate5To10mB", unpack_rate_kb_per_s); 112 unpack_rate_kb_per_s);
119 113
120 } else { 114 } else {
121 UNPACK_RATE_HISTOGRAM( 115 UNPACK_RATE_HISTOGRAM("Extensions.SandboxUnpackRateOver10mB",
122 "Extensions.SandboxUnpackRateOver10mB", unpack_rate_kb_per_s); 116 unpack_rate_kb_per_s);
123 } 117 }
124 } 118 }
125 119
126 // Work horse for FindWritableTempLocation. Creates a temp file in the folder 120 // Work horse for FindWritableTempLocation. Creates a temp file in the folder
127 // and uses NormalizeFilePath to check if the path is junction free. 121 // and uses NormalizeFilePath to check if the path is junction free.
128 bool VerifyJunctionFreeLocation(base::FilePath* temp_dir) { 122 bool VerifyJunctionFreeLocation(base::FilePath* temp_dir) {
129 if (temp_dir->empty()) 123 if (temp_dir->empty())
130 return false; 124 return false;
131 125
132 base::FilePath temp_file; 126 base::FilePath temp_file;
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
179 LOG(ERROR) << "Both the %TEMP% folder and the profile seem to be on " 173 LOG(ERROR) << "Both the %TEMP% folder and the profile seem to be on "
180 << "remote drives or read-only. Installation can not complete!"; 174 << "remote drives or read-only. Installation can not complete!";
181 return false; 175 return false;
182 } 176 }
183 177
184 // Read the decoded images back from the file we saved them to. 178 // Read the decoded images back from the file we saved them to.
185 // |extension_path| is the path to the extension we unpacked that wrote the 179 // |extension_path| is the path to the extension we unpacked that wrote the
186 // data. Returns true on success. 180 // data. Returns true on success.
187 bool ReadImagesFromFile(const base::FilePath& extension_path, 181 bool ReadImagesFromFile(const base::FilePath& extension_path,
188 DecodedImages* images) { 182 DecodedImages* images) {
189 base::FilePath path = 183 base::FilePath path = extension_path.AppendASCII(kDecodedImagesFilename);
190 extension_path.AppendASCII(kDecodedImagesFilename);
191 std::string file_str; 184 std::string file_str;
192 if (!base::ReadFileToString(path, &file_str)) 185 if (!base::ReadFileToString(path, &file_str))
193 return false; 186 return false;
194 187
195 IPC::Message pickle(file_str.data(), file_str.size()); 188 IPC::Message pickle(file_str.data(), file_str.size());
196 PickleIterator iter(pickle); 189 PickleIterator iter(pickle);
197 return IPC::ReadParam(&pickle, &iter, images); 190 return IPC::ReadParam(&pickle, &iter, images);
198 } 191 }
199 192
200 // Read the decoded message catalogs back from the file we saved them to. 193 // Read the decoded message catalogs back from the file we saved them to.
201 // |extension_path| is the path to the extension we unpacked that wrote the 194 // |extension_path| is the path to the extension we unpacked that wrote the
202 // data. Returns true on success. 195 // data. Returns true on success.
203 bool ReadMessageCatalogsFromFile(const base::FilePath& extension_path, 196 bool ReadMessageCatalogsFromFile(const base::FilePath& extension_path,
204 base::DictionaryValue* catalogs) { 197 base::DictionaryValue* catalogs) {
205 base::FilePath path = extension_path.AppendASCII( 198 base::FilePath path =
206 kDecodedMessageCatalogsFilename); 199 extension_path.AppendASCII(kDecodedMessageCatalogsFilename);
207 std::string file_str; 200 std::string file_str;
208 if (!base::ReadFileToString(path, &file_str)) 201 if (!base::ReadFileToString(path, &file_str))
209 return false; 202 return false;
210 203
211 IPC::Message pickle(file_str.data(), file_str.size()); 204 IPC::Message pickle(file_str.data(), file_str.size());
212 PickleIterator iter(pickle); 205 PickleIterator iter(pickle);
213 return IPC::ReadParam(&pickle, &iter, catalogs); 206 return IPC::ReadParam(&pickle, &iter, catalogs);
214 } 207 }
215 208
216 } // namespace 209 } // namespace
(...skipping 12 matching lines...) Expand all
229 location_(location), 222 location_(location),
230 creation_flags_(creation_flags), 223 creation_flags_(creation_flags),
231 unpacker_io_task_runner_(unpacker_io_task_runner) { 224 unpacker_io_task_runner_(unpacker_io_task_runner) {
232 } 225 }
233 226
234 bool SandboxedUnpacker::CreateTempDirectory() { 227 bool SandboxedUnpacker::CreateTempDirectory() {
235 CHECK(unpacker_io_task_runner_->RunsTasksOnCurrentThread()); 228 CHECK(unpacker_io_task_runner_->RunsTasksOnCurrentThread());
236 229
237 base::FilePath temp_dir; 230 base::FilePath temp_dir;
238 if (!FindWritableTempLocation(extensions_dir_, &temp_dir)) { 231 if (!FindWritableTempLocation(extensions_dir_, &temp_dir)) {
239 ReportFailure( 232 ReportFailure(COULD_NOT_GET_TEMP_DIRECTORY,
240 COULD_NOT_GET_TEMP_DIRECTORY, 233 l10n_util::GetStringFUTF16(
241 l10n_util::GetStringFUTF16( 234 IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
242 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 235 ASCIIToUTF16("COULD_NOT_GET_TEMP_DIRECTORY")));
243 ASCIIToUTF16("COULD_NOT_GET_TEMP_DIRECTORY")));
244 return false; 236 return false;
245 } 237 }
246 238
247 if (!temp_dir_.CreateUniqueTempDirUnderPath(temp_dir)) { 239 if (!temp_dir_.CreateUniqueTempDirUnderPath(temp_dir)) {
248 ReportFailure( 240 ReportFailure(COULD_NOT_CREATE_TEMP_DIRECTORY,
249 COULD_NOT_CREATE_TEMP_DIRECTORY, 241 l10n_util::GetStringFUTF16(
250 l10n_util::GetStringFUTF16( 242 IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
251 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 243 ASCIIToUTF16("COULD_NOT_CREATE_TEMP_DIRECTORY")));
252 ASCIIToUTF16("COULD_NOT_CREATE_TEMP_DIRECTORY")));
253 return false; 244 return false;
254 } 245 }
255 246
256 return true; 247 return true;
257 } 248 }
258 249
259 void SandboxedUnpacker::Start() { 250 void SandboxedUnpacker::Start() {
260 // We assume that we are started on the thread that the client wants us to do 251 // We assume that we are started on the thread that the client wants us to do
261 // file IO on. 252 // file IO on.
262 CHECK(unpacker_io_task_runner_->RunsTasksOnCurrentThread()); 253 CHECK(unpacker_io_task_runner_->RunsTasksOnCurrentThread());
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
294 285
295 // The utility process will have access to the directory passed to 286 // The utility process will have access to the directory passed to
296 // SandboxedUnpacker. That directory should not contain a symlink or NTFS 287 // SandboxedUnpacker. That directory should not contain a symlink or NTFS
297 // reparse point. When the path is used, following the link/reparse point 288 // reparse point. When the path is used, following the link/reparse point
298 // will cause file system access outside the sandbox path, and the sandbox 289 // will cause file system access outside the sandbox path, and the sandbox
299 // will deny the operation. 290 // will deny the operation.
300 base::FilePath link_free_crx_path; 291 base::FilePath link_free_crx_path;
301 if (!base::NormalizeFilePath(temp_crx_path, &link_free_crx_path)) { 292 if (!base::NormalizeFilePath(temp_crx_path, &link_free_crx_path)) {
302 LOG(ERROR) << "Could not get the normalized path of " 293 LOG(ERROR) << "Could not get the normalized path of "
303 << temp_crx_path.value(); 294 << temp_crx_path.value();
304 ReportFailure( 295 ReportFailure(COULD_NOT_GET_SANDBOX_FRIENDLY_PATH,
305 COULD_NOT_GET_SANDBOX_FRIENDLY_PATH, 296 l10n_util::GetStringUTF16(IDS_EXTENSION_UNPACK_FAILED));
306 l10n_util::GetStringUTF16(IDS_EXTENSION_UNPACK_FAILED));
307 return; 297 return;
308 } 298 }
309 PATH_LENGTH_HISTOGRAM("Extensions.SandboxUnpackLinkFreeCrxPathLength", 299 PATH_LENGTH_HISTOGRAM("Extensions.SandboxUnpackLinkFreeCrxPathLength",
310 link_free_crx_path); 300 link_free_crx_path);
311 301
312 BrowserThread::PostTask( 302 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
313 BrowserThread::IO, FROM_HERE, 303 base::Bind(&SandboxedUnpacker::StartProcessOnIOThread,
314 base::Bind( 304 this, link_free_crx_path));
315 &SandboxedUnpacker::StartProcessOnIOThread,
316 this,
317 link_free_crx_path));
318 } 305 }
319 306
320 SandboxedUnpacker::~SandboxedUnpacker() { 307 SandboxedUnpacker::~SandboxedUnpacker() {
321 } 308 }
322 309
323 bool SandboxedUnpacker::OnMessageReceived(const IPC::Message& message) { 310 bool SandboxedUnpacker::OnMessageReceived(const IPC::Message& message) {
324 bool handled = true; 311 bool handled = true;
325 IPC_BEGIN_MESSAGE_MAP(SandboxedUnpacker, message) 312 IPC_BEGIN_MESSAGE_MAP(SandboxedUnpacker, message)
326 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_UnpackExtension_Succeeded, 313 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_UnpackExtension_Succeeded,
327 OnUnpackExtensionSucceeded) 314 OnUnpackExtensionSucceeded)
328 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_UnpackExtension_Failed, 315 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_UnpackExtension_Failed,
329 OnUnpackExtensionFailed) 316 OnUnpackExtensionFailed)
330 IPC_MESSAGE_UNHANDLED(handled = false) 317 IPC_MESSAGE_UNHANDLED(handled = false)
331 IPC_END_MESSAGE_MAP() 318 IPC_END_MESSAGE_MAP()
332 return handled; 319 return handled;
333 } 320 }
334 321
335 void SandboxedUnpacker::OnProcessCrashed(int exit_code) { 322 void SandboxedUnpacker::OnProcessCrashed(int exit_code) {
336 // Don't report crashes if they happen after we got a response. 323 // Don't report crashes if they happen after we got a response.
337 if (got_response_) 324 if (got_response_)
338 return; 325 return;
339 326
340 // Utility process crashed while trying to install. 327 // Utility process crashed while trying to install.
341 ReportFailure( 328 ReportFailure(
342 UTILITY_PROCESS_CRASHED_WHILE_TRYING_TO_INSTALL, 329 UTILITY_PROCESS_CRASHED_WHILE_TRYING_TO_INSTALL,
343 l10n_util::GetStringFUTF16( 330 l10n_util::GetStringFUTF16(
344 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 331 IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
345 ASCIIToUTF16("UTILITY_PROCESS_CRASHED_WHILE_TRYING_TO_INSTALL")) + 332 ASCIIToUTF16("UTILITY_PROCESS_CRASHED_WHILE_TRYING_TO_INSTALL")) +
346 ASCIIToUTF16(". ") + 333 ASCIIToUTF16(". ") +
347 l10n_util::GetStringUTF16(IDS_EXTENSION_INSTALL_PROCESS_CRASHED)); 334 l10n_util::GetStringUTF16(IDS_EXTENSION_INSTALL_PROCESS_CRASHED));
348 } 335 }
349 336
350 void SandboxedUnpacker::StartProcessOnIOThread( 337 void SandboxedUnpacker::StartProcessOnIOThread(
351 const base::FilePath& temp_crx_path) { 338 const base::FilePath& temp_crx_path) {
352 UtilityProcessHost* host = 339 UtilityProcessHost* host =
353 UtilityProcessHost::Create(this, unpacker_io_task_runner_.get()); 340 UtilityProcessHost::Create(this, unpacker_io_task_runner_.get());
354 // Grant the subprocess access to the entire subdir the extension file is 341 // Grant the subprocess access to the entire subdir the extension file is
355 // in, so that it can unpack to that dir. 342 // in, so that it can unpack to that dir.
356 host->SetExposedDir(temp_crx_path.DirName()); 343 host->SetExposedDir(temp_crx_path.DirName());
357 host->Send( 344 host->Send(new ChromeUtilityMsg_UnpackExtension(temp_crx_path, extension_id_,
358 new ChromeUtilityMsg_UnpackExtension( 345 location_, creation_flags_));
359 temp_crx_path, extension_id_, location_, creation_flags_));
360 } 346 }
361 347
362 void SandboxedUnpacker::OnUnpackExtensionSucceeded( 348 void SandboxedUnpacker::OnUnpackExtensionSucceeded(
363 const base::DictionaryValue& manifest) { 349 const base::DictionaryValue& manifest) {
364 CHECK(unpacker_io_task_runner_->RunsTasksOnCurrentThread()); 350 CHECK(unpacker_io_task_runner_->RunsTasksOnCurrentThread());
365 got_response_ = true; 351 got_response_ = true;
366 352
367 scoped_ptr<base::DictionaryValue> final_manifest( 353 scoped_ptr<base::DictionaryValue> final_manifest(
368 RewriteManifestFile(manifest)); 354 RewriteManifestFile(manifest));
369 if (!final_manifest) 355 if (!final_manifest)
370 return; 356 return;
371 357
372 // Create an extension object that refers to the temporary location the 358 // Create an extension object that refers to the temporary location the
373 // extension was unpacked to. We use this until the extension is finally 359 // extension was unpacked to. We use this until the extension is finally
374 // installed. For example, the install UI shows images from inside the 360 // installed. For example, the install UI shows images from inside the
375 // extension. 361 // extension.
376 362
377 // Localize manifest now, so confirm UI gets correct extension name. 363 // Localize manifest now, so confirm UI gets correct extension name.
378 364
379 // TODO(rdevlin.cronin): Continue removing std::string errors and replacing 365 // TODO(rdevlin.cronin): Continue removing std::string errors and replacing
380 // with base::string16 366 // with base::string16
381 std::string utf8_error; 367 std::string utf8_error;
382 if (!extension_l10n_util::LocalizeExtension(extension_root_, 368 if (!extension_l10n_util::LocalizeExtension(
383 final_manifest.get(), 369 extension_root_, final_manifest.get(), &utf8_error)) {
384 &utf8_error)) {
385 ReportFailure( 370 ReportFailure(
386 COULD_NOT_LOCALIZE_EXTENSION, 371 COULD_NOT_LOCALIZE_EXTENSION,
387 l10n_util::GetStringFUTF16( 372 l10n_util::GetStringFUTF16(IDS_EXTENSION_PACKAGE_ERROR_MESSAGE,
388 IDS_EXTENSION_PACKAGE_ERROR_MESSAGE, 373 base::UTF8ToUTF16(utf8_error)));
389 base::UTF8ToUTF16(utf8_error)));
390 return; 374 return;
391 } 375 }
392 376
393 extension_ = Extension::Create( 377 extension_ =
394 extension_root_, 378 Extension::Create(extension_root_, location_, *final_manifest,
395 location_, 379 Extension::REQUIRE_KEY | creation_flags_, &utf8_error);
396 *final_manifest,
397 Extension::REQUIRE_KEY | creation_flags_,
398 &utf8_error);
399 380
400 if (!extension_.get()) { 381 if (!extension_.get()) {
401 ReportFailure(INVALID_MANIFEST, 382 ReportFailure(INVALID_MANIFEST,
402 ASCIIToUTF16("Manifest is invalid: " + utf8_error)); 383 ASCIIToUTF16("Manifest is invalid: " + utf8_error));
403 return; 384 return;
404 } 385 }
405 386
406 SkBitmap install_icon; 387 SkBitmap install_icon;
407 if (!RewriteImageFiles(&install_icon)) 388 if (!RewriteImageFiles(&install_icon))
408 return; 389 return;
409 390
410 if (!RewriteCatalogFiles()) 391 if (!RewriteCatalogFiles())
411 return; 392 return;
412 393
413 ReportSuccess(manifest, install_icon); 394 ReportSuccess(manifest, install_icon);
414 } 395 }
415 396
416 void SandboxedUnpacker::OnUnpackExtensionFailed(const base::string16& error) { 397 void SandboxedUnpacker::OnUnpackExtensionFailed(const base::string16& error) {
417 CHECK(unpacker_io_task_runner_->RunsTasksOnCurrentThread()); 398 CHECK(unpacker_io_task_runner_->RunsTasksOnCurrentThread());
418 got_response_ = true; 399 got_response_ = true;
419 ReportFailure( 400 ReportFailure(
420 UNPACKER_CLIENT_FAILED, 401 UNPACKER_CLIENT_FAILED,
421 l10n_util::GetStringFUTF16( 402 l10n_util::GetStringFUTF16(IDS_EXTENSION_PACKAGE_ERROR_MESSAGE, error));
422 IDS_EXTENSION_PACKAGE_ERROR_MESSAGE,
423 error));
424 } 403 }
425 404
426 bool SandboxedUnpacker::ValidateSignature() { 405 bool SandboxedUnpacker::ValidateSignature() {
427 base::ScopedFILE file(base::OpenFile(crx_path_, "rb")); 406 base::ScopedFILE file(base::OpenFile(crx_path_, "rb"));
428 407
429 if (!file.get()) { 408 if (!file.get()) {
430 // Could not open crx file for reading. 409 // Could not open crx file for reading.
431 #if defined (OS_WIN) 410 #if defined(OS_WIN)
432 // On windows, get the error code. 411 // On windows, get the error code.
433 uint32 error_code = ::GetLastError(); 412 uint32 error_code = ::GetLastError();
434 // TODO(skerner): Use this histogram to understand why so many 413 // TODO(skerner): Use this histogram to understand why so many
435 // windows users hit this error. crbug.com/69693 414 // windows users hit this error. crbug.com/69693
436 415
437 // Windows errors are unit32s, but all of likely errors are in 416 // Windows errors are unit32s, but all of likely errors are in
438 // [1, 1000]. See winerror.h for the meaning of specific values. 417 // [1, 1000]. See winerror.h for the meaning of specific values.
439 // Clip errors outside the expected range to a single extra value. 418 // Clip errors outside the expected range to a single extra value.
440 // If there are errors in that extra bucket, we will know to expand 419 // If there are errors in that extra bucket, we will know to expand
441 // the range. 420 // the range.
442 const uint32 kMaxErrorToSend = 1001; 421 const uint32 kMaxErrorToSend = 1001;
443 error_code = std::min(error_code, kMaxErrorToSend); 422 error_code = std::min(error_code, kMaxErrorToSend);
444 UMA_HISTOGRAM_ENUMERATION("Extensions.ErrorCodeFromCrxOpen", 423 UMA_HISTOGRAM_ENUMERATION("Extensions.ErrorCodeFromCrxOpen", error_code,
445 error_code, kMaxErrorToSend); 424 kMaxErrorToSend);
446 #endif 425 #endif
447 426
448 ReportFailure( 427 ReportFailure(
449 CRX_FILE_NOT_READABLE, 428 CRX_FILE_NOT_READABLE,
450 l10n_util::GetStringFUTF16( 429 l10n_util::GetStringFUTF16(IDS_EXTENSION_PACKAGE_ERROR_CODE,
451 IDS_EXTENSION_PACKAGE_ERROR_CODE, 430 ASCIIToUTF16("CRX_FILE_NOT_READABLE")));
452 ASCIIToUTF16("CRX_FILE_NOT_READABLE")));
453 return false; 431 return false;
454 } 432 }
455 433
456 // Read and verify the header. 434 // Read and verify the header.
457 // TODO(erikkay): Yuck. I'm not a big fan of this kind of code, but it 435 // TODO(erikkay): Yuck. I'm not a big fan of this kind of code, but it
458 // appears that we don't have any endian/alignment aware serialization 436 // appears that we don't have any endian/alignment aware serialization
459 // code in the code base. So for now, this assumes that we're running 437 // code in the code base. So for now, this assumes that we're running
460 // on a little endian machine with 4 byte alignment. 438 // on a little endian machine with 4 byte alignment.
461 CrxFile::Header header; 439 CrxFile::Header header;
462 size_t len = fread(&header, 1, sizeof(header), file.get()); 440 size_t len = fread(&header, 1, sizeof(header), file.get());
463 if (len < sizeof(header)) { 441 if (len < sizeof(header)) {
464 // Invalid crx header 442 // Invalid crx header
465 ReportFailure( 443 ReportFailure(CRX_HEADER_INVALID, l10n_util::GetStringFUTF16(
466 CRX_HEADER_INVALID, 444 IDS_EXTENSION_PACKAGE_ERROR_CODE,
467 l10n_util::GetStringFUTF16( 445 ASCIIToUTF16("CRX_HEADER_INVALID")));
468 IDS_EXTENSION_PACKAGE_ERROR_CODE,
469 ASCIIToUTF16("CRX_HEADER_INVALID")));
470 return false; 446 return false;
471 } 447 }
472 448
473 CrxFile::Error error; 449 CrxFile::Error error;
474 scoped_ptr<CrxFile> crx(CrxFile::Parse(header, &error)); 450 scoped_ptr<CrxFile> crx(CrxFile::Parse(header, &error));
475 if (!crx) { 451 if (!crx) {
476 switch (error) { 452 switch (error) {
477 case CrxFile::kWrongMagic: 453 case CrxFile::kWrongMagic:
478 ReportFailure( 454 ReportFailure(CRX_MAGIC_NUMBER_INVALID,
479 CRX_MAGIC_NUMBER_INVALID, 455 l10n_util::GetStringFUTF16(
480 l10n_util::GetStringFUTF16( 456 IDS_EXTENSION_PACKAGE_ERROR_CODE,
481 IDS_EXTENSION_PACKAGE_ERROR_CODE, 457 ASCIIToUTF16("CRX_MAGIC_NUMBER_INVALID")));
482 ASCIIToUTF16("CRX_MAGIC_NUMBER_INVALID")));
483 break; 458 break;
484 case CrxFile::kInvalidVersion: 459 case CrxFile::kInvalidVersion:
485 // Bad version numer 460 // Bad version numer
486 ReportFailure( 461 ReportFailure(CRX_VERSION_NUMBER_INVALID,
487 CRX_VERSION_NUMBER_INVALID, 462 l10n_util::GetStringFUTF16(
488 l10n_util::GetStringFUTF16( 463 IDS_EXTENSION_PACKAGE_ERROR_CODE,
489 IDS_EXTENSION_PACKAGE_ERROR_CODE, 464 ASCIIToUTF16("CRX_VERSION_NUMBER_INVALID")));
490 ASCIIToUTF16("CRX_VERSION_NUMBER_INVALID")));
491 break; 465 break;
492 case CrxFile::kInvalidKeyTooLarge: 466 case CrxFile::kInvalidKeyTooLarge:
493 case CrxFile::kInvalidSignatureTooLarge: 467 case CrxFile::kInvalidSignatureTooLarge:
494 // Excessively large key or signature 468 // Excessively large key or signature
495 ReportFailure( 469 ReportFailure(
496 CRX_EXCESSIVELY_LARGE_KEY_OR_SIGNATURE, 470 CRX_EXCESSIVELY_LARGE_KEY_OR_SIGNATURE,
497 l10n_util::GetStringFUTF16( 471 l10n_util::GetStringFUTF16(
498 IDS_EXTENSION_PACKAGE_ERROR_CODE, 472 IDS_EXTENSION_PACKAGE_ERROR_CODE,
499 ASCIIToUTF16("CRX_EXCESSIVELY_LARGE_KEY_OR_SIGNATURE"))); 473 ASCIIToUTF16("CRX_EXCESSIVELY_LARGE_KEY_OR_SIGNATURE")));
500 break; 474 break;
501 case CrxFile::kInvalidKeyTooSmall: 475 case CrxFile::kInvalidKeyTooSmall:
502 // Key length is zero 476 // Key length is zero
503 ReportFailure( 477 ReportFailure(
504 CRX_ZERO_KEY_LENGTH, 478 CRX_ZERO_KEY_LENGTH,
505 l10n_util::GetStringFUTF16( 479 l10n_util::GetStringFUTF16(IDS_EXTENSION_PACKAGE_ERROR_CODE,
506 IDS_EXTENSION_PACKAGE_ERROR_CODE, 480 ASCIIToUTF16("CRX_ZERO_KEY_LENGTH")));
507 ASCIIToUTF16("CRX_ZERO_KEY_LENGTH")));
508 break; 481 break;
509 case CrxFile::kInvalidSignatureTooSmall: 482 case CrxFile::kInvalidSignatureTooSmall:
510 // Signature length is zero 483 // Signature length is zero
511 ReportFailure( 484 ReportFailure(CRX_ZERO_SIGNATURE_LENGTH,
512 CRX_ZERO_SIGNATURE_LENGTH, 485 l10n_util::GetStringFUTF16(
513 l10n_util::GetStringFUTF16( 486 IDS_EXTENSION_PACKAGE_ERROR_CODE,
514 IDS_EXTENSION_PACKAGE_ERROR_CODE, 487 ASCIIToUTF16("CRX_ZERO_SIGNATURE_LENGTH")));
515 ASCIIToUTF16("CRX_ZERO_SIGNATURE_LENGTH")));
516 break; 488 break;
517 } 489 }
518 return false; 490 return false;
519 } 491 }
520 492
521 std::vector<uint8> key; 493 std::vector<uint8> key;
522 key.resize(header.key_size); 494 key.resize(header.key_size);
523 len = fread(&key.front(), sizeof(uint8), header.key_size, file.get()); 495 len = fread(&key.front(), sizeof(uint8), header.key_size, file.get());
524 if (len < header.key_size) { 496 if (len < header.key_size) {
525 // Invalid public key 497 // Invalid public key
526 ReportFailure( 498 ReportFailure(
527 CRX_PUBLIC_KEY_INVALID, 499 CRX_PUBLIC_KEY_INVALID,
528 l10n_util::GetStringFUTF16( 500 l10n_util::GetStringFUTF16(IDS_EXTENSION_PACKAGE_ERROR_CODE,
529 IDS_EXTENSION_PACKAGE_ERROR_CODE, 501 ASCIIToUTF16("CRX_PUBLIC_KEY_INVALID")));
530 ASCIIToUTF16("CRX_PUBLIC_KEY_INVALID")));
531 return false; 502 return false;
532 } 503 }
533 504
534 std::vector<uint8> signature; 505 std::vector<uint8> signature;
535 signature.resize(header.signature_size); 506 signature.resize(header.signature_size);
536 len = fread(&signature.front(), sizeof(uint8), header.signature_size, 507 len = fread(&signature.front(), sizeof(uint8), header.signature_size,
537 file.get()); 508 file.get());
538 if (len < header.signature_size) { 509 if (len < header.signature_size) {
539 // Invalid signature 510 // Invalid signature
540 ReportFailure( 511 ReportFailure(
541 CRX_SIGNATURE_INVALID, 512 CRX_SIGNATURE_INVALID,
542 l10n_util::GetStringFUTF16( 513 l10n_util::GetStringFUTF16(IDS_EXTENSION_PACKAGE_ERROR_CODE,
543 IDS_EXTENSION_PACKAGE_ERROR_CODE, 514 ASCIIToUTF16("CRX_SIGNATURE_INVALID")));
544 ASCIIToUTF16("CRX_SIGNATURE_INVALID")));
545 return false; 515 return false;
546 } 516 }
547 517
548 crypto::SignatureVerifier verifier; 518 crypto::SignatureVerifier verifier;
549 if (!verifier.VerifyInit(crx_file::kSignatureAlgorithm, 519 if (!verifier.VerifyInit(
550 sizeof(crx_file::kSignatureAlgorithm), 520 crx_file::kSignatureAlgorithm, sizeof(crx_file::kSignatureAlgorithm),
551 &signature.front(), 521 &signature.front(), signature.size(), &key.front(), key.size())) {
552 signature.size(),
553 &key.front(),
554 key.size())) {
555 // Signature verification initialization failed. This is most likely 522 // Signature verification initialization failed. This is most likely
556 // caused by a public key in the wrong format (should encode algorithm). 523 // caused by a public key in the wrong format (should encode algorithm).
557 ReportFailure( 524 ReportFailure(
558 CRX_SIGNATURE_VERIFICATION_INITIALIZATION_FAILED, 525 CRX_SIGNATURE_VERIFICATION_INITIALIZATION_FAILED,
559 l10n_util::GetStringFUTF16( 526 l10n_util::GetStringFUTF16(
560 IDS_EXTENSION_PACKAGE_ERROR_CODE, 527 IDS_EXTENSION_PACKAGE_ERROR_CODE,
561 ASCIIToUTF16("CRX_SIGNATURE_VERIFICATION_INITIALIZATION_FAILED"))); 528 ASCIIToUTF16("CRX_SIGNATURE_VERIFICATION_INITIALIZATION_FAILED")));
562 return false; 529 return false;
563 } 530 }
564 531
565 unsigned char buf[1 << 12]; 532 unsigned char buf[1 << 12];
566 while ((len = fread(buf, 1, sizeof(buf), file.get())) > 0) 533 while ((len = fread(buf, 1, sizeof(buf), file.get())) > 0)
567 verifier.VerifyUpdate(buf, len); 534 verifier.VerifyUpdate(buf, len);
568 535
569 if (!verifier.VerifyFinal()) { 536 if (!verifier.VerifyFinal()) {
570 // Signature verification failed 537 // Signature verification failed
571 ReportFailure( 538 ReportFailure(CRX_SIGNATURE_VERIFICATION_FAILED,
572 CRX_SIGNATURE_VERIFICATION_FAILED, 539 l10n_util::GetStringFUTF16(
573 l10n_util::GetStringFUTF16( 540 IDS_EXTENSION_PACKAGE_ERROR_CODE,
574 IDS_EXTENSION_PACKAGE_ERROR_CODE, 541 ASCIIToUTF16("CRX_SIGNATURE_VERIFICATION_FAILED")));
575 ASCIIToUTF16("CRX_SIGNATURE_VERIFICATION_FAILED")));
576 return false; 542 return false;
577 } 543 }
578 544
579 std::string public_key = 545 std::string public_key =
580 std::string(reinterpret_cast<char*>(&key.front()), key.size()); 546 std::string(reinterpret_cast<char*>(&key.front()), key.size());
581 base::Base64Encode(public_key, &public_key_); 547 base::Base64Encode(public_key, &public_key_);
582 548
583 extension_id_ = crx_file::id_util::GenerateId(public_key); 549 extension_id_ = crx_file::id_util::GenerateId(public_key);
584 550
585 return true; 551 return true;
586 } 552 }
587 553
588 void SandboxedUnpacker::ReportFailure(FailureReason reason, 554 void SandboxedUnpacker::ReportFailure(FailureReason reason,
589 const base::string16& error) { 555 const base::string16& error) {
590 UMA_HISTOGRAM_ENUMERATION("Extensions.SandboxUnpackFailureReason", 556 UMA_HISTOGRAM_ENUMERATION("Extensions.SandboxUnpackFailureReason", reason,
591 reason, NUM_FAILURE_REASONS); 557 NUM_FAILURE_REASONS);
592 UMA_HISTOGRAM_TIMES("Extensions.SandboxUnpackFailureTime", 558 UMA_HISTOGRAM_TIMES("Extensions.SandboxUnpackFailureTime",
593 base::TimeTicks::Now() - unpack_start_time_); 559 base::TimeTicks::Now() - unpack_start_time_);
594 Cleanup(); 560 Cleanup();
595 client_->OnUnpackFailure(error); 561 client_->OnUnpackFailure(error);
596 } 562 }
597 563
598 void SandboxedUnpacker::ReportSuccess( 564 void SandboxedUnpacker::ReportSuccess(
599 const base::DictionaryValue& original_manifest, 565 const base::DictionaryValue& original_manifest,
600 const SkBitmap& install_icon) { 566 const SkBitmap& install_icon) {
601 UMA_HISTOGRAM_COUNTS("Extensions.SandboxUnpackSuccess", 1); 567 UMA_HISTOGRAM_COUNTS("Extensions.SandboxUnpackSuccess", 1);
602 568
603 RecordSuccessfulUnpackTimeHistograms( 569 RecordSuccessfulUnpackTimeHistograms(
604 crx_path_, base::TimeTicks::Now() - unpack_start_time_); 570 crx_path_, base::TimeTicks::Now() - unpack_start_time_);
605 571
606 // Client takes ownership of temporary directory and extension. 572 // Client takes ownership of temporary directory and extension.
607 client_->OnUnpackSuccess( 573 client_->OnUnpackSuccess(temp_dir_.Take(), extension_root_,
608 temp_dir_.Take(), extension_root_, &original_manifest, extension_.get(), 574 &original_manifest, extension_.get(), install_icon);
609 install_icon);
610 extension_ = NULL; 575 extension_ = NULL;
611 } 576 }
612 577
613 base::DictionaryValue* SandboxedUnpacker::RewriteManifestFile( 578 base::DictionaryValue* SandboxedUnpacker::RewriteManifestFile(
614 const base::DictionaryValue& manifest) { 579 const base::DictionaryValue& manifest) {
615 // Add the public key extracted earlier to the parsed manifest and overwrite 580 // Add the public key extracted earlier to the parsed manifest and overwrite
616 // the original manifest. We do this to ensure the manifest doesn't contain an 581 // the original manifest. We do this to ensure the manifest doesn't contain an
617 // exploitable bug that could be used to compromise the browser. 582 // exploitable bug that could be used to compromise the browser.
618 scoped_ptr<base::DictionaryValue> final_manifest(manifest.DeepCopy()); 583 scoped_ptr<base::DictionaryValue> final_manifest(manifest.DeepCopy());
619 final_manifest->SetString(manifest_keys::kPublicKey, public_key_); 584 final_manifest->SetString(manifest_keys::kPublicKey, public_key_);
620 585
621 std::string manifest_json; 586 std::string manifest_json;
622 JSONStringValueSerializer serializer(&manifest_json); 587 JSONStringValueSerializer serializer(&manifest_json);
623 serializer.set_pretty_print(true); 588 serializer.set_pretty_print(true);
624 if (!serializer.Serialize(*final_manifest)) { 589 if (!serializer.Serialize(*final_manifest)) {
625 // Error serializing manifest.json. 590 // Error serializing manifest.json.
626 ReportFailure( 591 ReportFailure(ERROR_SERIALIZING_MANIFEST_JSON,
627 ERROR_SERIALIZING_MANIFEST_JSON, 592 l10n_util::GetStringFUTF16(
628 l10n_util::GetStringFUTF16( 593 IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
629 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 594 ASCIIToUTF16("ERROR_SERIALIZING_MANIFEST_JSON")));
630 ASCIIToUTF16("ERROR_SERIALIZING_MANIFEST_JSON")));
631 return NULL; 595 return NULL;
632 } 596 }
633 597
634 base::FilePath manifest_path = 598 base::FilePath manifest_path = extension_root_.Append(kManifestFilename);
635 extension_root_.Append(kManifestFilename);
636 int size = base::checked_cast<int>(manifest_json.size()); 599 int size = base::checked_cast<int>(manifest_json.size());
637 if (base::WriteFile(manifest_path, manifest_json.data(), size) != size) { 600 if (base::WriteFile(manifest_path, manifest_json.data(), size) != size) {
638 // Error saving manifest.json. 601 // Error saving manifest.json.
639 ReportFailure( 602 ReportFailure(
640 ERROR_SAVING_MANIFEST_JSON, 603 ERROR_SAVING_MANIFEST_JSON,
641 l10n_util::GetStringFUTF16( 604 l10n_util::GetStringFUTF16(IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
642 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 605 ASCIIToUTF16("ERROR_SAVING_MANIFEST_JSON")));
643 ASCIIToUTF16("ERROR_SAVING_MANIFEST_JSON")));
644 return NULL; 606 return NULL;
645 } 607 }
646 608
647 return final_manifest.release(); 609 return final_manifest.release();
648 } 610 }
649 611
650 bool SandboxedUnpacker::RewriteImageFiles(SkBitmap* install_icon) { 612 bool SandboxedUnpacker::RewriteImageFiles(SkBitmap* install_icon) {
651 DecodedImages images; 613 DecodedImages images;
652 if (!ReadImagesFromFile(temp_dir_.path(), &images)) { 614 if (!ReadImagesFromFile(temp_dir_.path(), &images)) {
653 // Couldn't read image data from disk. 615 // Couldn't read image data from disk.
654 ReportFailure( 616 ReportFailure(COULD_NOT_READ_IMAGE_DATA_FROM_DISK,
655 COULD_NOT_READ_IMAGE_DATA_FROM_DISK, 617 l10n_util::GetStringFUTF16(
656 l10n_util::GetStringFUTF16( 618 IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
657 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 619 ASCIIToUTF16("COULD_NOT_READ_IMAGE_DATA_FROM_DISK")));
658 ASCIIToUTF16("COULD_NOT_READ_IMAGE_DATA_FROM_DISK")));
659 return false; 620 return false;
660 } 621 }
661 622
662 // Delete any images that may be used by the browser. We're going to write 623 // Delete any images that may be used by the browser. We're going to write
663 // out our own versions of the parsed images, and we want to make sure the 624 // out our own versions of the parsed images, and we want to make sure the
664 // originals are gone for good. 625 // originals are gone for good.
665 std::set<base::FilePath> image_paths = 626 std::set<base::FilePath> image_paths =
666 ExtensionsClient::Get()->GetBrowserImagePaths(extension_.get()); 627 ExtensionsClient::Get()->GetBrowserImagePaths(extension_.get());
667 if (image_paths.size() != images.size()) { 628 if (image_paths.size() != images.size()) {
668 // Decoded images don't match what's in the manifest. 629 // Decoded images don't match what's in the manifest.
669 ReportFailure( 630 ReportFailure(
670 DECODED_IMAGES_DO_NOT_MATCH_THE_MANIFEST, 631 DECODED_IMAGES_DO_NOT_MATCH_THE_MANIFEST,
671 l10n_util::GetStringFUTF16( 632 l10n_util::GetStringFUTF16(
672 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 633 IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
673 ASCIIToUTF16("DECODED_IMAGES_DO_NOT_MATCH_THE_MANIFEST"))); 634 ASCIIToUTF16("DECODED_IMAGES_DO_NOT_MATCH_THE_MANIFEST")));
674 return false; 635 return false;
675 } 636 }
676 637
677 for (std::set<base::FilePath>::iterator it = image_paths.begin(); 638 for (std::set<base::FilePath>::iterator it = image_paths.begin();
678 it != image_paths.end(); ++it) { 639 it != image_paths.end(); ++it) {
679 base::FilePath path = *it; 640 base::FilePath path = *it;
680 if (path.IsAbsolute() || path.ReferencesParent()) { 641 if (path.IsAbsolute() || path.ReferencesParent()) {
681 // Invalid path for browser image. 642 // Invalid path for browser image.
682 ReportFailure( 643 ReportFailure(INVALID_PATH_FOR_BROWSER_IMAGE,
683 INVALID_PATH_FOR_BROWSER_IMAGE, 644 l10n_util::GetStringFUTF16(
684 l10n_util::GetStringFUTF16( 645 IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
685 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 646 ASCIIToUTF16("INVALID_PATH_FOR_BROWSER_IMAGE")));
686 ASCIIToUTF16("INVALID_PATH_FOR_BROWSER_IMAGE")));
687 return false; 647 return false;
688 } 648 }
689 if (!base::DeleteFile(extension_root_.Append(path), false)) { 649 if (!base::DeleteFile(extension_root_.Append(path), false)) {
690 // Error removing old image file. 650 // Error removing old image file.
691 ReportFailure( 651 ReportFailure(ERROR_REMOVING_OLD_IMAGE_FILE,
692 ERROR_REMOVING_OLD_IMAGE_FILE, 652 l10n_util::GetStringFUTF16(
693 l10n_util::GetStringFUTF16( 653 IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
694 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 654 ASCIIToUTF16("ERROR_REMOVING_OLD_IMAGE_FILE")));
695 ASCIIToUTF16("ERROR_REMOVING_OLD_IMAGE_FILE")));
696 return false; 655 return false;
697 } 656 }
698 } 657 }
699 658
700 const std::string& install_icon_path = 659 const std::string& install_icon_path =
701 IconsInfo::GetIcons(extension_.get()).Get( 660 IconsInfo::GetIcons(extension_.get())
702 extension_misc::EXTENSION_ICON_LARGE, ExtensionIconSet::MATCH_BIGGER); 661 .Get(extension_misc::EXTENSION_ICON_LARGE,
662 ExtensionIconSet::MATCH_BIGGER);
703 663
704 // Write our parsed images back to disk as well. 664 // Write our parsed images back to disk as well.
705 for (size_t i = 0; i < images.size(); ++i) { 665 for (size_t i = 0; i < images.size(); ++i) {
706 if (BrowserThread::GetBlockingPool()->IsShutdownInProgress()) { 666 if (BrowserThread::GetBlockingPool()->IsShutdownInProgress()) {
707 // Abort package installation if shutdown was initiated, crbug.com/235525 667 // Abort package installation if shutdown was initiated, crbug.com/235525
708 ReportFailure( 668 ReportFailure(
709 ABORTED_DUE_TO_SHUTDOWN, 669 ABORTED_DUE_TO_SHUTDOWN,
710 l10n_util::GetStringFUTF16( 670 l10n_util::GetStringFUTF16(IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
711 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 671 ASCIIToUTF16("ABORTED_DUE_TO_SHUTDOWN")));
712 ASCIIToUTF16("ABORTED_DUE_TO_SHUTDOWN")));
713 return false; 672 return false;
714 } 673 }
715 674
716 const SkBitmap& image = get<0>(images[i]); 675 const SkBitmap& image = get<0>(images[i]);
717 base::FilePath path_suffix = get<1>(images[i]); 676 base::FilePath path_suffix = get<1>(images[i]);
718 if (path_suffix.MaybeAsASCII() == install_icon_path) 677 if (path_suffix.MaybeAsASCII() == install_icon_path)
719 *install_icon = image; 678 *install_icon = image;
720 679
721 if (path_suffix.IsAbsolute() || path_suffix.ReferencesParent()) { 680 if (path_suffix.IsAbsolute() || path_suffix.ReferencesParent()) {
722 // Invalid path for bitmap image. 681 // Invalid path for bitmap image.
723 ReportFailure( 682 ReportFailure(INVALID_PATH_FOR_BITMAP_IMAGE,
724 INVALID_PATH_FOR_BITMAP_IMAGE, 683 l10n_util::GetStringFUTF16(
725 l10n_util::GetStringFUTF16( 684 IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
726 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 685 ASCIIToUTF16("INVALID_PATH_FOR_BITMAP_IMAGE")));
727 ASCIIToUTF16("INVALID_PATH_FOR_BITMAP_IMAGE")));
728 return false; 686 return false;
729 } 687 }
730 base::FilePath path = extension_root_.Append(path_suffix); 688 base::FilePath path = extension_root_.Append(path_suffix);
731 689
732 std::vector<unsigned char> image_data; 690 std::vector<unsigned char> image_data;
733 // TODO(mpcomplete): It's lame that we're encoding all images as PNG, even 691 // TODO(mpcomplete): It's lame that we're encoding all images as PNG, even
734 // though they may originally be .jpg, etc. Figure something out. 692 // though they may originally be .jpg, etc. Figure something out.
735 // http://code.google.com/p/chromium/issues/detail?id=12459 693 // http://code.google.com/p/chromium/issues/detail?id=12459
736 if (!gfx::PNGCodec::EncodeBGRASkBitmap(image, false, &image_data)) { 694 if (!gfx::PNGCodec::EncodeBGRASkBitmap(image, false, &image_data)) {
737 // Error re-encoding theme image. 695 // Error re-encoding theme image.
738 ReportFailure( 696 ReportFailure(ERROR_RE_ENCODING_THEME_IMAGE,
739 ERROR_RE_ENCODING_THEME_IMAGE, 697 l10n_util::GetStringFUTF16(
740 l10n_util::GetStringFUTF16( 698 IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
741 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 699 ASCIIToUTF16("ERROR_RE_ENCODING_THEME_IMAGE")));
742 ASCIIToUTF16("ERROR_RE_ENCODING_THEME_IMAGE")));
743 return false; 700 return false;
744 } 701 }
745 702
746 // Note: we're overwriting existing files that the utility process wrote, 703 // Note: we're overwriting existing files that the utility process wrote,
747 // so we can be sure the directory exists. 704 // so we can be sure the directory exists.
748 const char* image_data_ptr = reinterpret_cast<const char*>(&image_data[0]); 705 const char* image_data_ptr = reinterpret_cast<const char*>(&image_data[0]);
749 int size = base::checked_cast<int>(image_data.size()); 706 int size = base::checked_cast<int>(image_data.size());
750 if (base::WriteFile(path, image_data_ptr, size) != size) { 707 if (base::WriteFile(path, image_data_ptr, size) != size) {
751 // Error saving theme image. 708 // Error saving theme image.
752 ReportFailure( 709 ReportFailure(
753 ERROR_SAVING_THEME_IMAGE, 710 ERROR_SAVING_THEME_IMAGE,
754 l10n_util::GetStringFUTF16( 711 l10n_util::GetStringFUTF16(IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
755 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 712 ASCIIToUTF16("ERROR_SAVING_THEME_IMAGE")));
756 ASCIIToUTF16("ERROR_SAVING_THEME_IMAGE")));
757 return false; 713 return false;
758 } 714 }
759 } 715 }
760 716
761 return true; 717 return true;
762 } 718 }
763 719
764 bool SandboxedUnpacker::RewriteCatalogFiles() { 720 bool SandboxedUnpacker::RewriteCatalogFiles() {
765 base::DictionaryValue catalogs; 721 base::DictionaryValue catalogs;
766 if (!ReadMessageCatalogsFromFile(temp_dir_.path(), &catalogs)) { 722 if (!ReadMessageCatalogsFromFile(temp_dir_.path(), &catalogs)) {
767 // Could not read catalog data from disk. 723 // Could not read catalog data from disk.
768 ReportFailure( 724 ReportFailure(COULD_NOT_READ_CATALOG_DATA_FROM_DISK,
769 COULD_NOT_READ_CATALOG_DATA_FROM_DISK, 725 l10n_util::GetStringFUTF16(
770 l10n_util::GetStringFUTF16( 726 IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
771 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 727 ASCIIToUTF16("COULD_NOT_READ_CATALOG_DATA_FROM_DISK")));
772 ASCIIToUTF16("COULD_NOT_READ_CATALOG_DATA_FROM_DISK")));
773 return false; 728 return false;
774 } 729 }
775 730
776 // Write our parsed catalogs back to disk. 731 // Write our parsed catalogs back to disk.
777 for (base::DictionaryValue::Iterator it(catalogs); 732 for (base::DictionaryValue::Iterator it(catalogs); !it.IsAtEnd();
778 !it.IsAtEnd(); it.Advance()) { 733 it.Advance()) {
779 const base::DictionaryValue* catalog = NULL; 734 const base::DictionaryValue* catalog = NULL;
780 if (!it.value().GetAsDictionary(&catalog)) { 735 if (!it.value().GetAsDictionary(&catalog)) {
781 // Invalid catalog data. 736 // Invalid catalog data.
782 ReportFailure( 737 ReportFailure(
783 INVALID_CATALOG_DATA, 738 INVALID_CATALOG_DATA,
784 l10n_util::GetStringFUTF16( 739 l10n_util::GetStringFUTF16(IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
785 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 740 ASCIIToUTF16("INVALID_CATALOG_DATA")));
786 ASCIIToUTF16("INVALID_CATALOG_DATA")));
787 return false; 741 return false;
788 } 742 }
789 743
790 base::FilePath relative_path = base::FilePath::FromUTF8Unsafe(it.key()); 744 base::FilePath relative_path = base::FilePath::FromUTF8Unsafe(it.key());
791 relative_path = relative_path.Append(kMessagesFilename); 745 relative_path = relative_path.Append(kMessagesFilename);
792 if (relative_path.IsAbsolute() || relative_path.ReferencesParent()) { 746 if (relative_path.IsAbsolute() || relative_path.ReferencesParent()) {
793 // Invalid path for catalog. 747 // Invalid path for catalog.
794 ReportFailure( 748 ReportFailure(
795 INVALID_PATH_FOR_CATALOG, 749 INVALID_PATH_FOR_CATALOG,
796 l10n_util::GetStringFUTF16( 750 l10n_util::GetStringFUTF16(IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
797 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 751 ASCIIToUTF16("INVALID_PATH_FOR_CATALOG")));
798 ASCIIToUTF16("INVALID_PATH_FOR_CATALOG")));
799 return false; 752 return false;
800 } 753 }
801 base::FilePath path = extension_root_.Append(relative_path); 754 base::FilePath path = extension_root_.Append(relative_path);
802 755
803 std::string catalog_json; 756 std::string catalog_json;
804 JSONStringValueSerializer serializer(&catalog_json); 757 JSONStringValueSerializer serializer(&catalog_json);
805 serializer.set_pretty_print(true); 758 serializer.set_pretty_print(true);
806 if (!serializer.Serialize(*catalog)) { 759 if (!serializer.Serialize(*catalog)) {
807 // Error serializing catalog. 760 // Error serializing catalog.
808 ReportFailure( 761 ReportFailure(ERROR_SERIALIZING_CATALOG,
809 ERROR_SERIALIZING_CATALOG, 762 l10n_util::GetStringFUTF16(
810 l10n_util::GetStringFUTF16( 763 IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
811 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 764 ASCIIToUTF16("ERROR_SERIALIZING_CATALOG")));
812 ASCIIToUTF16("ERROR_SERIALIZING_CATALOG")));
813 return false; 765 return false;
814 } 766 }
815 767
816 // Note: we're overwriting existing files that the utility process read, 768 // Note: we're overwriting existing files that the utility process read,
817 // so we can be sure the directory exists. 769 // so we can be sure the directory exists.
818 int size = base::checked_cast<int>(catalog_json.size()); 770 int size = base::checked_cast<int>(catalog_json.size());
819 if (base::WriteFile(path, catalog_json.c_str(), size) != size) { 771 if (base::WriteFile(path, catalog_json.c_str(), size) != size) {
820 // Error saving catalog. 772 // Error saving catalog.
821 ReportFailure( 773 ReportFailure(
822 ERROR_SAVING_CATALOG, 774 ERROR_SAVING_CATALOG,
823 l10n_util::GetStringFUTF16( 775 l10n_util::GetStringFUTF16(IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
824 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 776 ASCIIToUTF16("ERROR_SAVING_CATALOG")));
825 ASCIIToUTF16("ERROR_SAVING_CATALOG")));
826 return false; 777 return false;
827 } 778 }
828 } 779 }
829 780
830 return true; 781 return true;
831 } 782 }
832 783
833 void SandboxedUnpacker::Cleanup() { 784 void SandboxedUnpacker::Cleanup() {
834 DCHECK(unpacker_io_task_runner_->RunsTasksOnCurrentThread()); 785 DCHECK(unpacker_io_task_runner_->RunsTasksOnCurrentThread());
835 if (!temp_dir_.Delete()) { 786 if (!temp_dir_.Delete()) {
836 LOG(WARNING) << "Can not delete temp directory at " 787 LOG(WARNING) << "Can not delete temp directory at "
837 << temp_dir_.path().value(); 788 << temp_dir_.path().value();
838 } 789 }
839 } 790 }
840 791
841 } // namespace extensions 792 } // namespace extensions
OLDNEW
« no previous file with comments | « extensions/browser/sandboxed_unpacker.h ('k') | extensions/browser/sandboxed_unpacker_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698