Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / extensions / wallpaper_api.cc
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_api.h"
6
7 #include "ash/desktop_background/desktop_background_controller.h"
8 #include "base/file_util.h"
9 #include "base/lazy_instance.h"
10 #include "base/path_service.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/threading/worker_pool.h"
13 #include "chrome/browser/browser_process.h"
14 #include "chrome/browser/chromeos/login/user.h"
15 #include "chrome/browser/chromeos/login/user_manager.h"
16 #include "chrome/browser/chromeos/login/wallpaper_manager.h"
17 #include "chrome/common/chrome_paths.h"
18 #include "net/base/load_flags.h"
19 #include "net/http/http_status_code.h"
20 #include "net/url_request/url_fetcher.h"
21 #include "net/url_request/url_fetcher_delegate.h"
22 #include "url/gurl.h"
23
24 using base::BinaryValue;
25 using content::BrowserThread;
26
27 typedef base::Callback<void(bool success, const std::string&)> FetchCallback;
28
29 namespace set_wallpaper = extensions::api::wallpaper::SetWallpaper;
30
31 namespace {
32
33 class WallpaperFetcher : public net::URLFetcherDelegate {
34  public:
35   WallpaperFetcher() {}
36
37   virtual ~WallpaperFetcher() {}
38
39   void FetchWallpaper(const GURL& url, FetchCallback callback) {
40     CancelPreviousFetch();
41     callback_ = callback;
42     url_fetcher_.reset(net::URLFetcher::Create(url,
43                                                net::URLFetcher::GET,
44                                                this));
45     url_fetcher_->SetRequestContext(
46         g_browser_process->system_request_context());
47     url_fetcher_->SetLoadFlags(net::LOAD_DISABLE_CACHE);
48     url_fetcher_->Start();
49   }
50
51  private:
52   // URLFetcherDelegate overrides:
53   virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE {
54     DCHECK(url_fetcher_.get() == source);
55
56     bool success = source->GetStatus().is_success() &&
57                    source->GetResponseCode() == net::HTTP_OK;
58     std::string response;
59     if (success) {
60       source->GetResponseAsString(&response);
61     } else {
62       response = base::StringPrintf(
63           "Downloading wallpaper %s failed. The response code is %d.",
64           source->GetOriginalURL().ExtractFileName().c_str(),
65           source->GetResponseCode());
66     }
67     url_fetcher_.reset();
68     callback_.Run(success, response);
69   }
70
71   void CancelPreviousFetch() {
72     if (url_fetcher_.get()) {
73       std::string error = base::StringPrintf(
74           "Downloading wallpaper %s is canceled.",
75           url_fetcher_->GetOriginalURL().ExtractFileName().c_str());
76       callback_.Run(false, error);
77       url_fetcher_.reset();
78     }
79   }
80
81   scoped_ptr<net::URLFetcher> url_fetcher_;
82   FetchCallback callback_;
83 };
84
85 base::LazyInstance<WallpaperFetcher> g_wallpaper_fetcher =
86     LAZY_INSTANCE_INITIALIZER;
87
88 }  // namespace
89
90 WallpaperSetWallpaperFunction::WallpaperSetWallpaperFunction() {
91 }
92
93 WallpaperSetWallpaperFunction::~WallpaperSetWallpaperFunction() {
94 }
95
96 bool WallpaperSetWallpaperFunction::RunAsync() {
97   params_ = set_wallpaper::Params::Create(*args_);
98   EXTENSION_FUNCTION_VALIDATE(params_);
99
100   // Gets email address and username hash while at UI thread.
101   user_id_ = chromeos::UserManager::Get()->GetLoggedInUser()->email();
102   user_id_hash_ =
103       chromeos::UserManager::Get()->GetLoggedInUser()->username_hash();
104
105   if (params_->details.wallpaper_data) {
106     StartDecode(*params_->details.wallpaper_data);
107   } else {
108     GURL wallpaper_url(*params_->details.url);
109     if (wallpaper_url.is_valid()) {
110       g_wallpaper_fetcher.Get().FetchWallpaper(
111           wallpaper_url,
112           base::Bind(&WallpaperSetWallpaperFunction::OnWallpaperFetched, this));
113     } else {
114       SetError("URL is invalid.");
115       SendResponse(false);
116     }
117   }
118   return true;
119 }
120
121 void WallpaperSetWallpaperFunction::OnWallpaperDecoded(
122     const gfx::ImageSkia& image) {
123   chromeos::WallpaperManager* wallpaper_manager =
124       chromeos::WallpaperManager::Get();
125   base::FilePath thumbnail_path = wallpaper_manager->GetCustomWallpaperPath(
126       chromeos::kThumbnailWallpaperSubDir,
127       user_id_hash_,
128       params_->details.name);
129
130   sequence_token_ = BrowserThread::GetBlockingPool()->
131       GetNamedSequenceToken(chromeos::kWallpaperSequenceTokenName);
132   scoped_refptr<base::SequencedTaskRunner> task_runner =
133       BrowserThread::GetBlockingPool()->
134           GetSequencedTaskRunnerWithShutdownBehavior(sequence_token_,
135               base::SequencedWorkerPool::BLOCK_SHUTDOWN);
136   ash::WallpaperLayout layout = wallpaper_api_util::GetLayoutEnum(
137       set_wallpaper::Params::Details::ToString(params_->details.layout));
138   bool update_wallpaper =
139       user_id_ == chromeos::UserManager::Get()->GetActiveUser()->email();
140   wallpaper_manager->SetCustomWallpaper(user_id_,
141                                         user_id_hash_,
142                                         params_->details.name,
143                                         layout,
144                                         chromeos::User::CUSTOMIZED,
145                                         image,
146                                         update_wallpaper);
147   unsafe_wallpaper_decoder_ = NULL;
148
149   if (params_->details.thumbnail) {
150     image.EnsureRepsForSupportedScales();
151     scoped_ptr<gfx::ImageSkia> deep_copy(image.DeepCopy());
152     // Generates thumbnail before call api function callback. We can then
153     // request thumbnail in the javascript callback.
154     task_runner->PostTask(
155         FROM_HERE,
156         base::Bind(&WallpaperSetWallpaperFunction::GenerateThumbnail,
157                    this,
158                    thumbnail_path,
159                    base::Passed(deep_copy.Pass())));
160   } else {
161     SendResponse(true);
162   }
163 }
164
165 void WallpaperSetWallpaperFunction::GenerateThumbnail(
166     const base::FilePath& thumbnail_path, scoped_ptr<gfx::ImageSkia> image) {
167   DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
168       sequence_token_));
169   if (!base::PathExists(thumbnail_path.DirName()))
170     base::CreateDirectory(thumbnail_path.DirName());
171
172   scoped_refptr<base::RefCountedBytes> data;
173   chromeos::WallpaperManager::Get()->ResizeImage(
174       *image,
175       ash::WALLPAPER_LAYOUT_STRETCH,
176       chromeos::kWallpaperThumbnailWidth,
177       chromeos::kWallpaperThumbnailHeight,
178       &data,
179       NULL);
180   BrowserThread::PostTask(
181       BrowserThread::UI, FROM_HERE,
182       base::Bind(
183           &WallpaperSetWallpaperFunction::ThumbnailGenerated,
184           this, data));
185 }
186
187 void WallpaperSetWallpaperFunction::ThumbnailGenerated(
188     base::RefCountedBytes* data) {
189   BinaryValue* result = BinaryValue::CreateWithCopiedBuffer(
190       reinterpret_cast<const char*>(data->front()), data->size());
191   SetResult(result);
192   SendResponse(true);
193 }
194
195 void WallpaperSetWallpaperFunction::OnWallpaperFetched(
196     bool success,
197     const std::string& response) {
198   if (success) {
199     params_->details.wallpaper_data.reset(new std::string(response));
200     StartDecode(*params_->details.wallpaper_data);
201   } else {
202     SetError(response);
203     SendResponse(false);
204   }
205 }