Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / chromeos / extensions / wallpaper_private_api.cc
blobc4b71df1480dcb7c07826893164ab3ed70870723
1 // Copyright (c) 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_private_api.h"
7 #include <vector>
9 #include "ash/ash_switches.h"
10 #include "ash/desktop_background/desktop_background_controller.h"
11 #include "ash/shell.h"
12 #include "ash/wm/mru_window_tracker.h"
13 #include "ash/wm/window_state.h"
14 #include "ash/wm/window_util.h"
15 #include "base/command_line.h"
16 #include "base/file_util.h"
17 #include "base/files/file_enumerator.h"
18 #include "base/memory/scoped_ptr.h"
19 #include "base/path_service.h"
20 #include "base/strings/string_number_conversions.h"
21 #include "base/strings/stringprintf.h"
22 #include "base/threading/worker_pool.h"
23 #include "chrome/browser/browser_process.h"
24 #include "chrome/browser/chromeos/login/user.h"
25 #include "chrome/browser/chromeos/login/user_image.h"
26 #include "chrome/browser/chromeos/login/user_manager.h"
27 #include "chrome/browser/chromeos/login/wallpaper_manager.h"
28 #include "chrome/common/chrome_paths.h"
29 #include "content/public/browser/browser_thread.h"
30 #include "extensions/browser/event_router.h"
31 #include "grit/app_locale_settings.h"
32 #include "grit/generated_resources.h"
33 #include "grit/platform_locale_settings.h"
34 #include "ui/base/l10n/l10n_util.h"
35 #include "ui/base/webui/web_ui_util.h"
36 #include "url/gurl.h"
38 using base::BinaryValue;
39 using content::BrowserThread;
40 namespace wallpaper_private = extensions::api::wallpaper_private;
41 namespace set_wallpaper_if_exists = wallpaper_private::SetWallpaperIfExists;
42 namespace set_wallpaper = wallpaper_private::SetWallpaper;
43 namespace set_custom_wallpaper = wallpaper_private::SetCustomWallpaper;
44 namespace set_custom_wallpaper_layout =
45 wallpaper_private::SetCustomWallpaperLayout;
46 namespace get_thumbnail = wallpaper_private::GetThumbnail;
47 namespace save_thumbnail = wallpaper_private::SaveThumbnail;
48 namespace get_offline_wallpaper_list =
49 wallpaper_private::GetOfflineWallpaperList;
51 namespace {
53 #if defined(GOOGLE_CHROME_BUILD)
54 const char kWallpaperManifestBaseURL[] = "https://commondatastorage.googleapis."
55 "com/chromeos-wallpaper-public/manifest_";
56 #endif
58 bool IsOEMDefaultWallpaper() {
59 return CommandLine::ForCurrentProcess()->HasSwitch(
60 ash::switches::kAshDefaultWallpaperIsOem);
63 // Saves |data| as |file_name| to directory with |key|. Return false if the
64 // directory can not be found/created or failed to write file.
65 bool SaveData(int key, const std::string& file_name, const std::string& data) {
66 base::FilePath data_dir;
67 CHECK(PathService::Get(key, &data_dir));
68 if (!base::DirectoryExists(data_dir) &&
69 !base::CreateDirectory(data_dir)) {
70 return false;
72 base::FilePath file_path = data_dir.Append(file_name);
74 return base::PathExists(file_path) ||
75 (file_util::WriteFile(file_path, data.c_str(),
76 data.size()) != -1);
79 // Gets |file_name| from directory with |key|. Return false if the directory can
80 // not be found or failed to read file to string |data|. Note if the |file_name|
81 // can not be found in the directory, return true with empty |data|. It is
82 // expected that we may try to access file which did not saved yet.
83 bool GetData(const base::FilePath& path, std::string* data) {
84 base::FilePath data_dir = path.DirName();
85 if (!base::DirectoryExists(data_dir) &&
86 !base::CreateDirectory(data_dir))
87 return false;
89 return !base::PathExists(path) ||
90 base::ReadFileToString(path, data);
93 // WindowStateManager remembers which windows have been minimized in order to
94 // restore them when the wallpaper viewer is hidden.
95 class WindowStateManager : public aura::WindowObserver {
96 public:
97 typedef std::map<std::string, std::set<aura::Window*> >
98 UserIDHashWindowListMap;
100 // Minimizes all windows except the active window.
101 static void MinimizeInactiveWindows(const std::string& user_id_hash);
103 // Unminimizes all minimized windows restoring them to their previous state.
104 // This should only be called after calling MinimizeInactiveWindows.
105 static void RestoreWindows(const std::string& user_id_hash);
107 private:
108 WindowStateManager();
110 virtual ~WindowStateManager();
112 // Store all unminimized windows except |active_window| and minimize them.
113 // All the windows are saved in a map and the key value is |user_id_hash|.
114 void BuildWindowListAndMinimizeInactiveForUser(
115 const std::string& user_id_hash, aura::Window* active_window);
117 // Unminimize all the stored windows for |user_id_hash|.
118 void RestoreMinimizedWindows(const std::string& user_id_hash);
120 // Remove the observer from |window| if |window| is no longer referenced in
121 // user_id_hash_window_list_map_.
122 void RemoveObserverIfUnreferenced(aura::Window* window);
124 // aura::WindowObserver overrides.
125 virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE;
127 // Map of user id hash and associated list of minimized windows.
128 UserIDHashWindowListMap user_id_hash_window_list_map_;
130 DISALLOW_COPY_AND_ASSIGN(WindowStateManager);
133 // static
134 WindowStateManager* g_window_state_manager = NULL;
136 // static
137 void WindowStateManager::MinimizeInactiveWindows(
138 const std::string& user_id_hash) {
139 if (!g_window_state_manager)
140 g_window_state_manager = new WindowStateManager();
141 g_window_state_manager->BuildWindowListAndMinimizeInactiveForUser(
142 user_id_hash, ash::wm::GetActiveWindow());
145 // static
146 void WindowStateManager::RestoreWindows(const std::string& user_id_hash) {
147 if (!g_window_state_manager) {
148 DCHECK(false) << "This should only be called after calling "
149 << "MinimizeInactiveWindows.";
150 return;
153 g_window_state_manager->RestoreMinimizedWindows(user_id_hash);
154 if (g_window_state_manager->user_id_hash_window_list_map_.empty()) {
155 delete g_window_state_manager;
156 g_window_state_manager = NULL;
160 WindowStateManager::WindowStateManager() {}
162 WindowStateManager::~WindowStateManager() {}
164 void WindowStateManager::BuildWindowListAndMinimizeInactiveForUser(
165 const std::string& user_id_hash, aura::Window* active_window) {
166 if (user_id_hash_window_list_map_.find(user_id_hash) ==
167 user_id_hash_window_list_map_.end()) {
168 user_id_hash_window_list_map_[user_id_hash] = std::set<aura::Window*>();
170 std::set<aura::Window*>* results =
171 &user_id_hash_window_list_map_[user_id_hash];
173 std::vector<aura::Window*> windows =
174 ash::MruWindowTracker::BuildWindowList(false);
176 for (std::vector<aura::Window*>::iterator iter = windows.begin();
177 iter != windows.end(); ++iter) {
178 // Ignore active window and minimized windows.
179 if (*iter == active_window || ash::wm::GetWindowState(*iter)->IsMinimized())
180 continue;
182 // TODO(bshe): Add WindowStateObserver too. http://crbug.com/323252
183 if (!(*iter)->HasObserver(this))
184 (*iter)->AddObserver(this);
186 results->insert(*iter);
187 ash::wm::GetWindowState(*iter)->Minimize();
191 void WindowStateManager::RestoreMinimizedWindows(
192 const std::string& user_id_hash) {
193 UserIDHashWindowListMap::iterator it =
194 user_id_hash_window_list_map_.find(user_id_hash);
195 if (it == user_id_hash_window_list_map_.end()) {
196 DCHECK(false) << "This should only be called after calling "
197 << "MinimizeInactiveWindows.";
198 return;
201 std::set<aura::Window*> removed_windows;
202 removed_windows.swap(it->second);
203 user_id_hash_window_list_map_.erase(it);
205 for (std::set<aura::Window*>::iterator iter = removed_windows.begin();
206 iter != removed_windows.end(); ++iter) {
207 ash::wm::GetWindowState(*iter)->Unminimize();
208 RemoveObserverIfUnreferenced(*iter);
212 void WindowStateManager::RemoveObserverIfUnreferenced(aura::Window* window) {
213 for (UserIDHashWindowListMap::iterator iter =
214 user_id_hash_window_list_map_.begin();
215 iter != user_id_hash_window_list_map_.end();
216 ++iter) {
217 if (iter->second.find(window) != iter->second.end())
218 return;
220 // Remove observer if |window| is not observed by any users.
221 window->RemoveObserver(this);
224 void WindowStateManager::OnWindowDestroyed(aura::Window* window) {
225 for (UserIDHashWindowListMap::iterator iter =
226 user_id_hash_window_list_map_.begin();
227 iter != user_id_hash_window_list_map_.end();
228 ++iter) {
229 iter->second.erase(window);
233 } // namespace
235 bool WallpaperPrivateGetStringsFunction::RunImpl() {
236 base::DictionaryValue* dict = new base::DictionaryValue();
237 SetResult(dict);
239 #define SET_STRING(id, idr) \
240 dict->SetString(id, l10n_util::GetStringUTF16(idr))
241 SET_STRING("webFontFamily", IDS_WEB_FONT_FAMILY);
242 SET_STRING("webFontSize", IDS_WEB_FONT_SIZE);
243 SET_STRING("allCategoryLabel", IDS_WALLPAPER_MANAGER_ALL_CATEGORY_LABEL);
244 SET_STRING("deleteCommandLabel", IDS_WALLPAPER_MANAGER_DELETE_COMMAND_LABEL);
245 SET_STRING("customCategoryLabel",
246 IDS_WALLPAPER_MANAGER_CUSTOM_CATEGORY_LABEL);
247 SET_STRING("selectCustomLabel",
248 IDS_WALLPAPER_MANAGER_SELECT_CUSTOM_LABEL);
249 SET_STRING("positionLabel", IDS_WALLPAPER_MANAGER_POSITION_LABEL);
250 SET_STRING("colorLabel", IDS_WALLPAPER_MANAGER_COLOR_LABEL);
251 SET_STRING("centerCroppedLayout",
252 IDS_OPTIONS_WALLPAPER_CENTER_CROPPED_LAYOUT);
253 SET_STRING("centerLayout", IDS_OPTIONS_WALLPAPER_CENTER_LAYOUT);
254 SET_STRING("stretchLayout", IDS_OPTIONS_WALLPAPER_STRETCH_LAYOUT);
255 SET_STRING("connectionFailed", IDS_WALLPAPER_MANAGER_ACCESS_FAIL);
256 SET_STRING("downloadFailed", IDS_WALLPAPER_MANAGER_DOWNLOAD_FAIL);
257 SET_STRING("downloadCanceled", IDS_WALLPAPER_MANAGER_DOWNLOAD_CANCEL);
258 SET_STRING("customWallpaperWarning",
259 IDS_WALLPAPER_MANAGER_SHOW_CUSTOM_WALLPAPER_ON_START_WARNING);
260 SET_STRING("accessFileFailure", IDS_WALLPAPER_MANAGER_ACCESS_FILE_FAILURE);
261 SET_STRING("invalidWallpaper", IDS_WALLPAPER_MANAGER_INVALID_WALLPAPER);
262 SET_STRING("surpriseMeLabel", IDS_WALLPAPER_MANAGER_SURPRISE_ME_LABEL);
263 SET_STRING("learnMore", IDS_LEARN_MORE);
264 #undef SET_STRING
266 webui::SetFontAndTextDirection(dict);
268 chromeos::WallpaperManager* wallpaper_manager =
269 chromeos::WallpaperManager::Get();
270 chromeos::WallpaperInfo info;
272 if (wallpaper_manager->GetLoggedInUserWallpaperInfo(&info))
273 dict->SetString("currentWallpaper", info.file);
275 #if defined(GOOGLE_CHROME_BUILD)
276 dict->SetString("manifestBaseURL", kWallpaperManifestBaseURL);
277 #endif
279 dict->SetBoolean("isOEMDefaultWallpaper", IsOEMDefaultWallpaper());
280 return true;
283 WallpaperPrivateSetWallpaperIfExistsFunction::
284 WallpaperPrivateSetWallpaperIfExistsFunction() {}
286 WallpaperPrivateSetWallpaperIfExistsFunction::
287 ~WallpaperPrivateSetWallpaperIfExistsFunction() {}
289 bool WallpaperPrivateSetWallpaperIfExistsFunction::RunImpl() {
290 params = set_wallpaper_if_exists::Params::Create(*args_);
291 EXTENSION_FUNCTION_VALIDATE(params);
293 std::string email = chromeos::UserManager::Get()->GetLoggedInUser()->email();
295 base::FilePath wallpaper_path;
296 base::FilePath fallback_path;
297 ash::WallpaperResolution resolution = ash::Shell::GetInstance()->
298 desktop_background_controller()->GetAppropriateResolution();
300 std::string file_name = GURL(params->url).ExtractFileName();
301 CHECK(PathService::Get(chrome::DIR_CHROMEOS_WALLPAPERS,
302 &wallpaper_path));
303 fallback_path = wallpaper_path.Append(file_name);
304 if (params->layout != wallpaper_private::WALLPAPER_LAYOUT_STRETCH &&
305 resolution == ash::WALLPAPER_RESOLUTION_SMALL) {
306 file_name = base::FilePath(file_name).InsertBeforeExtension(
307 chromeos::kSmallWallpaperSuffix).value();
309 wallpaper_path = wallpaper_path.Append(file_name);
311 sequence_token_ = BrowserThread::GetBlockingPool()->
312 GetNamedSequenceToken(chromeos::kWallpaperSequenceTokenName);
313 scoped_refptr<base::SequencedTaskRunner> task_runner =
314 BrowserThread::GetBlockingPool()->
315 GetSequencedTaskRunnerWithShutdownBehavior(sequence_token_,
316 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN);
318 task_runner->PostTask(FROM_HERE,
319 base::Bind(
320 &WallpaperPrivateSetWallpaperIfExistsFunction::
321 ReadFileAndInitiateStartDecode,
322 this, wallpaper_path, fallback_path));
323 return true;
326 void WallpaperPrivateSetWallpaperIfExistsFunction::
327 ReadFileAndInitiateStartDecode(const base::FilePath& file_path,
328 const base::FilePath& fallback_path) {
329 DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
330 sequence_token_));
331 std::string data;
332 base::FilePath path = file_path;
334 if (!base::PathExists(file_path))
335 path = fallback_path;
337 if (base::PathExists(path) &&
338 base::ReadFileToString(path, &data)) {
339 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
340 base::Bind(&WallpaperPrivateSetWallpaperIfExistsFunction::StartDecode,
341 this, data));
342 return;
344 std::string error = base::StringPrintf(
345 "Failed to set wallpaper %s from file system.",
346 path.BaseName().value().c_str());
347 BrowserThread::PostTask(
348 BrowserThread::UI, FROM_HERE,
349 base::Bind(&WallpaperPrivateSetWallpaperIfExistsFunction::OnFileNotExists,
350 this, error));
353 void WallpaperPrivateSetWallpaperIfExistsFunction::OnWallpaperDecoded(
354 const gfx::ImageSkia& wallpaper) {
355 // Set unsafe_wallpaper_decoder_ to null since the decoding already finished.
356 unsafe_wallpaper_decoder_ = NULL;
358 chromeos::WallpaperManager* wallpaper_manager =
359 chromeos::WallpaperManager::Get();
360 ash::WallpaperLayout layout = wallpaper_api_util::GetLayoutEnum(
361 wallpaper_private::ToString(params->layout));
363 wallpaper_manager->SetWallpaperFromImageSkia(wallpaper, layout);
364 bool is_persistent =
365 !chromeos::UserManager::Get()->IsCurrentUserNonCryptohomeDataEphemeral();
366 chromeos::WallpaperInfo info = {
367 params->url,
368 layout,
369 chromeos::User::ONLINE,
370 base::Time::Now().LocalMidnight()
372 std::string email = chromeos::UserManager::Get()->GetLoggedInUser()->email();
373 wallpaper_manager->SetUserWallpaperInfo(email, info, is_persistent);
374 SetResult(base::Value::CreateBooleanValue(true));
375 SendResponse(true);
378 void WallpaperPrivateSetWallpaperIfExistsFunction::OnFileNotExists(
379 const std::string& error) {
380 SetResult(base::Value::CreateBooleanValue(false));
381 OnFailure(error);
384 WallpaperPrivateSetWallpaperFunction::WallpaperPrivateSetWallpaperFunction() {
387 WallpaperPrivateSetWallpaperFunction::~WallpaperPrivateSetWallpaperFunction() {
390 bool WallpaperPrivateSetWallpaperFunction::RunImpl() {
391 params = set_wallpaper::Params::Create(*args_);
392 EXTENSION_FUNCTION_VALIDATE(params);
394 // Gets email address while at UI thread.
395 email_ = chromeos::UserManager::Get()->GetLoggedInUser()->email();
397 StartDecode(params->wallpaper);
399 return true;
402 void WallpaperPrivateSetWallpaperFunction::OnWallpaperDecoded(
403 const gfx::ImageSkia& wallpaper) {
404 wallpaper_ = wallpaper;
405 // Set unsafe_wallpaper_decoder_ to null since the decoding already finished.
406 unsafe_wallpaper_decoder_ = NULL;
408 sequence_token_ = BrowserThread::GetBlockingPool()->
409 GetNamedSequenceToken(chromeos::kWallpaperSequenceTokenName);
410 scoped_refptr<base::SequencedTaskRunner> task_runner =
411 BrowserThread::GetBlockingPool()->
412 GetSequencedTaskRunnerWithShutdownBehavior(sequence_token_,
413 base::SequencedWorkerPool::BLOCK_SHUTDOWN);
415 task_runner->PostTask(FROM_HERE,
416 base::Bind(&WallpaperPrivateSetWallpaperFunction::SaveToFile, this));
419 void WallpaperPrivateSetWallpaperFunction::SaveToFile() {
420 DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
421 sequence_token_));
422 std::string file_name = GURL(params->url).ExtractFileName();
423 if (SaveData(chrome::DIR_CHROMEOS_WALLPAPERS, file_name, params->wallpaper)) {
424 wallpaper_.EnsureRepsForSupportedScales();
425 scoped_ptr<gfx::ImageSkia> deep_copy(wallpaper_.DeepCopy());
426 // ImageSkia is not RefCountedThreadSafe. Use a deep copied ImageSkia if
427 // post to another thread.
428 BrowserThread::PostTask(
429 BrowserThread::UI, FROM_HERE,
430 base::Bind(&WallpaperPrivateSetWallpaperFunction::SetDecodedWallpaper,
431 this, base::Passed(&deep_copy)));
432 chromeos::UserImage wallpaper(wallpaper_);
434 base::FilePath wallpaper_dir;
435 CHECK(PathService::Get(chrome::DIR_CHROMEOS_WALLPAPERS, &wallpaper_dir));
436 base::FilePath file_path = wallpaper_dir.Append(
437 file_name).InsertBeforeExtension(chromeos::kSmallWallpaperSuffix);
438 if (base::PathExists(file_path))
439 return;
440 // Generates and saves small resolution wallpaper. Uses CENTER_CROPPED to
441 // maintain the aspect ratio after resize.
442 chromeos::WallpaperManager::Get()->ResizeAndSaveWallpaper(
443 wallpaper,
444 file_path,
445 ash::WALLPAPER_LAYOUT_CENTER_CROPPED,
446 ash::kSmallWallpaperMaxWidth,
447 ash::kSmallWallpaperMaxHeight);
448 } else {
449 std::string error = base::StringPrintf(
450 "Failed to create/write wallpaper to %s.", file_name.c_str());
451 BrowserThread::PostTask(
452 BrowserThread::UI, FROM_HERE,
453 base::Bind(&WallpaperPrivateSetWallpaperFunction::OnFailure,
454 this, error));
458 void WallpaperPrivateSetWallpaperFunction::SetDecodedWallpaper(
459 scoped_ptr<gfx::ImageSkia> wallpaper) {
460 chromeos::WallpaperManager* wallpaper_manager =
461 chromeos::WallpaperManager::Get();
463 ash::WallpaperLayout layout = wallpaper_api_util::GetLayoutEnum(
464 wallpaper_private::ToString(params->layout));
466 wallpaper_manager->SetWallpaperFromImageSkia(*wallpaper.get(), layout);
467 bool is_persistent =
468 !chromeos::UserManager::Get()->IsCurrentUserNonCryptohomeDataEphemeral();
469 chromeos::WallpaperInfo info = {
470 params->url,
471 layout,
472 chromeos::User::ONLINE,
473 base::Time::Now().LocalMidnight()
475 wallpaper_manager->SetUserWallpaperInfo(email_, info, is_persistent);
476 SendResponse(true);
479 WallpaperPrivateResetWallpaperFunction::
480 WallpaperPrivateResetWallpaperFunction() {}
482 WallpaperPrivateResetWallpaperFunction::
483 ~WallpaperPrivateResetWallpaperFunction() {}
485 bool WallpaperPrivateResetWallpaperFunction::RunImpl() {
486 chromeos::WallpaperManager* wallpaper_manager =
487 chromeos::WallpaperManager::Get();
488 chromeos::UserManager* user_manager = chromeos::UserManager::Get();
490 std::string email = user_manager->GetLoggedInUser()->email();
491 wallpaper_manager->RemoveUserWallpaperInfo(email);
493 chromeos::WallpaperInfo info = {
495 ash::WALLPAPER_LAYOUT_CENTER,
496 chromeos::User::DEFAULT,
497 base::Time::Now().LocalMidnight()
499 bool is_persistent =
500 !user_manager->IsCurrentUserNonCryptohomeDataEphemeral();
501 wallpaper_manager->SetUserWallpaperInfo(email, info, is_persistent);
502 wallpaper_manager->SetDefaultWallpaper();
503 return true;
506 WallpaperPrivateSetCustomWallpaperFunction::
507 WallpaperPrivateSetCustomWallpaperFunction() {}
509 WallpaperPrivateSetCustomWallpaperFunction::
510 ~WallpaperPrivateSetCustomWallpaperFunction() {}
512 bool WallpaperPrivateSetCustomWallpaperFunction::RunImpl() {
513 params = set_custom_wallpaper::Params::Create(*args_);
514 EXTENSION_FUNCTION_VALIDATE(params);
516 // Gets email address and username hash while at UI thread.
517 email_ = chromeos::UserManager::Get()->GetLoggedInUser()->email();
518 user_id_hash_ =
519 chromeos::UserManager::Get()->GetLoggedInUser()->username_hash();
521 StartDecode(params->wallpaper);
523 return true;
526 void WallpaperPrivateSetCustomWallpaperFunction::OnWallpaperDecoded(
527 const gfx::ImageSkia& wallpaper) {
528 chromeos::WallpaperManager* wallpaper_manager =
529 chromeos::WallpaperManager::Get();
530 chromeos::UserImage::RawImage raw_image(params->wallpaper.begin(),
531 params->wallpaper.end());
532 chromeos::UserImage image(wallpaper, raw_image);
533 base::FilePath thumbnail_path = wallpaper_manager->GetCustomWallpaperPath(
534 chromeos::kThumbnailWallpaperSubDir, user_id_hash_, params->file_name);
536 sequence_token_ = BrowserThread::GetBlockingPool()->
537 GetNamedSequenceToken(chromeos::kWallpaperSequenceTokenName);
538 scoped_refptr<base::SequencedTaskRunner> task_runner =
539 BrowserThread::GetBlockingPool()->
540 GetSequencedTaskRunnerWithShutdownBehavior(sequence_token_,
541 base::SequencedWorkerPool::BLOCK_SHUTDOWN);
543 ash::WallpaperLayout layout = wallpaper_api_util::GetLayoutEnum(
544 wallpaper_private::ToString(params->layout));
546 wallpaper_manager->SetCustomWallpaper(email_,
547 user_id_hash_,
548 params->file_name,
549 layout,
550 chromeos::User::CUSTOMIZED,
551 image);
552 unsafe_wallpaper_decoder_ = NULL;
554 if (params->generate_thumbnail) {
555 wallpaper.EnsureRepsForSupportedScales();
556 scoped_ptr<gfx::ImageSkia> deep_copy(wallpaper.DeepCopy());
557 // Generates thumbnail before call api function callback. We can then
558 // request thumbnail in the javascript callback.
559 task_runner->PostTask(FROM_HERE,
560 base::Bind(
561 &WallpaperPrivateSetCustomWallpaperFunction::GenerateThumbnail,
562 this, thumbnail_path, base::Passed(&deep_copy)));
563 } else {
564 SendResponse(true);
568 void WallpaperPrivateSetCustomWallpaperFunction::GenerateThumbnail(
569 const base::FilePath& thumbnail_path, scoped_ptr<gfx::ImageSkia> image) {
570 DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
571 sequence_token_));
572 chromeos::UserImage wallpaper(*image.get());
573 if (!base::PathExists(thumbnail_path.DirName()))
574 base::CreateDirectory(thumbnail_path.DirName());
576 scoped_refptr<base::RefCountedBytes> data;
577 chromeos::WallpaperManager::Get()->ResizeWallpaper(
578 wallpaper,
579 ash::WALLPAPER_LAYOUT_STRETCH,
580 ash::kWallpaperThumbnailWidth,
581 ash::kWallpaperThumbnailHeight,
582 &data);
583 BrowserThread::PostTask(
584 BrowserThread::UI, FROM_HERE,
585 base::Bind(
586 &WallpaperPrivateSetCustomWallpaperFunction::ThumbnailGenerated,
587 this, data));
590 void WallpaperPrivateSetCustomWallpaperFunction::ThumbnailGenerated(
591 base::RefCountedBytes* data) {
592 BinaryValue* result = BinaryValue::CreateWithCopiedBuffer(
593 reinterpret_cast<const char*>(data->front()), data->size());
594 SetResult(result);
595 SendResponse(true);
598 WallpaperPrivateSetCustomWallpaperLayoutFunction::
599 WallpaperPrivateSetCustomWallpaperLayoutFunction() {}
601 WallpaperPrivateSetCustomWallpaperLayoutFunction::
602 ~WallpaperPrivateSetCustomWallpaperLayoutFunction() {}
604 bool WallpaperPrivateSetCustomWallpaperLayoutFunction::RunImpl() {
605 scoped_ptr<set_custom_wallpaper_layout::Params> params(
606 set_custom_wallpaper_layout::Params::Create(*args_));
607 EXTENSION_FUNCTION_VALIDATE(params);
609 chromeos::WallpaperManager* wallpaper_manager =
610 chromeos::WallpaperManager::Get();
611 chromeos::WallpaperInfo info;
612 wallpaper_manager->GetLoggedInUserWallpaperInfo(&info);
613 if (info.type != chromeos::User::CUSTOMIZED) {
614 SetError("Only custom wallpaper can change layout.");
615 SendResponse(false);
616 return false;
618 info.layout = wallpaper_api_util::GetLayoutEnum(
619 wallpaper_private::ToString(params->layout));
621 std::string email = chromeos::UserManager::Get()->GetLoggedInUser()->email();
622 bool is_persistent =
623 !chromeos::UserManager::Get()->IsCurrentUserNonCryptohomeDataEphemeral();
624 wallpaper_manager->SetUserWallpaperInfo(email, info, is_persistent);
625 wallpaper_manager->UpdateWallpaper();
626 SendResponse(true);
628 // Gets email address while at UI thread.
629 return true;
632 WallpaperPrivateMinimizeInactiveWindowsFunction::
633 WallpaperPrivateMinimizeInactiveWindowsFunction() {
636 WallpaperPrivateMinimizeInactiveWindowsFunction::
637 ~WallpaperPrivateMinimizeInactiveWindowsFunction() {
640 bool WallpaperPrivateMinimizeInactiveWindowsFunction::RunImpl() {
641 WindowStateManager::MinimizeInactiveWindows(
642 chromeos::UserManager::Get()->GetActiveUser()->username_hash());
643 return true;
646 WallpaperPrivateRestoreMinimizedWindowsFunction::
647 WallpaperPrivateRestoreMinimizedWindowsFunction() {
650 WallpaperPrivateRestoreMinimizedWindowsFunction::
651 ~WallpaperPrivateRestoreMinimizedWindowsFunction() {
654 bool WallpaperPrivateRestoreMinimizedWindowsFunction::RunImpl() {
655 WindowStateManager::RestoreWindows(
656 chromeos::UserManager::Get()->GetActiveUser()->username_hash());
657 return true;
660 WallpaperPrivateGetThumbnailFunction::WallpaperPrivateGetThumbnailFunction() {
663 WallpaperPrivateGetThumbnailFunction::~WallpaperPrivateGetThumbnailFunction() {
666 bool WallpaperPrivateGetThumbnailFunction::RunImpl() {
667 scoped_ptr<get_thumbnail::Params> params(
668 get_thumbnail::Params::Create(*args_));
669 EXTENSION_FUNCTION_VALIDATE(params);
671 base::FilePath thumbnail_path;
672 std::string email = chromeos::UserManager::Get()->GetLoggedInUser()->email();
673 if (params->source == get_thumbnail::Params::SOURCE_ONLINE) {
674 std::string file_name = GURL(params->url_or_file).ExtractFileName();
675 CHECK(PathService::Get(chrome::DIR_CHROMEOS_WALLPAPER_THUMBNAILS,
676 &thumbnail_path));
677 thumbnail_path = thumbnail_path.Append(file_name);
678 } else {
679 if (!IsOEMDefaultWallpaper()) {
680 SetError("No OEM wallpaper.");
681 SendResponse(false);
682 return false;
685 // TODO(bshe): Small resolution wallpaper is used here as wallpaper
686 // thumbnail. We should either resize it or include a wallpaper thumbnail in
687 // addition to large and small wallpaper resolutions.
688 thumbnail_path = CommandLine::ForCurrentProcess()->GetSwitchValuePath(
689 ash::switches::kAshDefaultWallpaperSmall);
692 sequence_token_ = BrowserThread::GetBlockingPool()->
693 GetNamedSequenceToken(chromeos::kWallpaperSequenceTokenName);
694 scoped_refptr<base::SequencedTaskRunner> task_runner =
695 BrowserThread::GetBlockingPool()->
696 GetSequencedTaskRunnerWithShutdownBehavior(sequence_token_,
697 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN);
699 task_runner->PostTask(FROM_HERE,
700 base::Bind(&WallpaperPrivateGetThumbnailFunction::Get, this,
701 thumbnail_path));
702 return true;
705 void WallpaperPrivateGetThumbnailFunction::Failure(
706 const std::string& file_name) {
707 SetError(base::StringPrintf("Failed to access wallpaper thumbnails for %s.",
708 file_name.c_str()));
709 SendResponse(false);
712 void WallpaperPrivateGetThumbnailFunction::FileNotLoaded() {
713 SendResponse(true);
716 void WallpaperPrivateGetThumbnailFunction::FileLoaded(
717 const std::string& data) {
718 BinaryValue* thumbnail = BinaryValue::CreateWithCopiedBuffer(data.c_str(),
719 data.size());
720 SetResult(thumbnail);
721 SendResponse(true);
724 void WallpaperPrivateGetThumbnailFunction::Get(const base::FilePath& path) {
725 DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
726 sequence_token_));
727 std::string data;
728 if (GetData(path, &data)) {
729 if (data.empty()) {
730 BrowserThread::PostTask(
731 BrowserThread::UI, FROM_HERE,
732 base::Bind(&WallpaperPrivateGetThumbnailFunction::FileNotLoaded, this));
733 } else {
734 BrowserThread::PostTask(
735 BrowserThread::UI, FROM_HERE,
736 base::Bind(&WallpaperPrivateGetThumbnailFunction::FileLoaded, this,
737 data));
739 } else {
740 BrowserThread::PostTask(
741 BrowserThread::UI, FROM_HERE,
742 base::Bind(&WallpaperPrivateGetThumbnailFunction::Failure, this,
743 path.BaseName().value()));
747 WallpaperPrivateSaveThumbnailFunction::WallpaperPrivateSaveThumbnailFunction() {
750 WallpaperPrivateSaveThumbnailFunction::
751 ~WallpaperPrivateSaveThumbnailFunction() {}
753 bool WallpaperPrivateSaveThumbnailFunction::RunImpl() {
754 scoped_ptr<save_thumbnail::Params> params(
755 save_thumbnail::Params::Create(*args_));
756 EXTENSION_FUNCTION_VALIDATE(params);
758 sequence_token_ = BrowserThread::GetBlockingPool()->
759 GetNamedSequenceToken(chromeos::kWallpaperSequenceTokenName);
760 scoped_refptr<base::SequencedTaskRunner> task_runner =
761 BrowserThread::GetBlockingPool()->
762 GetSequencedTaskRunnerWithShutdownBehavior(sequence_token_,
763 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN);
765 task_runner->PostTask(FROM_HERE,
766 base::Bind(&WallpaperPrivateSaveThumbnailFunction::Save,
767 this, params->data, GURL(params->url).ExtractFileName()));
768 return true;
771 void WallpaperPrivateSaveThumbnailFunction::Failure(
772 const std::string& file_name) {
773 SetError(base::StringPrintf("Failed to create/write thumbnail of %s.",
774 file_name.c_str()));
775 SendResponse(false);
778 void WallpaperPrivateSaveThumbnailFunction::Success() {
779 SendResponse(true);
782 void WallpaperPrivateSaveThumbnailFunction::Save(const std::string& data,
783 const std::string& file_name) {
784 DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
785 sequence_token_));
786 if (SaveData(chrome::DIR_CHROMEOS_WALLPAPER_THUMBNAILS, file_name, data)) {
787 BrowserThread::PostTask(
788 BrowserThread::UI, FROM_HERE,
789 base::Bind(&WallpaperPrivateSaveThumbnailFunction::Success, this));
790 } else {
791 BrowserThread::PostTask(
792 BrowserThread::UI, FROM_HERE,
793 base::Bind(&WallpaperPrivateSaveThumbnailFunction::Failure,
794 this, file_name));
798 WallpaperPrivateGetOfflineWallpaperListFunction::
799 WallpaperPrivateGetOfflineWallpaperListFunction() {
802 WallpaperPrivateGetOfflineWallpaperListFunction::
803 ~WallpaperPrivateGetOfflineWallpaperListFunction() {
806 bool WallpaperPrivateGetOfflineWallpaperListFunction::RunImpl() {
807 sequence_token_ = BrowserThread::GetBlockingPool()->
808 GetNamedSequenceToken(chromeos::kWallpaperSequenceTokenName);
809 scoped_refptr<base::SequencedTaskRunner> task_runner =
810 BrowserThread::GetBlockingPool()->
811 GetSequencedTaskRunnerWithShutdownBehavior(sequence_token_,
812 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN);
814 task_runner->PostTask(FROM_HERE,
815 base::Bind(&WallpaperPrivateGetOfflineWallpaperListFunction::GetList,
816 this));
817 return true;
820 void WallpaperPrivateGetOfflineWallpaperListFunction::GetList() {
821 DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
822 sequence_token_));
823 std::vector<std::string> file_list;
824 base::FilePath wallpaper_dir;
825 CHECK(PathService::Get(chrome::DIR_CHROMEOS_WALLPAPERS, &wallpaper_dir));
826 if (base::DirectoryExists(wallpaper_dir)) {
827 base::FileEnumerator files(wallpaper_dir, false,
828 base::FileEnumerator::FILES);
829 for (base::FilePath current = files.Next(); !current.empty();
830 current = files.Next()) {
831 std::string file_name = current.BaseName().RemoveExtension().value();
832 // Do not add file name of small resolution wallpaper to the list.
833 if (!EndsWith(file_name, chromeos::kSmallWallpaperSuffix, true))
834 file_list.push_back(current.BaseName().value());
837 BrowserThread::PostTask(
838 BrowserThread::UI, FROM_HERE,
839 base::Bind(&WallpaperPrivateGetOfflineWallpaperListFunction::OnComplete,
840 this, file_list));
843 void WallpaperPrivateGetOfflineWallpaperListFunction::OnComplete(
844 const std::vector<std::string>& file_list) {
845 base::ListValue* results = new base::ListValue();
846 results->AppendStrings(file_list);
847 SetResult(results);
848 SendResponse(true);