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 13 using content::BrowserThread; 14 15 namespace wallpaper_api_util { 16 namespace { 17 18 // Keeps in sync (same order) with WallpaperLayout enum in header file. 19 const char* kWallpaperLayoutArrays[] = { 20 "CENTER", 21 "CENTER_CROPPED", 22 "STRETCH", 23 "TILE" 24 }; 25 26 const int kWallpaperLayoutCount = arraysize(kWallpaperLayoutArrays); 27 28 } // namespace 29 30 const char kCancelWallpaperMessage[] = "Set wallpaper was canceled."; 31 32 ash::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 43 class 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 101 WallpaperFunctionBase::UnsafeWallpaperDecoder* 102 WallpaperFunctionBase::unsafe_wallpaper_decoder_; 103 104 WallpaperFunctionBase::WallpaperFunctionBase() { 105 } 106 107 WallpaperFunctionBase::~WallpaperFunctionBase() { 108 } 109 110 void 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 118 void WallpaperFunctionBase::OnCancel() { 119 unsafe_wallpaper_decoder_ = NULL; 120 SetError(wallpaper_api_util::kCancelWallpaperMessage); 121 SendResponse(false); 122 } 123 124 void WallpaperFunctionBase::OnFailure(const std::string& error) { 125 unsafe_wallpaper_decoder_ = NULL; 126 SetError(error); 127 SendResponse(false); 128 } 129