summaryrefslogtreecommitdiffstats
path: root/chrome/browser/extensions/sandboxed_extension_unpacker.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/extensions/sandboxed_extension_unpacker.cc')
-rw-r--r--chrome/browser/extensions/sandboxed_extension_unpacker.cc218
1 files changed, 140 insertions, 78 deletions
diff --git a/chrome/browser/extensions/sandboxed_extension_unpacker.cc b/chrome/browser/extensions/sandboxed_extension_unpacker.cc
index 160a0de..65ccded 100644
--- a/chrome/browser/extensions/sandboxed_extension_unpacker.cc
+++ b/chrome/browser/extensions/sandboxed_extension_unpacker.cc
@@ -21,7 +21,6 @@
#include "chrome/common/extensions/extension_unpacker.h"
#include "chrome/common/json_value_serializer.h"
#include "net/base/base64.h"
-
#include "third_party/skia/include/core/SkBitmap.h"
const char SandboxedExtensionUnpacker::kExtensionHeaderMagic[] = "Cr24";
@@ -83,7 +82,8 @@ void SandboxedExtensionUnpacker::Start() {
// Otherwise, unpack the extension in this process.
ExtensionUnpacker unpacker(temp_crx_path);
if (unpacker.Run() && unpacker.DumpImagesToFile())
- OnUnpackExtensionSucceeded(*unpacker.parsed_manifest());
+ OnUnpackExtensionSucceeded(*unpacker.parsed_manifest(),
+ *unpacker.parsed_catalogs());
else
OnUnpackExtensionFailed(unpacker.error_message());
}
@@ -97,38 +97,16 @@ void SandboxedExtensionUnpacker::StartProcessOnIOThread(
}
void SandboxedExtensionUnpacker::OnUnpackExtensionSucceeded(
- const DictionaryValue& manifest) {
- DCHECK(ChromeThread::CurrentlyOn(thread_identifier_));
+ const DictionaryValue& manifest,
+ const DictionaryValue& catalogs) {
+ // Skip check for unittests.
+ if (thread_identifier_ != ChromeThread::ID_COUNT)
+ DCHECK(ChromeThread::CurrentlyOn(thread_identifier_));
got_response_ = true;
- ExtensionUnpacker::DecodedImages images;
- if (!ExtensionUnpacker::ReadImagesFromFile(temp_dir_.path(), &images)) {
- ReportFailure("Couldn't read image data from disk.");
+ scoped_ptr<DictionaryValue> final_manifest(RewriteManifestFile(manifest));
+ if (!final_manifest.get())
return;
- }
-
- // Add the public key extracted earlier to the parsed manifest and overwrite
- // the original manifest. We do this to ensure the manifest doesn't contain an
- // exploitable bug that could be used to compromise the browser.
- scoped_ptr<DictionaryValue> final_manifest(
- static_cast<DictionaryValue*>(manifest.DeepCopy()));
- final_manifest->SetString(extension_manifest_keys::kPublicKey, public_key_);
-
- std::string manifest_json;
- JSONStringValueSerializer serializer(&manifest_json);
- serializer.set_pretty_print(true);
- if (!serializer.Serialize(*final_manifest)) {
- ReportFailure("Error serializing manifest.json.");
- return;
- }
-
- FilePath manifest_path =
- extension_root_.AppendASCII(Extension::kManifestFilename);
- if (!file_util::WriteFile(manifest_path,
- manifest_json.data(), manifest_json.size())) {
- ReportFailure("Error saving manifest.json.");
- return;
- }
// Create an extension object that refers to the temporary location the
// extension was unpacked to. We use this until the extension is finally
@@ -144,55 +122,11 @@ void SandboxedExtensionUnpacker::OnUnpackExtensionSucceeded(
return;
}
- // Delete any images that may be used by the browser. We're going to write
- // out our own versions of the parsed images, and we want to make sure the
- // originals are gone for good.
- std::set<FilePath> image_paths = extension_->GetBrowserImages();
- if (image_paths.size() != images.size()) {
- ReportFailure("Decoded images don't match what's in the manifest.");
+ if (!RewriteImageFiles())
return;
- }
-
- for (std::set<FilePath>::iterator it = image_paths.begin();
- it != image_paths.end(); ++it) {
- FilePath path = *it;
- if (path.IsAbsolute() || path.ReferencesParent()) {
- ReportFailure("Invalid path for browser image.");
- return;
- }
- if (!file_util::Delete(extension_root_.Append(path), false)) {
- ReportFailure("Error removing old image file.");
- return;
- }
- }
- // Write our parsed images back to disk as well.
- for (size_t i = 0; i < images.size(); ++i) {
- const SkBitmap& image = images[i].a;
- FilePath path_suffix = images[i].b;
- if (path_suffix.IsAbsolute() || path_suffix.ReferencesParent()) {
- ReportFailure("Invalid path for bitmap image.");
- return;
- }
- FilePath path = extension_root_.Append(path_suffix);
-
- std::vector<unsigned char> image_data;
- // TODO(mpcomplete): It's lame that we're encoding all images as PNG, even
- // though they may originally be .jpg, etc. Figure something out.
- // http://code.google.com/p/chromium/issues/detail?id=12459
- if (!gfx::PNGCodec::EncodeBGRASkBitmap(image, false, &image_data)) {
- ReportFailure("Error re-encoding theme image.");
- return;
- }
-
- // Note: we're overwriting existing files that the utility process wrote,
- // so we can be sure the directory exists.
- const char* image_data_ptr = reinterpret_cast<const char*>(&image_data[0]);
- if (!file_util::WriteFile(path, image_data_ptr, image_data.size())) {
- ReportFailure("Error saving theme image.");
- return;
- }
- }
+ if (!RewriteCatalogFiles(catalogs))
+ return;
ReportSuccess();
}
@@ -310,3 +244,131 @@ void SandboxedExtensionUnpacker::ReportSuccess() {
client_->OnUnpackSuccess(temp_dir_.Take(), extension_root_,
extension_.release());
}
+
+DictionaryValue* SandboxedExtensionUnpacker::RewriteManifestFile(
+ const DictionaryValue& manifest) {
+ // Add the public key extracted earlier to the parsed manifest and overwrite
+ // the original manifest. We do this to ensure the manifest doesn't contain an
+ // exploitable bug that could be used to compromise the browser.
+ scoped_ptr<DictionaryValue> final_manifest(
+ static_cast<DictionaryValue*>(manifest.DeepCopy()));
+ final_manifest->SetString(extension_manifest_keys::kPublicKey, public_key_);
+
+ std::string manifest_json;
+ JSONStringValueSerializer serializer(&manifest_json);
+ serializer.set_pretty_print(true);
+ if (!serializer.Serialize(*final_manifest)) {
+ ReportFailure("Error serializing manifest.json.");
+ return NULL;
+ }
+
+ FilePath manifest_path =
+ extension_root_.AppendASCII(Extension::kManifestFilename);
+ if (!file_util::WriteFile(manifest_path,
+ manifest_json.data(), manifest_json.size())) {
+ ReportFailure("Error saving manifest.json.");
+ return NULL;
+ }
+
+ return final_manifest.release();
+}
+
+bool SandboxedExtensionUnpacker::RewriteImageFiles() {
+ ExtensionUnpacker::DecodedImages images;
+ if (!ExtensionUnpacker::ReadImagesFromFile(temp_dir_.path(), &images)) {
+ ReportFailure("Couldn't read image data from disk.");
+ return false;
+ }
+
+ // Delete any images that may be used by the browser. We're going to write
+ // out our own versions of the parsed images, and we want to make sure the
+ // originals are gone for good.
+ std::set<FilePath> image_paths = extension_->GetBrowserImages();
+ if (image_paths.size() != images.size()) {
+ ReportFailure("Decoded images don't match what's in the manifest.");
+ return false;
+ }
+
+ for (std::set<FilePath>::iterator it = image_paths.begin();
+ it != image_paths.end(); ++it) {
+ FilePath path = *it;
+ if (path.IsAbsolute() || path.ReferencesParent()) {
+ ReportFailure("Invalid path for browser image.");
+ return false;
+ }
+ if (!file_util::Delete(extension_root_.Append(path), false)) {
+ ReportFailure("Error removing old image file.");
+ return false;
+ }
+ }
+
+ // Write our parsed images back to disk as well.
+ for (size_t i = 0; i < images.size(); ++i) {
+ const SkBitmap& image = images[i].a;
+ FilePath path_suffix = images[i].b;
+ if (path_suffix.IsAbsolute() || path_suffix.ReferencesParent()) {
+ ReportFailure("Invalid path for bitmap image.");
+ return false;
+ }
+ FilePath path = extension_root_.Append(path_suffix);
+
+ std::vector<unsigned char> image_data;
+ // TODO(mpcomplete): It's lame that we're encoding all images as PNG, even
+ // though they may originally be .jpg, etc. Figure something out.
+ // http://code.google.com/p/chromium/issues/detail?id=12459
+ if (!gfx::PNGCodec::EncodeBGRASkBitmap(image, false, &image_data)) {
+ ReportFailure("Error re-encoding theme image.");
+ return false;
+ }
+
+ // Note: we're overwriting existing files that the utility process wrote,
+ // so we can be sure the directory exists.
+ const char* image_data_ptr = reinterpret_cast<const char*>(&image_data[0]);
+ if (!file_util::WriteFile(path, image_data_ptr, image_data.size())) {
+ ReportFailure("Error saving theme image.");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool SandboxedExtensionUnpacker::RewriteCatalogFiles(
+ const DictionaryValue& catalogs) {
+ // Write our parsed catalogs back to disk.
+ DictionaryValue::key_iterator key_it = catalogs.begin_keys();
+ for (; key_it != catalogs.end_keys(); ++key_it) {
+ DictionaryValue* catalog;
+ if (!catalogs.GetDictionary(*key_it, &catalog)) {
+ ReportFailure("Invalid catalog data.");
+ return false;
+ }
+
+ FilePath relative_path = FilePath::FromWStringHack(*key_it);
+ relative_path = relative_path.AppendASCII(Extension::kMessagesFilename);
+ if (relative_path.IsAbsolute() || relative_path.ReferencesParent()) {
+ ReportFailure("Invalid path for catalog.");
+ return false;
+ }
+ FilePath path = extension_root_.Append(relative_path);
+
+ std::string catalog_json;
+ JSONStringValueSerializer serializer(&catalog_json);
+ serializer.set_pretty_print(true);
+ if (!serializer.Serialize(*catalog)) {
+ ReportFailure("Error serializing catalog.");
+ return false;
+ }
+
+ // Note: we're overwriting existing files that the utility process read,
+ // so we can be sure the directory exists.
+ if (!file_util::WriteFile(path,
+ catalog_json.c_str(),
+ catalog_json.size())) {
+ ReportFailure("Error saving catalog.");
+ return false;
+ }
+ }
+
+ return true;
+}