Chromium Code Reviews| Index: chrome/browser/chromeos/arc/arc_wallpaper_handler.cc |
| diff --git a/chrome/browser/chromeos/arc/arc_wallpaper_handler.cc b/chrome/browser/chromeos/arc/arc_wallpaper_handler.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..73578c8259683bc28699f1591c25f2b49455898f |
| --- /dev/null |
| +++ b/chrome/browser/chromeos/arc/arc_wallpaper_handler.cc |
| @@ -0,0 +1,123 @@ |
| +// Copyright 2016 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "chrome/browser/chromeos/arc/arc_wallpaper_handler.h" |
| + |
| +#include <string> |
| +#include <vector> |
| + |
| +#include "base/bind.h" |
| +#include "base/callback.h" |
| +#include "base/logging.h" |
| +#include "chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.h" |
| +#include "chrome/browser/image_decoder.h" |
| +#include "components/signin/core/account_id/account_id.h" |
| +#include "components/user_manager/user_manager.h" |
| +#include "components/wallpaper/wallpaper_files_id.h" |
| +#include "components/wallpaper/wallpaper_layout.h" |
| +#include "ui/gfx/image/image_skia.h" |
| + |
| +namespace arc { |
| + |
| +namespace { |
| + |
| +constexpr char kAndroidWallpaperFilename[] = "android.jpg"; |
| + |
| +// A thin wrapper of ImageDecoder to decode untrusted JPEG images. |
| +class UnsafeJpegImageDecoder : public ImageDecoder::ImageRequest { |
|
hidehiko
2016/06/16 05:49:24
This looks just an adapter of from Callback to Ima
Shuhei Takahashi
2016/06/16 14:56:10
With ImageDecoder::Cancel(), I can do this, thanks
|
| + public: |
| + // Type of the callback function called on image decode completion. |
| + // ImageSkia instance can be null value if decoding failed. |
|
rickyz (no longer on Chrome)
2016/06/16 01:38:48
Heh, didn't realize this was referring to ImageSki
Shuhei Takahashi
2016/06/16 14:56:10
That's why I wrote null "value" but it might not b
|
| + using Callback = base::Callback<void(const gfx::ImageSkia&)>; |
| + |
| + // Starts decoding |jpeg_data| and invokes |callback| on completion. |
| + static void Start(const std::vector<uint8_t>& jpeg_data, |
| + const Callback& callback); |
| + |
| + // ImageDecoder::ImageRequest implementation. |
| + void OnImageDecoded(const SkBitmap& image) override; |
| + void OnDecodeImageFailed() override; |
| + |
| + private: |
| + UnsafeJpegImageDecoder(const std::vector<uint8_t>& jpeg_data, |
| + const Callback& callback); |
| + ~UnsafeJpegImageDecoder() override = default; |
| + |
| + Callback callback_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(UnsafeJpegImageDecoder); |
| +}; |
| + |
| +// static |
| +void UnsafeJpegImageDecoder::Start(const std::vector<uint8_t>& jpeg_data, |
| + const Callback& callback) { |
| + // Unfortunately ImageDecoder accepts a raw pointer to ImageRequest only, |
| + // so callers must not delete ImageRequest instance until decoding finishes. |
| + // In our case, let OnImageDecoded/OnDecodeImageFailed delete this |
| + // instance on completion. |
| + new UnsafeJpegImageDecoder(jpeg_data, callback); |
|
hidehiko
2016/06/16 05:49:24
We should cancel the operation, on the destruction
Shuhei Takahashi
2016/06/16 14:56:10
Ah I did not notice there is ImageDecoder::Cancel(
|
| +} |
| + |
| +void UnsafeJpegImageDecoder::OnImageDecoded(const SkBitmap& decoded_image) { |
| + // Make the SkBitmap immutable as we won't modify it. This is important |
| + // because otherwise it gets duplicated during painting, wasting memory. |
| + SkBitmap immutable(decoded_image); |
| + immutable.setImmutable(); |
| + gfx::ImageSkia final_image = gfx::ImageSkia::CreateFrom1xBitmap(immutable); |
| + final_image.MakeThreadSafe(); |
| + callback_.Run(final_image); |
| + delete this; |
| +} |
| + |
| +void UnsafeJpegImageDecoder::OnDecodeImageFailed() { |
| + callback_.Run(gfx::ImageSkia()); |
| + delete this; |
| +} |
| + |
| +UnsafeJpegImageDecoder::UnsafeJpegImageDecoder( |
| + const std::vector<uint8_t>& jpeg_data, |
| + const Callback& callback) |
| + : callback_(callback) { |
| + std::string jpeg_data_as_string(reinterpret_cast<const char*>(jpeg_data[0]), |
|
rickyz (no longer on Chrome)
2016/06/16 01:38:48
Blech, I'm reading through ImageDecoder::StartWith
hidehiko
2016/06/16 05:49:24
Ah, +1 for :-(. Maybe, we want to fix it separatel
Shuhei Takahashi
2016/06/16 14:56:10
Agreed. I'll leave a TODO here.
|
| + jpeg_data.size()); |
| + ImageDecoder::StartWithOptions(this, jpeg_data_as_string, |
| + ImageDecoder::ROBUST_JPEG_CODEC, true); |
| +} |
| + |
| +// Sets a decoded image as the wallpaper. |
| +void SetImageAsWallpaper(const gfx::ImageSkia& image) { |
| + if (image.isNull()) { |
| + LOG(ERROR) << "Failed to decode wallpaper image."; |
| + return; |
| + } |
| + |
| + chromeos::WallpaperManager* wallpaper_manager = |
| + chromeos::WallpaperManager::Get(); |
| + |
| + const AccountId& account_id = |
| + user_manager::UserManager::Get()->GetPrimaryUser()->GetAccountId(); |
| + wallpaper::WallpaperFilesId wallpaper_files_id = |
| + wallpaper_manager->GetFilesId(account_id); |
| + bool update_wallpaper = |
| + account_id == |
| + user_manager::UserManager::Get()->GetActiveUser()->GetAccountId(); |
| + // TODO(crbug.com/618922): Allow specifying layout. |
| + wallpaper_manager->SetCustomWallpaper( |
| + account_id, wallpaper_files_id, kAndroidWallpaperFilename, |
| + wallpaper::WALLPAPER_LAYOUT_STRETCH, user_manager::User::CUSTOMIZED, |
| + image, update_wallpaper); |
| + |
| + // TODO(crbug.com/618922): Register the wallpaper to Chrome OS wallpaper |
| + // picker. Currently the new wallpaper does not appear there. The best way to |
| + // make this happen seems to do the same things as wallpaper_api.cc and |
| + // wallpaper_private_api.cc. |
| +} |
| + |
| +} // namespace |
| + |
| +void ArcWallpaperHandler::SetWallpaper(const std::vector<uint8_t>& jpeg_data) { |
| + UnsafeJpegImageDecoder::Start(jpeg_data, base::Bind(&SetImageAsWallpaper)); |
| +} |
| + |
| +} // namespace arc |