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/http/http_status_code.h"
20 #include "net/url_request/url_fetcher.h"
21 #include "net/url_request/url_fetcher_delegate.h"
24 using base::BinaryValue;
25 using content::BrowserThread;
27 typedef base::Callback<void(bool success, const std::string&)> FetchCallback;
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 DCHECK(url_fetcher_.get() == source);
56 bool success = source->GetStatus().is_success() &&
57 source->GetResponseCode() == net::HTTP_OK;
60 source->GetResponseAsString(&response);
62 response = base::StringPrintf(
63 "Downloading wallpaper %s failed. The response code is %d.",
64 source->GetOriginalURL().ExtractFileName().c_str(),
65 source->GetResponseCode());
68 callback_.Run(success, response);
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);
81 scoped_ptr<net::URLFetcher> url_fetcher_;
82 FetchCallback callback_;
85 base::LazyInstance<WallpaperFetcher> g_wallpaper_fetcher =
86 LAZY_INSTANCE_INITIALIZER;
90 WallpaperSetWallpaperFunction::WallpaperSetWallpaperFunction() {
93 WallpaperSetWallpaperFunction::~WallpaperSetWallpaperFunction() {
96 bool WallpaperSetWallpaperFunction::RunAsync() {
97 params_ = set_wallpaper::Params::Create(*args_);
98 EXTENSION_FUNCTION_VALIDATE(params_);
100 // Gets email address and username hash while at UI thread.
101 user_id_ = chromeos::UserManager::Get()->GetLoggedInUser()->email();
103 chromeos::UserManager::Get()->GetLoggedInUser()->username_hash();
105 if (params_->details.wallpaper_data) {
106 StartDecode(*params_->details.wallpaper_data);
108 GURL wallpaper_url(*params_->details.url);
109 if (wallpaper_url.is_valid()) {
110 g_wallpaper_fetcher.Get().FetchWallpaper(
112 base::Bind(&WallpaperSetWallpaperFunction::OnWallpaperFetched, this));
114 SetError("URL is invalid.");
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,
128 params_->details.name);
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_,
142 params_->details.name,
144 chromeos::User::CUSTOMIZED,
147 unsafe_wallpaper_decoder_ = NULL;
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(
156 base::Bind(&WallpaperSetWallpaperFunction::GenerateThumbnail,
159 base::Passed(deep_copy.Pass())));
165 void WallpaperSetWallpaperFunction::GenerateThumbnail(
166 const base::FilePath& thumbnail_path, scoped_ptr<gfx::ImageSkia> image) {
167 DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
169 if (!base::PathExists(thumbnail_path.DirName()))
170 base::CreateDirectory(thumbnail_path.DirName());
172 scoped_refptr<base::RefCountedBytes> data;
173 chromeos::WallpaperManager::Get()->ResizeImage(
175 ash::WALLPAPER_LAYOUT_STRETCH,
176 chromeos::kWallpaperThumbnailWidth,
177 chromeos::kWallpaperThumbnailHeight,
180 BrowserThread::PostTask(
181 BrowserThread::UI, FROM_HERE,
183 &WallpaperSetWallpaperFunction::ThumbnailGenerated,
187 void WallpaperSetWallpaperFunction::ThumbnailGenerated(
188 base::RefCountedBytes* data) {
189 BinaryValue* result = BinaryValue::CreateWithCopiedBuffer(
190 reinterpret_cast<const char*>(data->front()), data->size());
195 void WallpaperSetWallpaperFunction::OnWallpaperFetched(
197 const std::string& response) {
199 params_->details.wallpaper_data.reset(new std::string(response));
200 StartDecode(*params_->details.wallpaper_data);