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