Add ENABLE_MEDIA_ROUTER define to builds other than Android and iOS.
[chromium-blink-merge.git] / chrome / browser / chromeos / extensions / wallpaper_api.cc
blobb57296cbe9e9082720133a02556926acabcec265
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 <string>
8 #include <vector>
10 #include "ash/desktop_background/desktop_background_controller.h"
11 #include "base/files/file_util.h"
12 #include "base/lazy_instance.h"
13 #include "base/prefs/pref_service.h"
14 #include "base/strings/stringprintf.h"
15 #include "base/threading/worker_pool.h"
16 #include "chrome/browser/browser_process.h"
17 #include "chrome/browser/chromeos/extensions/wallpaper_private_api.h"
18 #include "chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.h"
19 #include "chrome/browser/profiles/profile.h"
20 #include "chrome/common/chrome_paths.h"
21 #include "chrome/common/extensions/extension_constants.h"
22 #include "chrome/common/pref_names.h"
23 #include "components/user_manager/user.h"
24 #include "components/user_manager/user_manager.h"
25 #include "components/wallpaper/wallpaper_layout.h"
26 #include "extensions/browser/event_router.h"
27 #include "net/base/load_flags.h"
28 #include "net/http/http_status_code.h"
29 #include "net/url_request/url_fetcher.h"
30 #include "net/url_request/url_fetcher_delegate.h"
31 #include "url/gurl.h"
33 using base::BinaryValue;
34 using content::BrowserThread;
36 typedef base::Callback<void(bool success, const std::string&)> FetchCallback;
38 namespace set_wallpaper = extensions::api::wallpaper::SetWallpaper;
40 namespace {
42 class WallpaperFetcher : public net::URLFetcherDelegate {
43 public:
44 WallpaperFetcher() {}
46 ~WallpaperFetcher() override {}
48 void FetchWallpaper(const GURL& url, FetchCallback callback) {
49 CancelPreviousFetch();
50 callback_ = callback;
51 url_fetcher_.reset(net::URLFetcher::Create(url,
52 net::URLFetcher::GET,
53 this));
54 url_fetcher_->SetRequestContext(
55 g_browser_process->system_request_context());
56 url_fetcher_->SetLoadFlags(net::LOAD_DISABLE_CACHE);
57 url_fetcher_->Start();
60 private:
61 // URLFetcherDelegate overrides:
62 void OnURLFetchComplete(const net::URLFetcher* source) override {
63 DCHECK(url_fetcher_.get() == source);
65 bool success = source->GetStatus().is_success() &&
66 source->GetResponseCode() == net::HTTP_OK;
67 std::string response;
68 if (success) {
69 source->GetResponseAsString(&response);
70 } else {
71 response = base::StringPrintf(
72 "Downloading wallpaper %s failed. The response code is %d.",
73 source->GetOriginalURL().ExtractFileName().c_str(),
74 source->GetResponseCode());
76 url_fetcher_.reset();
77 callback_.Run(success, response);
78 callback_.Reset();
81 void CancelPreviousFetch() {
82 if (url_fetcher_.get()) {
83 callback_.Run(false, wallpaper_api_util::kCancelWallpaperMessage);
84 callback_.Reset();
85 url_fetcher_.reset();
89 scoped_ptr<net::URLFetcher> url_fetcher_;
90 FetchCallback callback_;
93 base::LazyInstance<WallpaperFetcher> g_wallpaper_fetcher =
94 LAZY_INSTANCE_INITIALIZER;
96 } // namespace
98 WallpaperSetWallpaperFunction::WallpaperSetWallpaperFunction() {
101 WallpaperSetWallpaperFunction::~WallpaperSetWallpaperFunction() {
104 bool WallpaperSetWallpaperFunction::RunAsync() {
105 DCHECK_CURRENTLY_ON(BrowserThread::UI);
106 params_ = set_wallpaper::Params::Create(*args_);
107 EXTENSION_FUNCTION_VALIDATE(params_);
109 // Gets email address and username hash while at UI thread.
110 user_id_ = user_manager::UserManager::Get()->GetLoggedInUser()->email();
111 user_id_hash_ =
112 user_manager::UserManager::Get()->GetLoggedInUser()->username_hash();
114 if (params_->details.data) {
115 StartDecode(*params_->details.data);
116 } else {
117 GURL wallpaper_url(*params_->details.url);
118 if (wallpaper_url.is_valid()) {
119 g_wallpaper_fetcher.Get().FetchWallpaper(
120 wallpaper_url,
121 base::Bind(&WallpaperSetWallpaperFunction::OnWallpaperFetched, this));
122 } else {
123 SetError("URL is invalid.");
124 SendResponse(false);
127 return true;
130 void WallpaperSetWallpaperFunction::OnWallpaperDecoded(
131 const gfx::ImageSkia& image) {
132 chromeos::WallpaperManager* wallpaper_manager =
133 chromeos::WallpaperManager::Get();
134 base::FilePath thumbnail_path = wallpaper_manager->GetCustomWallpaperPath(
135 wallpaper::kThumbnailWallpaperSubDir, user_id_hash_,
136 params_->details.filename);
138 sequence_token_ = BrowserThread::GetBlockingPool()->GetNamedSequenceToken(
139 wallpaper::kWallpaperSequenceTokenName);
140 scoped_refptr<base::SequencedTaskRunner> task_runner =
141 BrowserThread::GetBlockingPool()->
142 GetSequencedTaskRunnerWithShutdownBehavior(sequence_token_,
143 base::SequencedWorkerPool::BLOCK_SHUTDOWN);
144 wallpaper::WallpaperLayout layout = wallpaper_api_util::GetLayoutEnum(
145 extensions::api::wallpaper::ToString(params_->details.layout));
146 bool update_wallpaper =
147 user_id_ == user_manager::UserManager::Get()->GetActiveUser()->email();
148 wallpaper_manager->SetCustomWallpaper(user_id_,
149 user_id_hash_,
150 params_->details.filename,
151 layout,
152 user_manager::User::CUSTOMIZED,
153 image,
154 update_wallpaper);
155 unsafe_wallpaper_decoder_ = NULL;
157 if (params_->details.thumbnail) {
158 image.EnsureRepsForSupportedScales();
159 scoped_ptr<gfx::ImageSkia> deep_copy(image.DeepCopy());
160 // Generates thumbnail before call api function callback. We can then
161 // request thumbnail in the javascript callback.
162 task_runner->PostTask(
163 FROM_HERE,
164 base::Bind(&WallpaperSetWallpaperFunction::GenerateThumbnail,
165 this,
166 thumbnail_path,
167 base::Passed(deep_copy.Pass())));
168 } else {
169 // Save current extenion name. It will be displayed in the component
170 // wallpaper picker app. If current extension is the component wallpaper
171 // picker, set an empty string.
172 Profile* profile = Profile::FromBrowserContext(browser_context());
173 if (extension()->id() == extension_misc::kWallpaperManagerId) {
174 profile->GetPrefs()->SetString(prefs::kCurrentWallpaperAppName,
175 std::string());
176 } else {
177 profile->GetPrefs()->SetString(prefs::kCurrentWallpaperAppName,
178 extension()->name());
180 SendResponse(true);
183 // Inform the native Wallpaper Picker Application that the current wallpaper
184 // has been modified by a third party application.
185 Profile* profile = Profile::FromBrowserContext(browser_context());
186 extensions::EventRouter* event_router = extensions::EventRouter::Get(profile);
187 scoped_ptr<base::ListValue> event_args(new base::ListValue());
188 scoped_ptr<extensions::Event> event(
189 new extensions::Event(extensions::api::wallpaper_private::
190 OnWallpaperChangedBy3rdParty::kEventName,
191 event_args.Pass()));
192 event_router->DispatchEventToExtension(extension_misc::kWallpaperManagerId,
193 event.Pass());
196 void WallpaperSetWallpaperFunction::GenerateThumbnail(
197 const base::FilePath& thumbnail_path, scoped_ptr<gfx::ImageSkia> image) {
198 DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
199 sequence_token_));
200 if (!base::PathExists(thumbnail_path.DirName()))
201 base::CreateDirectory(thumbnail_path.DirName());
203 scoped_refptr<base::RefCountedBytes> data;
204 chromeos::WallpaperManager::Get()->ResizeImage(
205 *image, wallpaper::WALLPAPER_LAYOUT_STRETCH,
206 wallpaper::kWallpaperThumbnailWidth, wallpaper::kWallpaperThumbnailHeight,
207 &data, NULL);
208 BrowserThread::PostTask(
209 BrowserThread::UI, FROM_HERE,
210 base::Bind(
211 &WallpaperSetWallpaperFunction::ThumbnailGenerated,
212 this, data));
215 void WallpaperSetWallpaperFunction::ThumbnailGenerated(
216 base::RefCountedBytes* data) {
217 BinaryValue* result = BinaryValue::CreateWithCopiedBuffer(
218 reinterpret_cast<const char*>(data->front()), data->size());
219 SetResult(result);
220 SendResponse(true);
223 void WallpaperSetWallpaperFunction::OnWallpaperFetched(
224 bool success,
225 const std::string& response) {
226 if (success) {
227 params_->details.data.reset(
228 new std::vector<char>(response.begin(), response.end()));
229 StartDecode(*params_->details.data);
230 } else {
231 SetError(response);
232 SendResponse(false);