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"
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/files/file_enumerator.h"
17 #include "base/files/file_util.h"
18 #include "base/memory/scoped_ptr.h"
19 #include "base/path_service.h"
20 #include "base/prefs/pref_service.h"
21 #include "base/strings/string_number_conversions.h"
22 #include "base/strings/stringprintf.h"
23 #include "base/threading/worker_pool.h"
24 #include "chrome/browser/browser_process.h"
25 #include "chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.h"
26 #include "chrome/browser/profiles/profile.h"
27 #include "chrome/common/chrome_paths.h"
28 #include "chrome/common/pref_names.h"
29 #include "chrome/grit/generated_resources.h"
30 #include "components/user_manager/user.h"
31 #include "components/user_manager/user_manager.h"
32 #include "content/public/browser/browser_thread.h"
33 #include "extensions/browser/event_router.h"
34 #include "grit/components_strings.h"
35 #include "ui/base/l10n/l10n_util.h"
36 #include "ui/base/webui/web_ui_util.h"
37 #include "ui/strings/grit/app_locale_settings.h"
40 using base::BinaryValue;
41 using content::BrowserThread;
42 namespace wallpaper_private = extensions::api::wallpaper_private;
43 namespace set_wallpaper_if_exists = wallpaper_private::SetWallpaperIfExists;
44 namespace set_wallpaper = wallpaper_private::SetWallpaper;
45 namespace set_custom_wallpaper = wallpaper_private::SetCustomWallpaper;
46 namespace set_custom_wallpaper_layout =
47 wallpaper_private::SetCustomWallpaperLayout;
48 namespace get_thumbnail = wallpaper_private::GetThumbnail;
49 namespace save_thumbnail = wallpaper_private::SaveThumbnail;
50 namespace get_offline_wallpaper_list =
51 wallpaper_private::GetOfflineWallpaperList;
55 #if defined(GOOGLE_CHROME_BUILD)
56 const char kWallpaperManifestBaseURL[] =
57 "https://storage.googleapis.com/chromeos-wallpaper-public/manifest_";
60 bool IsOEMDefaultWallpaper() {
61 return CommandLine::ForCurrentProcess()->HasSwitch(
62 ash::switches::kAshDefaultWallpaperIsOem);
65 // Saves |data| as |file_name| to directory with |key|. Return false if the
66 // directory can not be found/created or failed to write file.
67 bool SaveData(int key, const std::string& file_name, const std::string& data) {
68 base::FilePath data_dir;
69 CHECK(PathService::Get(key, &data_dir));
70 if (!base::DirectoryExists(data_dir) &&
71 !base::CreateDirectory(data_dir)) {
74 base::FilePath file_path = data_dir.Append(file_name);
76 return base::PathExists(file_path) ||
77 (base::WriteFile(file_path, data.c_str(), data.size()) != -1);
80 // Gets |file_name| from directory with |key|. Return false if the directory can
81 // not be found or failed to read file to string |data|. Note if the |file_name|
82 // can not be found in the directory, return true with empty |data|. It is
83 // expected that we may try to access file which did not saved yet.
84 bool GetData(const base::FilePath& path, std::string* data) {
85 base::FilePath data_dir = path.DirName();
86 if (!base::DirectoryExists(data_dir) &&
87 !base::CreateDirectory(data_dir))
90 return !base::PathExists(path) ||
91 base::ReadFileToString(path, data);
94 // WindowStateManager remembers which windows have been minimized in order to
95 // restore them when the wallpaper viewer is hidden.
96 class WindowStateManager : public aura::WindowObserver {
98 typedef std::map<std::string, std::set<aura::Window*> >
99 UserIDHashWindowListMap;
101 // Minimizes all windows except the active window.
102 static void MinimizeInactiveWindows(const std::string& user_id_hash);
104 // Unminimizes all minimized windows restoring them to their previous state.
105 // This should only be called after calling MinimizeInactiveWindows.
106 static void RestoreWindows(const std::string& user_id_hash);
109 WindowStateManager();
111 virtual ~WindowStateManager();
113 // Store all unminimized windows except |active_window| and minimize them.
114 // All the windows are saved in a map and the key value is |user_id_hash|.
115 void BuildWindowListAndMinimizeInactiveForUser(
116 const std::string& user_id_hash, aura::Window* active_window);
118 // Unminimize all the stored windows for |user_id_hash|.
119 void RestoreMinimizedWindows(const std::string& user_id_hash);
121 // Remove the observer from |window| if |window| is no longer referenced in
122 // user_id_hash_window_list_map_.
123 void RemoveObserverIfUnreferenced(aura::Window* window);
125 // aura::WindowObserver overrides.
126 virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE;
128 // Map of user id hash and associated list of minimized windows.
129 UserIDHashWindowListMap user_id_hash_window_list_map_;
131 DISALLOW_COPY_AND_ASSIGN(WindowStateManager);
135 WindowStateManager* g_window_state_manager = NULL;
138 void WindowStateManager::MinimizeInactiveWindows(
139 const std::string& user_id_hash) {
140 if (!g_window_state_manager)
141 g_window_state_manager = new WindowStateManager();
142 g_window_state_manager->BuildWindowListAndMinimizeInactiveForUser(
143 user_id_hash, ash::wm::GetActiveWindow());
147 void WindowStateManager::RestoreWindows(const std::string& user_id_hash) {
148 if (!g_window_state_manager) {
149 DCHECK(false) << "This should only be called after calling "
150 << "MinimizeInactiveWindows.";
154 g_window_state_manager->RestoreMinimizedWindows(user_id_hash);
155 if (g_window_state_manager->user_id_hash_window_list_map_.empty()) {
156 delete g_window_state_manager;
157 g_window_state_manager = NULL;
161 WindowStateManager::WindowStateManager() {}
163 WindowStateManager::~WindowStateManager() {}
165 void WindowStateManager::BuildWindowListAndMinimizeInactiveForUser(
166 const std::string& user_id_hash, aura::Window* active_window) {
167 if (user_id_hash_window_list_map_.find(user_id_hash) ==
168 user_id_hash_window_list_map_.end()) {
169 user_id_hash_window_list_map_[user_id_hash] = std::set<aura::Window*>();
171 std::set<aura::Window*>* results =
172 &user_id_hash_window_list_map_[user_id_hash];
174 std::vector<aura::Window*> windows =
175 ash::MruWindowTracker::BuildWindowList(false);
177 for (std::vector<aura::Window*>::iterator iter = windows.begin();
178 iter != windows.end(); ++iter) {
179 // Ignore active window and minimized windows.
180 if (*iter == active_window || ash::wm::GetWindowState(*iter)->IsMinimized())
183 // TODO(bshe): Add WindowStateObserver too. http://crbug.com/323252
184 if (!(*iter)->HasObserver(this))
185 (*iter)->AddObserver(this);
187 results->insert(*iter);
188 ash::wm::GetWindowState(*iter)->Minimize();
192 void WindowStateManager::RestoreMinimizedWindows(
193 const std::string& user_id_hash) {
194 UserIDHashWindowListMap::iterator it =
195 user_id_hash_window_list_map_.find(user_id_hash);
196 if (it == user_id_hash_window_list_map_.end()) {
197 DCHECK(false) << "This should only be called after calling "
198 << "MinimizeInactiveWindows.";
202 std::set<aura::Window*> removed_windows;
203 removed_windows.swap(it->second);
204 user_id_hash_window_list_map_.erase(it);
206 for (std::set<aura::Window*>::iterator iter = removed_windows.begin();
207 iter != removed_windows.end(); ++iter) {
208 ash::wm::GetWindowState(*iter)->Unminimize();
209 RemoveObserverIfUnreferenced(*iter);
213 void WindowStateManager::RemoveObserverIfUnreferenced(aura::Window* window) {
214 for (UserIDHashWindowListMap::iterator iter =
215 user_id_hash_window_list_map_.begin();
216 iter != user_id_hash_window_list_map_.end();
218 if (iter->second.find(window) != iter->second.end())
221 // Remove observer if |window| is not observed by any users.
222 window->RemoveObserver(this);
225 void WindowStateManager::OnWindowDestroyed(aura::Window* window) {
226 for (UserIDHashWindowListMap::iterator iter =
227 user_id_hash_window_list_map_.begin();
228 iter != user_id_hash_window_list_map_.end();
230 iter->second.erase(window);
236 bool WallpaperPrivateGetStringsFunction::RunSync() {
237 base::DictionaryValue* dict = new base::DictionaryValue();
240 #define SET_STRING(id, idr) \
241 dict->SetString(id, l10n_util::GetStringUTF16(idr))
242 SET_STRING("webFontFamily", IDS_WEB_FONT_FAMILY);
243 SET_STRING("webFontSize", IDS_WEB_FONT_SIZE);
244 SET_STRING("allCategoryLabel", IDS_WALLPAPER_MANAGER_ALL_CATEGORY_LABEL);
245 SET_STRING("deleteCommandLabel", IDS_WALLPAPER_MANAGER_DELETE_COMMAND_LABEL);
246 SET_STRING("customCategoryLabel",
247 IDS_WALLPAPER_MANAGER_CUSTOM_CATEGORY_LABEL);
248 SET_STRING("selectCustomLabel",
249 IDS_WALLPAPER_MANAGER_SELECT_CUSTOM_LABEL);
250 SET_STRING("positionLabel", IDS_WALLPAPER_MANAGER_POSITION_LABEL);
251 SET_STRING("colorLabel", IDS_WALLPAPER_MANAGER_COLOR_LABEL);
252 SET_STRING("centerCroppedLayout",
253 IDS_OPTIONS_WALLPAPER_CENTER_CROPPED_LAYOUT);
254 SET_STRING("centerLayout", IDS_OPTIONS_WALLPAPER_CENTER_LAYOUT);
255 SET_STRING("stretchLayout", IDS_OPTIONS_WALLPAPER_STRETCH_LAYOUT);
256 SET_STRING("connectionFailed", IDS_WALLPAPER_MANAGER_ACCESS_FAIL);
257 SET_STRING("downloadFailed", IDS_WALLPAPER_MANAGER_DOWNLOAD_FAIL);
258 SET_STRING("downloadCanceled", IDS_WALLPAPER_MANAGER_DOWNLOAD_CANCEL);
259 SET_STRING("customWallpaperWarning",
260 IDS_WALLPAPER_MANAGER_SHOW_CUSTOM_WALLPAPER_ON_START_WARNING);
261 SET_STRING("accessFileFailure", IDS_WALLPAPER_MANAGER_ACCESS_FILE_FAILURE);
262 SET_STRING("invalidWallpaper", IDS_WALLPAPER_MANAGER_INVALID_WALLPAPER);
263 SET_STRING("surpriseMeLabel", IDS_WALLPAPER_MANAGER_SURPRISE_ME_LABEL);
264 SET_STRING("learnMore", IDS_LEARN_MORE);
265 SET_STRING("currentWallpaperSetByMessage",
266 IDS_CURRENT_WALLPAPER_SET_BY_MESSAGE);
269 webui::SetFontAndTextDirection(dict);
271 chromeos::WallpaperManager* wallpaper_manager =
272 chromeos::WallpaperManager::Get();
273 chromeos::WallpaperInfo info;
275 if (wallpaper_manager->GetLoggedInUserWallpaperInfo(&info))
276 dict->SetString("currentWallpaper", info.location);
278 #if defined(GOOGLE_CHROME_BUILD)
279 dict->SetString("manifestBaseURL", kWallpaperManifestBaseURL);
282 Profile* profile = Profile::FromBrowserContext(browser_context());
283 std::string app_name(
284 profile->GetPrefs()->GetString(prefs::kCurrentWallpaperAppName));
285 if (!app_name.empty())
286 dict->SetString("wallpaperAppName", app_name);
288 dict->SetBoolean("isOEMDefaultWallpaper", IsOEMDefaultWallpaper());
289 dict->SetString("canceledWallpaper",
290 wallpaper_api_util::kCancelWallpaperMessage);
294 WallpaperPrivateSetWallpaperIfExistsFunction::
295 WallpaperPrivateSetWallpaperIfExistsFunction() {}
297 WallpaperPrivateSetWallpaperIfExistsFunction::
298 ~WallpaperPrivateSetWallpaperIfExistsFunction() {}
300 bool WallpaperPrivateSetWallpaperIfExistsFunction::RunAsync() {
301 #if !defined(USE_ATHENA)
302 // TODO(bshe): Support wallpaper manager in Athena, crbug.com/408734.
303 params = set_wallpaper_if_exists::Params::Create(*args_);
304 EXTENSION_FUNCTION_VALIDATE(params);
306 user_id_ = user_manager::UserManager::Get()->GetActiveUser()->email();
308 base::FilePath wallpaper_path;
309 base::FilePath fallback_path;
310 chromeos::WallpaperManager::WallpaperResolution resolution =
311 chromeos::WallpaperManager::GetAppropriateResolution();
313 std::string file_name = GURL(params->url).ExtractFileName();
314 CHECK(PathService::Get(chrome::DIR_CHROMEOS_WALLPAPERS,
316 fallback_path = wallpaper_path.Append(file_name);
317 if (params->layout != wallpaper_private::WALLPAPER_LAYOUT_STRETCH &&
318 resolution == chromeos::WallpaperManager::WALLPAPER_RESOLUTION_SMALL) {
319 file_name = base::FilePath(file_name).InsertBeforeExtension(
320 chromeos::kSmallWallpaperSuffix).value();
322 wallpaper_path = wallpaper_path.Append(file_name);
324 sequence_token_ = BrowserThread::GetBlockingPool()->
325 GetNamedSequenceToken(chromeos::kWallpaperSequenceTokenName);
326 scoped_refptr<base::SequencedTaskRunner> task_runner =
327 BrowserThread::GetBlockingPool()->
328 GetSequencedTaskRunnerWithShutdownBehavior(sequence_token_,
329 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN);
331 task_runner->PostTask(FROM_HERE,
333 &WallpaperPrivateSetWallpaperIfExistsFunction::
334 ReadFileAndInitiateStartDecode,
335 this, wallpaper_path, fallback_path));
340 void WallpaperPrivateSetWallpaperIfExistsFunction::
341 ReadFileAndInitiateStartDecode(const base::FilePath& file_path,
342 const base::FilePath& fallback_path) {
343 DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
346 base::FilePath path = file_path;
348 if (!base::PathExists(file_path))
349 path = fallback_path;
351 if (base::PathExists(path) &&
352 base::ReadFileToString(path, &data)) {
353 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
354 base::Bind(&WallpaperPrivateSetWallpaperIfExistsFunction::StartDecode,
358 std::string error = base::StringPrintf(
359 "Failed to set wallpaper %s from file system.",
360 path.BaseName().value().c_str());
361 BrowserThread::PostTask(
362 BrowserThread::UI, FROM_HERE,
363 base::Bind(&WallpaperPrivateSetWallpaperIfExistsFunction::OnFileNotExists,
367 void WallpaperPrivateSetWallpaperIfExistsFunction::OnWallpaperDecoded(
368 const gfx::ImageSkia& image) {
369 // Set unsafe_wallpaper_decoder_ to null since the decoding already finished.
370 unsafe_wallpaper_decoder_ = NULL;
372 chromeos::WallpaperManager* wallpaper_manager =
373 chromeos::WallpaperManager::Get();
374 ash::WallpaperLayout layout = wallpaper_api_util::GetLayoutEnum(
375 wallpaper_private::ToString(params->layout));
377 bool update_wallpaper =
378 user_id_ == user_manager::UserManager::Get()->GetActiveUser()->email();
379 wallpaper_manager->SetWallpaperFromImageSkia(
380 user_id_, image, layout, update_wallpaper);
381 bool is_persistent = !user_manager::UserManager::Get()
382 ->IsCurrentUserNonCryptohomeDataEphemeral();
383 chromeos::WallpaperInfo info = {params->url, layout,
384 user_manager::User::ONLINE,
385 base::Time::Now().LocalMidnight()};
386 wallpaper_manager->SetUserWallpaperInfo(user_id_, info, is_persistent);
387 SetResult(new base::FundamentalValue(true));
388 Profile* profile = Profile::FromBrowserContext(browser_context());
389 // This API is only available to the component wallpaper picker. We do not
390 // need to show the app's name if it is the component wallpaper picker. So set
391 // the pref to empty string.
392 profile->GetPrefs()->SetString(prefs::kCurrentWallpaperAppName,
397 void WallpaperPrivateSetWallpaperIfExistsFunction::OnFileNotExists(
398 const std::string& error) {
399 SetResult(new base::FundamentalValue(false));
403 WallpaperPrivateSetWallpaperFunction::WallpaperPrivateSetWallpaperFunction() {
406 WallpaperPrivateSetWallpaperFunction::~WallpaperPrivateSetWallpaperFunction() {
409 bool WallpaperPrivateSetWallpaperFunction::RunAsync() {
410 params = set_wallpaper::Params::Create(*args_);
411 EXTENSION_FUNCTION_VALIDATE(params);
413 // Gets email address while at UI thread.
414 user_id_ = user_manager::UserManager::Get()->GetActiveUser()->email();
416 StartDecode(params->wallpaper);
421 void WallpaperPrivateSetWallpaperFunction::OnWallpaperDecoded(
422 const gfx::ImageSkia& image) {
424 // Set unsafe_wallpaper_decoder_ to null since the decoding already finished.
425 unsafe_wallpaper_decoder_ = NULL;
427 sequence_token_ = BrowserThread::GetBlockingPool()->
428 GetNamedSequenceToken(chromeos::kWallpaperSequenceTokenName);
429 scoped_refptr<base::SequencedTaskRunner> task_runner =
430 BrowserThread::GetBlockingPool()->
431 GetSequencedTaskRunnerWithShutdownBehavior(sequence_token_,
432 base::SequencedWorkerPool::BLOCK_SHUTDOWN);
434 task_runner->PostTask(FROM_HERE,
435 base::Bind(&WallpaperPrivateSetWallpaperFunction::SaveToFile, this));
438 void WallpaperPrivateSetWallpaperFunction::SaveToFile() {
439 DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
441 std::string file_name = GURL(params->url).ExtractFileName();
442 if (SaveData(chrome::DIR_CHROMEOS_WALLPAPERS, file_name, params->wallpaper)) {
443 wallpaper_.EnsureRepsForSupportedScales();
444 scoped_ptr<gfx::ImageSkia> deep_copy(wallpaper_.DeepCopy());
445 // ImageSkia is not RefCountedThreadSafe. Use a deep copied ImageSkia if
446 // post to another thread.
447 BrowserThread::PostTask(
450 base::Bind(&WallpaperPrivateSetWallpaperFunction::SetDecodedWallpaper,
452 base::Passed(deep_copy.Pass())));
454 base::FilePath wallpaper_dir;
455 CHECK(PathService::Get(chrome::DIR_CHROMEOS_WALLPAPERS, &wallpaper_dir));
456 base::FilePath file_path = wallpaper_dir.Append(
457 file_name).InsertBeforeExtension(chromeos::kSmallWallpaperSuffix);
458 if (base::PathExists(file_path))
460 // Generates and saves small resolution wallpaper. Uses CENTER_CROPPED to
461 // maintain the aspect ratio after resize.
462 chromeos::WallpaperManager::Get()->ResizeAndSaveWallpaper(
465 ash::WALLPAPER_LAYOUT_CENTER_CROPPED,
466 chromeos::kSmallWallpaperMaxWidth,
467 chromeos::kSmallWallpaperMaxHeight,
470 std::string error = base::StringPrintf(
471 "Failed to create/write wallpaper to %s.", file_name.c_str());
472 BrowserThread::PostTask(
473 BrowserThread::UI, FROM_HERE,
474 base::Bind(&WallpaperPrivateSetWallpaperFunction::OnFailure,
479 void WallpaperPrivateSetWallpaperFunction::SetDecodedWallpaper(
480 scoped_ptr<gfx::ImageSkia> image) {
481 chromeos::WallpaperManager* wallpaper_manager =
482 chromeos::WallpaperManager::Get();
484 ash::WallpaperLayout layout = wallpaper_api_util::GetLayoutEnum(
485 wallpaper_private::ToString(params->layout));
487 bool update_wallpaper =
488 user_id_ == user_manager::UserManager::Get()->GetActiveUser()->email();
489 wallpaper_manager->SetWallpaperFromImageSkia(
490 user_id_, *image.get(), layout, update_wallpaper);
492 bool is_persistent = !user_manager::UserManager::Get()
493 ->IsCurrentUserNonCryptohomeDataEphemeral();
494 chromeos::WallpaperInfo info = {params->url, layout,
495 user_manager::User::ONLINE,
496 base::Time::Now().LocalMidnight()};
497 Profile* profile = Profile::FromBrowserContext(browser_context());
498 // This API is only available to the component wallpaper picker. We do not
499 // need to show the app's name if it is the component wallpaper picker. So set
500 // the pref to empty string.
501 profile->GetPrefs()->SetString(prefs::kCurrentWallpaperAppName,
503 wallpaper_manager->SetUserWallpaperInfo(user_id_, info, is_persistent);
507 WallpaperPrivateResetWallpaperFunction::
508 WallpaperPrivateResetWallpaperFunction() {}
510 WallpaperPrivateResetWallpaperFunction::
511 ~WallpaperPrivateResetWallpaperFunction() {}
513 bool WallpaperPrivateResetWallpaperFunction::RunAsync() {
514 chromeos::WallpaperManager* wallpaper_manager =
515 chromeos::WallpaperManager::Get();
516 user_manager::UserManager* user_manager = user_manager::UserManager::Get();
518 std::string user_id = user_manager->GetActiveUser()->email();
519 wallpaper_manager->RemoveUserWallpaperInfo(user_id);
521 chromeos::WallpaperInfo info = {std::string(),
522 ash::WALLPAPER_LAYOUT_CENTER,
523 user_manager::User::DEFAULT,
524 base::Time::Now().LocalMidnight()};
526 !user_manager->IsCurrentUserNonCryptohomeDataEphemeral();
527 wallpaper_manager->SetUserWallpaperInfo(user_id, info, is_persistent);
529 wallpaper_manager->SetDefaultWallpaperNow(user_id);
530 Profile* profile = Profile::FromBrowserContext(browser_context());
531 // This API is only available to the component wallpaper picker. We do not
532 // need to show the app's name if it is the component wallpaper picker. So set
533 // the pref to empty string.
534 profile->GetPrefs()->SetString(prefs::kCurrentWallpaperAppName,
539 WallpaperPrivateSetCustomWallpaperFunction::
540 WallpaperPrivateSetCustomWallpaperFunction() {}
542 WallpaperPrivateSetCustomWallpaperFunction::
543 ~WallpaperPrivateSetCustomWallpaperFunction() {}
545 bool WallpaperPrivateSetCustomWallpaperFunction::RunAsync() {
546 params = set_custom_wallpaper::Params::Create(*args_);
547 EXTENSION_FUNCTION_VALIDATE(params);
549 // Gets email address and username hash while at UI thread.
550 user_id_ = user_manager::UserManager::Get()->GetActiveUser()->email();
552 user_manager::UserManager::Get()->GetActiveUser()->username_hash();
554 StartDecode(params->wallpaper);
559 void WallpaperPrivateSetCustomWallpaperFunction::OnWallpaperDecoded(
560 const gfx::ImageSkia& image) {
561 chromeos::WallpaperManager* wallpaper_manager =
562 chromeos::WallpaperManager::Get();
563 base::FilePath thumbnail_path = wallpaper_manager->GetCustomWallpaperPath(
564 chromeos::kThumbnailWallpaperSubDir, user_id_hash_, params->file_name);
566 sequence_token_ = BrowserThread::GetBlockingPool()->
567 GetNamedSequenceToken(chromeos::kWallpaperSequenceTokenName);
568 scoped_refptr<base::SequencedTaskRunner> task_runner =
569 BrowserThread::GetBlockingPool()->
570 GetSequencedTaskRunnerWithShutdownBehavior(sequence_token_,
571 base::SequencedWorkerPool::BLOCK_SHUTDOWN);
573 ash::WallpaperLayout layout = wallpaper_api_util::GetLayoutEnum(
574 wallpaper_private::ToString(params->layout));
576 bool update_wallpaper =
577 user_id_ == user_manager::UserManager::Get()->GetActiveUser()->email();
578 wallpaper_manager->SetCustomWallpaper(user_id_,
582 user_manager::User::CUSTOMIZED,
585 unsafe_wallpaper_decoder_ = NULL;
587 Profile* profile = Profile::FromBrowserContext(browser_context());
588 // This API is only available to the component wallpaper picker. We do not
589 // need to show the app's name if it is the component wallpaper picker. So set
590 // the pref to empty string.
591 profile->GetPrefs()->SetString(prefs::kCurrentWallpaperAppName,
594 if (params->generate_thumbnail) {
595 image.EnsureRepsForSupportedScales();
596 scoped_ptr<gfx::ImageSkia> deep_copy(image.DeepCopy());
597 // Generates thumbnail before call api function callback. We can then
598 // request thumbnail in the javascript callback.
599 task_runner->PostTask(FROM_HERE,
601 &WallpaperPrivateSetCustomWallpaperFunction::GenerateThumbnail,
602 this, thumbnail_path, base::Passed(&deep_copy)));
608 void WallpaperPrivateSetCustomWallpaperFunction::GenerateThumbnail(
609 const base::FilePath& thumbnail_path, scoped_ptr<gfx::ImageSkia> image) {
610 DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
612 if (!base::PathExists(thumbnail_path.DirName()))
613 base::CreateDirectory(thumbnail_path.DirName());
615 scoped_refptr<base::RefCountedBytes> data;
616 chromeos::WallpaperManager::Get()->ResizeImage(
618 ash::WALLPAPER_LAYOUT_STRETCH,
619 chromeos::kWallpaperThumbnailWidth,
620 chromeos::kWallpaperThumbnailHeight,
623 BrowserThread::PostTask(
624 BrowserThread::UI, FROM_HERE,
626 &WallpaperPrivateSetCustomWallpaperFunction::ThumbnailGenerated,
630 void WallpaperPrivateSetCustomWallpaperFunction::ThumbnailGenerated(
631 base::RefCountedBytes* data) {
632 BinaryValue* result = BinaryValue::CreateWithCopiedBuffer(
633 reinterpret_cast<const char*>(data->front()), data->size());
638 WallpaperPrivateSetCustomWallpaperLayoutFunction::
639 WallpaperPrivateSetCustomWallpaperLayoutFunction() {}
641 WallpaperPrivateSetCustomWallpaperLayoutFunction::
642 ~WallpaperPrivateSetCustomWallpaperLayoutFunction() {}
644 bool WallpaperPrivateSetCustomWallpaperLayoutFunction::RunAsync() {
645 scoped_ptr<set_custom_wallpaper_layout::Params> params(
646 set_custom_wallpaper_layout::Params::Create(*args_));
647 EXTENSION_FUNCTION_VALIDATE(params);
649 chromeos::WallpaperManager* wallpaper_manager =
650 chromeos::WallpaperManager::Get();
651 chromeos::WallpaperInfo info;
652 wallpaper_manager->GetLoggedInUserWallpaperInfo(&info);
653 if (info.type != user_manager::User::CUSTOMIZED) {
654 SetError("Only custom wallpaper can change layout.");
658 info.layout = wallpaper_api_util::GetLayoutEnum(
659 wallpaper_private::ToString(params->layout));
662 user_manager::UserManager::Get()->GetActiveUser()->email();
663 bool is_persistent = !user_manager::UserManager::Get()
664 ->IsCurrentUserNonCryptohomeDataEphemeral();
665 wallpaper_manager->SetUserWallpaperInfo(email, info, is_persistent);
666 wallpaper_manager->UpdateWallpaper(false /* clear_cache */);
669 // Gets email address while at UI thread.
673 WallpaperPrivateMinimizeInactiveWindowsFunction::
674 WallpaperPrivateMinimizeInactiveWindowsFunction() {
677 WallpaperPrivateMinimizeInactiveWindowsFunction::
678 ~WallpaperPrivateMinimizeInactiveWindowsFunction() {
681 bool WallpaperPrivateMinimizeInactiveWindowsFunction::RunAsync() {
682 WindowStateManager::MinimizeInactiveWindows(
683 user_manager::UserManager::Get()->GetActiveUser()->username_hash());
687 WallpaperPrivateRestoreMinimizedWindowsFunction::
688 WallpaperPrivateRestoreMinimizedWindowsFunction() {
691 WallpaperPrivateRestoreMinimizedWindowsFunction::
692 ~WallpaperPrivateRestoreMinimizedWindowsFunction() {
695 bool WallpaperPrivateRestoreMinimizedWindowsFunction::RunAsync() {
696 WindowStateManager::RestoreWindows(
697 user_manager::UserManager::Get()->GetActiveUser()->username_hash());
701 WallpaperPrivateGetThumbnailFunction::WallpaperPrivateGetThumbnailFunction() {
704 WallpaperPrivateGetThumbnailFunction::~WallpaperPrivateGetThumbnailFunction() {
707 bool WallpaperPrivateGetThumbnailFunction::RunAsync() {
708 scoped_ptr<get_thumbnail::Params> params(
709 get_thumbnail::Params::Create(*args_));
710 EXTENSION_FUNCTION_VALIDATE(params);
712 base::FilePath thumbnail_path;
714 user_manager::UserManager::Get()->GetActiveUser()->email();
715 if (params->source == get_thumbnail::Params::SOURCE_ONLINE) {
716 std::string file_name = GURL(params->url_or_file).ExtractFileName();
717 CHECK(PathService::Get(chrome::DIR_CHROMEOS_WALLPAPER_THUMBNAILS,
719 thumbnail_path = thumbnail_path.Append(file_name);
721 if (!IsOEMDefaultWallpaper()) {
722 SetError("No OEM wallpaper.");
727 // TODO(bshe): Small resolution wallpaper is used here as wallpaper
728 // thumbnail. We should either resize it or include a wallpaper thumbnail in
729 // addition to large and small wallpaper resolutions.
730 thumbnail_path = CommandLine::ForCurrentProcess()->GetSwitchValuePath(
731 ash::switches::kAshDefaultWallpaperSmall);
734 sequence_token_ = BrowserThread::GetBlockingPool()->
735 GetNamedSequenceToken(chromeos::kWallpaperSequenceTokenName);
736 scoped_refptr<base::SequencedTaskRunner> task_runner =
737 BrowserThread::GetBlockingPool()->
738 GetSequencedTaskRunnerWithShutdownBehavior(sequence_token_,
739 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN);
741 task_runner->PostTask(FROM_HERE,
742 base::Bind(&WallpaperPrivateGetThumbnailFunction::Get, this,
747 void WallpaperPrivateGetThumbnailFunction::Failure(
748 const std::string& file_name) {
749 SetError(base::StringPrintf("Failed to access wallpaper thumbnails for %s.",
754 void WallpaperPrivateGetThumbnailFunction::FileNotLoaded() {
758 void WallpaperPrivateGetThumbnailFunction::FileLoaded(
759 const std::string& data) {
760 BinaryValue* thumbnail = BinaryValue::CreateWithCopiedBuffer(data.c_str(),
762 SetResult(thumbnail);
766 void WallpaperPrivateGetThumbnailFunction::Get(const base::FilePath& path) {
767 DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
770 if (GetData(path, &data)) {
772 BrowserThread::PostTask(
773 BrowserThread::UI, FROM_HERE,
774 base::Bind(&WallpaperPrivateGetThumbnailFunction::FileNotLoaded, this));
776 BrowserThread::PostTask(
777 BrowserThread::UI, FROM_HERE,
778 base::Bind(&WallpaperPrivateGetThumbnailFunction::FileLoaded, this,
782 BrowserThread::PostTask(
783 BrowserThread::UI, FROM_HERE,
784 base::Bind(&WallpaperPrivateGetThumbnailFunction::Failure, this,
785 path.BaseName().value()));
789 WallpaperPrivateSaveThumbnailFunction::WallpaperPrivateSaveThumbnailFunction() {
792 WallpaperPrivateSaveThumbnailFunction::
793 ~WallpaperPrivateSaveThumbnailFunction() {}
795 bool WallpaperPrivateSaveThumbnailFunction::RunAsync() {
796 scoped_ptr<save_thumbnail::Params> params(
797 save_thumbnail::Params::Create(*args_));
798 EXTENSION_FUNCTION_VALIDATE(params);
800 sequence_token_ = BrowserThread::GetBlockingPool()->
801 GetNamedSequenceToken(chromeos::kWallpaperSequenceTokenName);
802 scoped_refptr<base::SequencedTaskRunner> task_runner =
803 BrowserThread::GetBlockingPool()->
804 GetSequencedTaskRunnerWithShutdownBehavior(sequence_token_,
805 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN);
807 task_runner->PostTask(FROM_HERE,
808 base::Bind(&WallpaperPrivateSaveThumbnailFunction::Save,
809 this, params->data, GURL(params->url).ExtractFileName()));
813 void WallpaperPrivateSaveThumbnailFunction::Failure(
814 const std::string& file_name) {
815 SetError(base::StringPrintf("Failed to create/write thumbnail of %s.",
820 void WallpaperPrivateSaveThumbnailFunction::Success() {
824 void WallpaperPrivateSaveThumbnailFunction::Save(const std::string& data,
825 const std::string& file_name) {
826 DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
828 if (SaveData(chrome::DIR_CHROMEOS_WALLPAPER_THUMBNAILS, file_name, data)) {
829 BrowserThread::PostTask(
830 BrowserThread::UI, FROM_HERE,
831 base::Bind(&WallpaperPrivateSaveThumbnailFunction::Success, this));
833 BrowserThread::PostTask(
834 BrowserThread::UI, FROM_HERE,
835 base::Bind(&WallpaperPrivateSaveThumbnailFunction::Failure,
840 WallpaperPrivateGetOfflineWallpaperListFunction::
841 WallpaperPrivateGetOfflineWallpaperListFunction() {
844 WallpaperPrivateGetOfflineWallpaperListFunction::
845 ~WallpaperPrivateGetOfflineWallpaperListFunction() {
848 bool WallpaperPrivateGetOfflineWallpaperListFunction::RunAsync() {
849 sequence_token_ = BrowserThread::GetBlockingPool()->
850 GetNamedSequenceToken(chromeos::kWallpaperSequenceTokenName);
851 scoped_refptr<base::SequencedTaskRunner> task_runner =
852 BrowserThread::GetBlockingPool()->
853 GetSequencedTaskRunnerWithShutdownBehavior(sequence_token_,
854 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN);
856 task_runner->PostTask(FROM_HERE,
857 base::Bind(&WallpaperPrivateGetOfflineWallpaperListFunction::GetList,
862 void WallpaperPrivateGetOfflineWallpaperListFunction::GetList() {
863 DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
865 std::vector<std::string> file_list;
866 base::FilePath wallpaper_dir;
867 CHECK(PathService::Get(chrome::DIR_CHROMEOS_WALLPAPERS, &wallpaper_dir));
868 if (base::DirectoryExists(wallpaper_dir)) {
869 base::FileEnumerator files(wallpaper_dir, false,
870 base::FileEnumerator::FILES);
871 for (base::FilePath current = files.Next(); !current.empty();
872 current = files.Next()) {
873 std::string file_name = current.BaseName().RemoveExtension().value();
874 // Do not add file name of small resolution wallpaper to the list.
875 if (!EndsWith(file_name, chromeos::kSmallWallpaperSuffix, true))
876 file_list.push_back(current.BaseName().value());
879 BrowserThread::PostTask(
880 BrowserThread::UI, FROM_HERE,
881 base::Bind(&WallpaperPrivateGetOfflineWallpaperListFunction::OnComplete,
885 void WallpaperPrivateGetOfflineWallpaperListFunction::OnComplete(
886 const std::vector<std::string>& file_list) {
887 base::ListValue* results = new base::ListValue();
888 results->AppendStrings(file_list);