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