// Copyright 2013 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/extensions/wallpaper_function_base.h" #include "base/synchronization/cancellation_flag.h" #include "chrome/browser/image_decoder.h" #include "chrome/grit/generated_resources.h" #include "chromeos/login/login_state.h" #include "ui/base/l10n/l10n_util.h" using content::BrowserThread; namespace wallpaper_api_util { namespace { // Keeps in sync (same order) with WallpaperLayout enum in header file. const char* kWallpaperLayoutArrays[] = { "CENTER", "CENTER_CROPPED", "STRETCH", "TILE" }; const int kWallpaperLayoutCount = arraysize(kWallpaperLayoutArrays); } // namespace const char kCancelWallpaperMessage[] = "Set wallpaper was canceled."; ash::WallpaperLayout GetLayoutEnum(const std::string& layout) { for (int i = 0; i < kWallpaperLayoutCount; i++) { if (layout.compare(kWallpaperLayoutArrays[i]) == 0) return static_cast(i); } // Default to use CENTER layout. return ash::WALLPAPER_LAYOUT_CENTER; } } // namespace wallpaper_api_util class WallpaperFunctionBase::UnsafeWallpaperDecoder : public ImageDecoder::Delegate { public: explicit UnsafeWallpaperDecoder(scoped_refptr function) : function_(function) { } void Start(const std::string& image_data) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); // This function can only be called after user login. It is fine to use // unsafe image decoder here. Before user login, a robust jpeg decoder will // be used. CHECK(chromeos::LoginState::Get()->IsUserLoggedIn()); unsafe_image_decoder_ = new ImageDecoder(this, image_data, ImageDecoder::DEFAULT_CODEC); unsafe_image_decoder_->set_shrink_to_fit(true); scoped_refptr task_runner = BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI); unsafe_image_decoder_->Start(task_runner); } void Cancel() { cancel_flag_.Set(); } virtual void OnImageDecoded(const ImageDecoder* decoder, const SkBitmap& decoded_image) override { // 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(); if (cancel_flag_.IsSet()) { function_->OnCancel(); delete this; return; } function_->OnWallpaperDecoded(final_image); delete this; } virtual void OnDecodeImageFailed(const ImageDecoder* decoder) override { function_->OnFailure( l10n_util::GetStringUTF8(IDS_WALLPAPER_MANAGER_INVALID_WALLPAPER)); delete this; } private: scoped_refptr function_; scoped_refptr unsafe_image_decoder_; base::CancellationFlag cancel_flag_; DISALLOW_COPY_AND_ASSIGN(UnsafeWallpaperDecoder); }; WallpaperFunctionBase::UnsafeWallpaperDecoder* WallpaperFunctionBase::unsafe_wallpaper_decoder_; WallpaperFunctionBase::WallpaperFunctionBase() { } WallpaperFunctionBase::~WallpaperFunctionBase() { } void WallpaperFunctionBase::StartDecode(const std::string& data) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); if (unsafe_wallpaper_decoder_) unsafe_wallpaper_decoder_->Cancel(); unsafe_wallpaper_decoder_ = new UnsafeWallpaperDecoder(this); unsafe_wallpaper_decoder_->Start(data); } void WallpaperFunctionBase::OnCancel() { unsafe_wallpaper_decoder_ = NULL; SetError(wallpaper_api_util::kCancelWallpaperMessage); SendResponse(false); } void WallpaperFunctionBase::OnFailure(const std::string& error) { unsafe_wallpaper_decoder_ = NULL; SetError(error); SendResponse(false); }