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.
5 #include "chrome/browser/chromeos/extensions/wallpaper_api.h"
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/url_request/url_fetcher.h"
20 #include "net/url_request/url_fetcher_delegate.h"
23 using base::BinaryValue
;
24 using content::BrowserThread
;
26 typedef base::Callback
<void(net::URLRequestStatus::Status
, const std::string
&)>
29 namespace set_wallpaper
= extensions::api::wallpaper::SetWallpaper
;
33 class WallpaperFetcher
: public net::URLFetcherDelegate
{
37 virtual ~WallpaperFetcher() {}
39 void FetchWallpaper(const GURL
& url
, FetchCallback callback
) {
40 CancelPreviousFetch();
42 url_fetcher_
.reset(net::URLFetcher::Create(url
,
45 url_fetcher_
->SetRequestContext(
46 g_browser_process
->system_request_context());
47 url_fetcher_
->SetLoadFlags(net::LOAD_DISABLE_CACHE
);
48 url_fetcher_
->Start();
52 // URLFetcherDelegate overrides:
53 virtual void OnURLFetchComplete(const net::URLFetcher
* source
) OVERRIDE
{
54 net::URLRequestStatus::Status status
= source
->GetStatus().status();
56 if (status
== net::URLRequestStatus::SUCCESS
) {
57 url_fetcher_
->GetResponseAsString(&response
);
59 response
= source
->GetStatus().error();
62 callback_
.Run(status
, response
);
65 void CancelPreviousFetch() {
66 if (url_fetcher_
.get()) {
67 std::string error
= base::StringPrintf(
68 "Downloading wallpaper %s is canceled.",
69 url_fetcher_
->GetOriginalURL().ExtractFileName().c_str());
70 callback_
.Run(net::URLRequestStatus::CANCELED
, error
);
75 scoped_ptr
<net::URLFetcher
> url_fetcher_
;
76 FetchCallback callback_
;
79 base::LazyInstance
<WallpaperFetcher
> g_wallpaper_fetcher
=
80 LAZY_INSTANCE_INITIALIZER
;
84 WallpaperSetWallpaperFunction::WallpaperSetWallpaperFunction() {
87 WallpaperSetWallpaperFunction::~WallpaperSetWallpaperFunction() {
90 bool WallpaperSetWallpaperFunction::RunImpl() {
91 params_
= set_wallpaper::Params::Create(*args_
);
92 EXTENSION_FUNCTION_VALIDATE(params_
);
94 // Gets email address and username hash while at UI thread.
95 email_
= chromeos::UserManager::Get()->GetLoggedInUser()->email();
97 chromeos::UserManager::Get()->GetLoggedInUser()->username_hash();
99 if (params_
->details
.wallpaper_data
) {
100 StartDecode(*params_
->details
.wallpaper_data
);
102 GURL
wallpaper_url(*params_
->details
.url
);
103 if (wallpaper_url
.is_valid()) {
104 g_wallpaper_fetcher
.Get().FetchWallpaper(
106 base::Bind(&WallpaperSetWallpaperFunction::OnWallpaperFetched
,
109 SetError("URL is invalid.");
116 void WallpaperSetWallpaperFunction::OnWallpaperDecoded(
117 const gfx::ImageSkia
& wallpaper
) {
118 chromeos::WallpaperManager
* wallpaper_manager
=
119 chromeos::WallpaperManager::Get();
120 chromeos::UserImage::RawImage
raw_image(
121 params_
->details
.wallpaper_data
->begin(),
122 params_
->details
.wallpaper_data
->end());
123 chromeos::UserImage
image(wallpaper
, raw_image
);
124 base::FilePath thumbnail_path
= wallpaper_manager
->GetCustomWallpaperPath(
125 chromeos::kThumbnailWallpaperSubDir
,
127 params_
->details
.name
);
129 sequence_token_
= BrowserThread::GetBlockingPool()->
130 GetNamedSequenceToken(chromeos::kWallpaperSequenceTokenName
);
131 scoped_refptr
<base::SequencedTaskRunner
> task_runner
=
132 BrowserThread::GetBlockingPool()->
133 GetSequencedTaskRunnerWithShutdownBehavior(sequence_token_
,
134 base::SequencedWorkerPool::BLOCK_SHUTDOWN
);
135 ash::WallpaperLayout layout
= wallpaper_api_util::GetLayoutEnum(
136 set_wallpaper::Params::Details::ToString(params_
->details
.layout
));
137 wallpaper_manager
->SetCustomWallpaper(email_
,
139 params_
->details
.name
,
141 chromeos::User::CUSTOMIZED
,
143 unsafe_wallpaper_decoder_
= NULL
;
145 if (params_
->details
.thumbnail
) {
146 wallpaper
.EnsureRepsForSupportedScales();
147 scoped_ptr
<gfx::ImageSkia
> deep_copy(wallpaper
.DeepCopy());
148 // Generates thumbnail before call api function callback. We can then
149 // request thumbnail in the javascript callback.
150 task_runner
->PostTask(FROM_HERE
,
152 &WallpaperSetWallpaperFunction::GenerateThumbnail
,
153 this, thumbnail_path
, base::Passed(&deep_copy
)));
159 void WallpaperSetWallpaperFunction::GenerateThumbnail(
160 const base::FilePath
& thumbnail_path
, scoped_ptr
<gfx::ImageSkia
> image
) {
161 DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
163 chromeos::UserImage
wallpaper(*image
.get());
164 if (!base::PathExists(thumbnail_path
.DirName()))
165 base::CreateDirectory(thumbnail_path
.DirName());
167 scoped_refptr
<base::RefCountedBytes
> data
;
168 chromeos::WallpaperManager::Get()->ResizeWallpaper(
170 ash::WALLPAPER_LAYOUT_STRETCH
,
171 ash::kWallpaperThumbnailWidth
,
172 ash::kWallpaperThumbnailHeight
,
174 BrowserThread::PostTask(
175 BrowserThread::UI
, FROM_HERE
,
177 &WallpaperSetWallpaperFunction::ThumbnailGenerated
,
181 void WallpaperSetWallpaperFunction::ThumbnailGenerated(
182 base::RefCountedBytes
* data
) {
183 BinaryValue
* result
= BinaryValue::CreateWithCopiedBuffer(
184 reinterpret_cast<const char*>(data
->front()), data
->size());
189 void WallpaperSetWallpaperFunction::OnWallpaperFetched(
190 net::URLRequestStatus::Status status
, const std::string
& response
) {
191 if (status
== net::URLRequestStatus::SUCCESS
) {
192 params_
->details
.wallpaper_data
.reset(new std::string(response
));
193 StartDecode(*params_
->details
.wallpaper_data
);