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"
9d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "chromeos/login/login_state.h"
10d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "grit/generated_resources.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);
59d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    scoped_refptr<base::MessageLoopProxy> task_runner =
60d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI);
61d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    unsafe_image_decoder_->Start(task_runner);
62d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
63d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
64d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  void Cancel() {
65d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    cancel_flag_.Set();
66d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
67d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
68d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  virtual void OnImageDecoded(const ImageDecoder* decoder,
69d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                              const SkBitmap& decoded_image) OVERRIDE {
70d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // Make the SkBitmap immutable as we won't modify it. This is important
71d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // because otherwise it gets duplicated during painting, wasting memory.
72d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    SkBitmap immutable(decoded_image);
73d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    immutable.setImmutable();
74d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    gfx::ImageSkia final_image = gfx::ImageSkia::CreateFrom1xBitmap(immutable);
75d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    final_image.MakeThreadSafe();
76d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (cancel_flag_.IsSet()) {
77d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      function_->OnCancel();
78d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      delete this;
79d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      return;
80d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
81d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    function_->OnWallpaperDecoded(final_image);
82d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    delete this;
83d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
84d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
85d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  virtual void OnDecodeImageFailed(const ImageDecoder* decoder) OVERRIDE {
86d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    function_->OnFailure(
87d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        l10n_util::GetStringUTF8(IDS_WALLPAPER_MANAGER_INVALID_WALLPAPER));
88d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    delete this;
89d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
90d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
91d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) private:
92d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  scoped_refptr<WallpaperFunctionBase> function_;
93d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  scoped_refptr<ImageDecoder> unsafe_image_decoder_;
94d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  base::CancellationFlag cancel_flag_;
95d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
96d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(UnsafeWallpaperDecoder);
97d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)};
98d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
99d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)WallpaperFunctionBase::UnsafeWallpaperDecoder*
100d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    WallpaperFunctionBase::unsafe_wallpaper_decoder_;
101d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
102d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)WallpaperFunctionBase::WallpaperFunctionBase() {
103d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
104d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
105d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)WallpaperFunctionBase::~WallpaperFunctionBase() {
106d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
107d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
108d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void WallpaperFunctionBase::StartDecode(const std::string& data) {
109d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
110d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (unsafe_wallpaper_decoder_)
111d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    unsafe_wallpaper_decoder_->Cancel();
112d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  unsafe_wallpaper_decoder_ = new UnsafeWallpaperDecoder(this);
113d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  unsafe_wallpaper_decoder_->Start(data);
114d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
115d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
116d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void WallpaperFunctionBase::OnCancel() {
117d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  unsafe_wallpaper_decoder_ = NULL;
118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SetError(wallpaper_api_util::kCancelWallpaperMessage);
119d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  SendResponse(false);
120d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
121d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
122d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void WallpaperFunctionBase::OnFailure(const std::string& error) {
123d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  unsafe_wallpaper_decoder_ = NULL;
124d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  SetError(error);
125d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  SendResponse(false);
126d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
127