| Index: ui/gfx/icon_util.cc
|
| diff --git a/ui/gfx/icon_util.cc b/ui/gfx/icon_util.cc
|
| index 37ab0d59f53b16e2a702038c541697817ce1ff00..5c4bf11b9e0d98c0fed3f5e471b480d020333e3b 100644
|
| --- a/ui/gfx/icon_util.cc
|
| +++ b/ui/gfx/icon_util.cc
|
| @@ -5,6 +5,7 @@
|
| #include "ui/gfx/icon_util.h"
|
|
|
| #include "base/file_util.h"
|
| +#include "base/files/important_file_writer.h"
|
| #include "base/logging.h"
|
| #include "base/memory/scoped_ptr.h"
|
| #include "base/win/resource_util.h"
|
| @@ -20,6 +21,9 @@
|
|
|
| namespace {
|
|
|
| +const base::FilePath::CharType kIconChecksumFileExt[] =
|
| + FILE_PATH_LITERAL(".ico.md5");
|
| +
|
| struct ScopedICONINFO : ICONINFO {
|
| ScopedICONINFO() {
|
| hbmColor = NULL;
|
| @@ -470,13 +474,6 @@ bool IconUtil::CreateIconFileFromImageFamily(
|
| // Including PNG image, if any.
|
| size_t image_count = bitmap_count + (png_bytes.get() ? 1 : 0);
|
|
|
| - // Now that basic checks are done, we can create the file.
|
| - base::win::ScopedHandle icon_file(::CreateFile(icon_path.value().c_str(),
|
| - GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL));
|
| -
|
| - if (!icon_file.IsValid())
|
| - return false;
|
| -
|
| // Computing the total size of the buffer we need in order to store the
|
| // images in the desired icon format.
|
| size_t buffer_size = ComputeIconFileBufferSize(bitmaps);
|
| @@ -521,22 +518,8 @@ bool IconUtil::CreateIconFileFromImageFamily(
|
|
|
| DCHECK_EQ(offset, buffer_size);
|
|
|
| - // Finally, write the data to the file.
|
| - DWORD bytes_written;
|
| - bool delete_file = false;
|
| - if (!WriteFile(icon_file.Get(), &buffer[0], buffer_size, &bytes_written,
|
| - NULL) ||
|
| - bytes_written != buffer_size) {
|
| - delete_file = true;
|
| - }
|
| -
|
| - ::CloseHandle(icon_file.Take());
|
| - if (delete_file) {
|
| - bool success = file_util::Delete(icon_path, false);
|
| - DCHECK(success);
|
| - }
|
| -
|
| - return !delete_file;
|
| + std::string data(buffer.begin(), buffer.end());
|
| + return base::ImportantFileWriter::WriteFileAtomically(icon_path, data);
|
| }
|
|
|
| bool IconUtil::PixelsHaveAlpha(const uint32* pixels, size_t num_pixels) {
|
| @@ -707,3 +690,60 @@ void IconUtil::ComputeBitmapSizeComponents(const SkBitmap& bitmap,
|
| size_t masks_size = *xor_mask_size + and_mask_size;
|
| *bytes_in_resource = masks_size + sizeof(BITMAPINFOHEADER);
|
| }
|
| +
|
| +void IconUtil::GetImageCheckSum(const gfx::ImageFamily& image,
|
| + base::MD5Digest* digest) {
|
| + DCHECK(digest);
|
| + base::MD5Context md5_context;
|
| + base::MD5Init(&md5_context);
|
| +
|
| + for (gfx::ImageFamily::const_iterator it = image.begin(); it != image.end();
|
| + ++it) {
|
| + SkBitmap bitmap = it->AsBitmap();
|
| +
|
| + SkAutoLockPixels image_lock(bitmap);
|
| + base::StringPiece image_data(
|
| + reinterpret_cast<const char*>(bitmap.getPixels()), bitmap.getSize());
|
| + base::MD5Update(&md5_context, image_data);
|
| + }
|
| +
|
| + base::MD5Final(digest, &md5_context);
|
| +}
|
| +
|
| +bool IconUtil::SaveIconWithCheckSum(const base::FilePath& icon_file,
|
| + const gfx::ImageFamily& image) {
|
| + if (!CreateIconFileFromImageFamily(image, icon_file))
|
| + return false;
|
| +
|
| + base::MD5Digest digest;
|
| + GetImageCheckSum(image, &digest);
|
| +
|
| + base::FilePath cheksum_file(icon_file.ReplaceExtension(kIconChecksumFileExt));
|
| + return file_util::WriteFile(cheksum_file,
|
| + reinterpret_cast<const char*>(&digest),
|
| + sizeof(digest)) == sizeof(digest);
|
| +}
|
| +
|
| +bool IconUtil::ShouldUpdateIcon(const base::FilePath& icon_file,
|
| + const gfx::ImageFamily& image) {
|
| + base::FilePath checksum_file(
|
| + icon_file.ReplaceExtension(kIconChecksumFileExt));
|
| +
|
| + // Returns true if icon_file or checksum file is missing.
|
| + if (!file_util::PathExists(icon_file) ||
|
| + !file_util::PathExists(checksum_file))
|
| + return true;
|
| +
|
| + base::MD5Digest persisted_image_checksum;
|
| + if (sizeof(persisted_image_checksum) != file_util::ReadFile(checksum_file,
|
| + reinterpret_cast<char*>(&persisted_image_checksum),
|
| + sizeof(persisted_image_checksum)))
|
| + return true;
|
| +
|
| + base::MD5Digest downloaded_image_checksum;
|
| + GetImageCheckSum(image, &downloaded_image_checksum);
|
| +
|
| + // Update icon if checksums are not equal.
|
| + return memcmp(&persisted_image_checksum, &downloaded_image_checksum,
|
| + sizeof(base::MD5Digest)) != 0;
|
| +}
|
|
|