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..23009fdad5498f07e28fe4dfb04dd4d40036f77d |
| --- /dev/null |
| +++ b/chrome/browser/chromeos/arc/arc_wallpaper_handler.cc |
| @@ -0,0 +1,115 @@ |
| +// 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 "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 { |
| + public: |
| + // Type of the callback function called on image decode completion. |
| + // ImageSkia instance can be null value if decoding failed. |
| + using Callback = base::Callback<void(const gfx::ImageSkia&)>; |
| + |
| + // Starts decoding |jpeg_data| and invokes |callback| on completion. |
| + static void Start(const std::string& jpeg_data, const Callback& callback); |
| + |
| + // ImageDecoder::ImageRequest implementation. |
| + void OnImageDecoded(const SkBitmap& image) override; |
| + void OnDecodeImageFailed() override; |
| + |
| + private: |
| + UnsafeJpegImageDecoder(const std::string& jpeg_data, |
| + const Callback& callback); |
| + ~UnsafeJpegImageDecoder() {} |
|
Yusuke Sato
2016/06/15 19:44:32
override = default;
Shuhei Takahashi
2016/06/15 22:58:38
Done.
|
| + |
| + Callback callback_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(UnsafeJpegImageDecoder); |
| +}; |
| + |
| +void UnsafeJpegImageDecoder::Start(const std::string& jpeg_data, |
|
Yusuke Sato
2016/06/15 19:44:32
nit: What about adding '// static' here? I was a l
Shuhei Takahashi
2016/06/15 22:58:38
Done.
|
| + 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); |
| +} |
| + |
| +void UnsafeJpegImageDecoder::OnImageDecoded(const SkBitmap& decoded_image) { |
| + SkBitmap immutable(decoded_image); |
|
Yusuke Sato
2016/06/15 19:44:32
Can you add a short comment on why setImmutable()
Shuhei Takahashi
2016/06/15 22:58:38
Hmm, actually I just followed the way chrome/brows
|
| + 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::string& jpeg_data, |
| + const Callback& callback) |
| + : callback_(callback) { |
| + ImageDecoder::StartWithOptions(this, jpeg_data, |
| + ImageDecoder::ROBUST_JPEG_CODEC, true); |
| +} |
| + |
| +// Sets a decoded image as the wallpaper. |
| +void SetImageAsWallpaper(const gfx::ImageSkia& image) { |
| + if (image.isNull()) { |
|
Yusuke Sato
2016/06/15 19:44:32
Does this catch the callback_.Run(gfx::ImageSkia()
Shuhei Takahashi
2016/06/15 22:58:38
Yes.
https://cs.chromium.org/chromium/src/ui/gfx/
|
| + 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::string& jpeg_data) { |
| + UnsafeJpegImageDecoder::Start(jpeg_data, base::Bind(&SetImageAsWallpaper)); |
| +} |
| + |
| +} // namespace arc |