Home | History | Annotate | Download | only in extensions
      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