1// Copyright 2013 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/chromeos/extensions/wallpaper_function_base.h" 6 7#include "base/synchronization/cancellation_flag.h" 8#include "chrome/browser/image_decoder.h" 9#include "chrome/grit/generated_resources.h" 10#include "chromeos/login/login_state.h" 11#include "ui/base/l10n/l10n_util.h" 12 13using content::BrowserThread; 14 15namespace wallpaper_api_util { 16namespace { 17 18// Keeps in sync (same order) with WallpaperLayout enum in header file. 19const char* kWallpaperLayoutArrays[] = { 20 "CENTER", 21 "CENTER_CROPPED", 22 "STRETCH", 23 "TILE" 24}; 25 26const int kWallpaperLayoutCount = arraysize(kWallpaperLayoutArrays); 27 28} // namespace 29 30const char kCancelWallpaperMessage[] = "Set wallpaper was canceled."; 31 32ash::WallpaperLayout GetLayoutEnum(const std::string& layout) { 33 for (int i = 0; i < kWallpaperLayoutCount; i++) { 34 if (layout.compare(kWallpaperLayoutArrays[i]) == 0) 35 return static_cast<ash::WallpaperLayout>(i); 36 } 37 // Default to use CENTER layout. 38 return ash::WALLPAPER_LAYOUT_CENTER; 39} 40 41} // namespace wallpaper_api_util 42 43class WallpaperFunctionBase::UnsafeWallpaperDecoder 44 : public ImageDecoder::Delegate { 45 public: 46 explicit UnsafeWallpaperDecoder(scoped_refptr<WallpaperFunctionBase> function) 47 : function_(function) { 48 } 49 50 void Start(const std::string& image_data) { 51 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 52 53 // This function can only be called after user login. It is fine to use 54 // unsafe image decoder here. Before user login, a robust jpeg decoder will 55 // be used. 56 CHECK(chromeos::LoginState::Get()->IsUserLoggedIn()); 57 unsafe_image_decoder_ = new ImageDecoder(this, image_data, 58 ImageDecoder::DEFAULT_CODEC); 59 unsafe_image_decoder_->set_shrink_to_fit(true); 60 61 scoped_refptr<base::MessageLoopProxy> task_runner = 62 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI); 63 unsafe_image_decoder_->Start(task_runner); 64 } 65 66 void Cancel() { 67 cancel_flag_.Set(); 68 } 69 70 virtual void OnImageDecoded(const ImageDecoder* decoder, 71 const SkBitmap& decoded_image) OVERRIDE { 72 // Make the SkBitmap immutable as we won't modify it. This is important 73 // because otherwise it gets duplicated during painting, wasting memory. 74 SkBitmap immutable(decoded_image); 75 immutable.setImmutable(); 76 gfx::ImageSkia final_image = gfx::ImageSkia::CreateFrom1xBitmap(immutable); 77 final_image.MakeThreadSafe(); 78 if (cancel_flag_.IsSet()) { 79 function_->OnCancel(); 80 delete this; 81 return; 82 } 83 function_->OnWallpaperDecoded(final_image); 84 delete this; 85 } 86 87 virtual void OnDecodeImageFailed(const ImageDecoder* decoder) OVERRIDE { 88 function_->OnFailure( 89 l10n_util::GetStringUTF8(IDS_WALLPAPER_MANAGER_INVALID_WALLPAPER)); 90 delete this; 91 } 92 93 private: 94 scoped_refptr<WallpaperFunctionBase> function_; 95 scoped_refptr<ImageDecoder> unsafe_image_decoder_; 96 base::CancellationFlag cancel_flag_; 97 98 DISALLOW_COPY_AND_ASSIGN(UnsafeWallpaperDecoder); 99}; 100 101WallpaperFunctionBase::UnsafeWallpaperDecoder* 102 WallpaperFunctionBase::unsafe_wallpaper_decoder_; 103 104WallpaperFunctionBase::WallpaperFunctionBase() { 105} 106 107WallpaperFunctionBase::~WallpaperFunctionBase() { 108} 109 110void WallpaperFunctionBase::StartDecode(const std::string& data) { 111 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 112 if (unsafe_wallpaper_decoder_) 113 unsafe_wallpaper_decoder_->Cancel(); 114 unsafe_wallpaper_decoder_ = new UnsafeWallpaperDecoder(this); 115 unsafe_wallpaper_decoder_->Start(data); 116} 117 118void WallpaperFunctionBase::OnCancel() { 119 unsafe_wallpaper_decoder_ = NULL; 120 SetError(wallpaper_api_util::kCancelWallpaperMessage); 121 SendResponse(false); 122} 123 124void WallpaperFunctionBase::OnFailure(const std::string& error) { 125 unsafe_wallpaper_decoder_ = NULL; 126 SetError(error); 127 SendResponse(false); 128} 129