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/browser/sync/profile_sync_service.h"
28 #include "chrome/browser/sync/profile_sync_service_factory.h"
29 #include "chrome/common/chrome_paths.h"
30 #include "chrome/common/pref_names.h"
31 #include "chrome/grit/generated_resources.h"
32 #include "components/user_manager/user.h"
33 #include "components/user_manager/user_manager.h"
34 #include "content/public/browser/browser_thread.h"
35 #include "extensions/browser/event_router.h"
36 #include "grit/components_strings.h"
37 #include "ui/base/l10n/l10n_util.h"
38 #include "ui/base/webui/web_ui_util.h"
39 #include "ui/strings/grit/app_locale_settings.h"
42 using base::BinaryValue;
43 using content::BrowserThread;
44 namespace wallpaper_private = extensions::api::wallpaper_private;
45 namespace set_wallpaper_if_exists = wallpaper_private::SetWallpaperIfExists;
46 namespace set_wallpaper = wallpaper_private::SetWallpaper;
47 namespace set_custom_wallpaper = wallpaper_private::SetCustomWallpaper;
48 namespace set_custom_wallpaper_layout =
49 wallpaper_private::SetCustomWallpaperLayout;
50 namespace get_thumbnail = wallpaper_private::GetThumbnail;
51 namespace save_thumbnail = wallpaper_private::SaveThumbnail;
52 namespace get_offline_wallpaper_list =
53 wallpaper_private::GetOfflineWallpaperList;
57 #if defined(GOOGLE_CHROME_BUILD)
58 const char kWallpaperManifestBaseURL[] =
59 "https://storage.googleapis.com/chromeos-wallpaper-public/manifest_";
62 bool IsOEMDefaultWallpaper() {
63 return CommandLine::ForCurrentProcess()->HasSwitch(
64 ash::switches::kAshDefaultWallpaperIsOem);
67 // Saves |data| as |file_name| to directory with |key|. Return false if the
68 // directory can not be found/created or failed to write file.
69 bool SaveData(int key, const std::string& file_name, const std::string& data) {
70 base::FilePath data_dir;
71 CHECK(PathService::Get(key, &data_dir));
72 if (!base::DirectoryExists(data_dir) &&
73 !base::CreateDirectory(data_dir)) {
76 base::FilePath file_path = data_dir.Append(file_name);
78 return base::PathExists(file_path) ||
79 (base::WriteFile(file_path, data.c_str(), data.size()) != -1);
82 // Gets |file_name| from directory with |key|. Return false if the directory can
83 // not be found or failed to read file to string |data|. Note if the |file_name|
84 // can not be found in the directory, return true with empty |data|. It is
85 // expected that we may try to access file which did not saved yet.
86 bool GetData(const base::FilePath& path, std::string* data) {
87 base::FilePath data_dir = path.DirName();
88 if (!base::DirectoryExists(data_dir) &&
89 !base::CreateDirectory(data_dir))
92 return !base::PathExists(path) ||
93 base::ReadFileToString(path, data);
96 // WindowStateManager remembers which windows have been minimized in order to
97 // restore them when the wallpaper viewer is hidden.
98 class WindowStateManager : public aura::WindowObserver {
100 typedef std::map<std::string, std::set<aura::Window*> >
101 UserIDHashWindowListMap;
103 // Minimizes all windows except the active window.
104 static void MinimizeInactiveWindows(const std::string& user_id_hash);
106 // Unminimizes all minimized windows restoring them to their previous state.
107 // This should only be called after calling MinimizeInactiveWindows.
108 static void RestoreWindows(const std::string& user_id_hash);
111 WindowStateManager();
113 virtual ~WindowStateManager();
115 // Store all unminimized windows except |active_window| and minimize them.
116 // All the windows are saved in a map and the key value is |user_id_hash|.
117 void BuildWindowListAndMinimizeInactiveForUser(
118 const std::string& user_id_hash, aura::Window* active_window);
120 // Unminimize all the stored windows for |user_id_hash|.
121 void RestoreMinimizedWindows(const std::string& user_id_hash);
123 // Remove the observer from |window| if |window| is no longer referenced in
124 // user_id_hash_window_list_map_.
125 void RemoveObserverIfUnreferenced(aura::Window* window);
127 // aura::WindowObserver overrides.
128 virtual void OnWindowDestroyed(aura::Window* window) override;
130 // Map of user id hash and associated list of minimized windows.
131 UserIDHashWindowListMap user_id_hash_window_list_map_;
133 DISALLOW_COPY_AND_ASSIGN(WindowStateManager);
137 WindowStateManager* g_window_state_manager = NULL;
140 void WindowStateManager::MinimizeInactiveWindows(
141 const std::string& user_id_hash) {
142 if (!g_window_state_manager)
143 g_window_state_manager = new WindowStateManager();
144 g_window_state_manager->BuildWindowListAndMinimizeInactiveForUser(
145 user_id_hash, ash::wm::GetActiveWindow());
149 void WindowStateManager::RestoreWindows(const std::string& user_id_hash) {
150 if (!g_window_state_manager) {
151 DCHECK(false) << "This should only be called after calling "
152 << "MinimizeInactiveWindows.";
156 g_window_state_manager->RestoreMinimizedWindows(user_id_hash);
157 if (g_window_state_manager->user_id_hash_window_list_map_.empty()) {
158 delete g_window_state_manager;
159 g_window_state_manager = NULL;
163 WindowStateManager::WindowStateManager() {}
165 WindowStateManager::~WindowStateManager() {}
167 void WindowStateManager::BuildWindowListAndMinimizeInactiveForUser(
168 const std::string& user_id_hash, aura::Window* active_window) {
169 if (user_id_hash_window_list_map_.find(user_id_hash) ==
170 user_id_hash_window_list_map_.end()) {
171 user_id_hash_window_list_map_[user_id_hash] = std::set<aura::Window*>();
173 std::set<aura::Window*>* results =
174 &user_id_hash_window_list_map_[user_id_hash];
176 std::vector<aura::Window*> windows =
177 ash::MruWindowTracker::BuildWindowList(false);
179 for (std::vector<aura::Window*>::iterator iter = windows.begin();
180 iter != windows.end(); ++iter) {
181 // Ignore active window and minimized windows.
182 if (*iter == active_window || ash::wm::GetWindowState(*iter)->IsMinimized())
185 // TODO(bshe): Add WindowStateObserver too. http://crbug.com/323252
186 if (!(*iter)->HasObserver(this))
187 (*iter)->AddObserver(this);
189 results->insert(*iter);
190 ash::wm::GetWindowState(*iter)->Minimize();
194 void WindowStateManager::RestoreMinimizedWindows(
195 const std::string& user_id_hash) {
196 UserIDHashWindowListMap::iterator it =
197 user_id_hash_window_list_map_.find(user_id_hash);
198 if (it == user_id_hash_window_list_map_.end()) {
199 DCHECK(false) << "This should only be called after calling "
200 << "MinimizeInactiveWindows.";
204 std::set<aura::Window*> removed_windows;
205 removed_windows.swap(it->second);
206 user_id_hash_window_list_map_.erase(it);
208 for (std::set<aura::Window*>::iterator iter = removed_windows.begin();
209 iter != removed_windows.end(); ++iter) {
210 ash::wm::GetWindowState(*iter)->Unminimize();
211 RemoveObserverIfUnreferenced(*iter);
215 void WindowStateManager::RemoveObserverIfUnreferenced(aura::Window* window) {
216 for (UserIDHashWindowListMap::iterator iter =
217 user_id_hash_window_list_map_.begin();
218 iter != user_id_hash_window_list_map_.end();
220 if (iter->second.find(window) != iter->second.end())
223 // Remove observer if |window| is not observed by any users.
224 window->RemoveObserver(this);
227 void WindowStateManager::OnWindowDestroyed(aura::Window* window) {
228 for (UserIDHashWindowListMap::iterator iter =
229 user_id_hash_window_list_map_.begin();
230 iter != user_id_hash_window_list_map_.end();
232 iter->second.erase(window);
238 bool WallpaperPrivateGetStringsFunction::RunSync() {
239 base::DictionaryValue* dict = new base::DictionaryValue();
242 #define SET_STRING(id, idr) \
243 dict->SetString(id, l10n_util::GetStringUTF16(idr))
244 SET_STRING("webFontFamily", IDS_WEB_FONT_FAMILY);
245 SET_STRING("webFontSize", IDS_WEB_FONT_SIZE);
246 SET_STRING("allCategoryLabel", IDS_WALLPAPER_MANAGER_ALL_CATEGORY_LABEL);
247 SET_STRING("deleteCommandLabel", IDS_WALLPAPER_MANAGER_DELETE_COMMAND_LABEL);
248 SET_STRING("customCategoryLabel",
249 IDS_WALLPAPER_MANAGER_CUSTOM_CATEGORY_LABEL);
250 SET_STRING("selectCustomLabel",
251 IDS_WALLPAPER_MANAGER_SELECT_CUSTOM_LABEL);
252 SET_STRING("positionLabel", IDS_WALLPAPER_MANAGER_POSITION_LABEL);
253 SET_STRING("colorLabel", IDS_WALLPAPER_MANAGER_COLOR_LABEL);
254 SET_STRING("centerCroppedLayout",
255 IDS_OPTIONS_WALLPAPER_CENTER_CROPPED_LAYOUT);
256 SET_STRING("centerLayout", IDS_OPTIONS_WALLPAPER_CENTER_LAYOUT);
257 SET_STRING("stretchLayout", IDS_OPTIONS_WALLPAPER_STRETCH_LAYOUT);
258 SET_STRING("connectionFailed", IDS_WALLPAPER_MANAGER_ACCESS_FAIL);
259 SET_STRING("downloadFailed", IDS_WALLPAPER_MANAGER_DOWNLOAD_FAIL);
260 SET_STRING("downloadCanceled", IDS_WALLPAPER_MANAGER_DOWNLOAD_CANCEL);
261 SET_STRING("customWallpaperWarning",
262 IDS_WALLPAPER_MANAGER_SHOW_CUSTOM_WALLPAPER_ON_START_WARNING);
263 SET_STRING("accessFileFailure", IDS_WALLPAPER_MANAGER_ACCESS_FILE_FAILURE);
264 SET_STRING("invalidWallpaper", IDS_WALLPAPER_MANAGER_INVALID_WALLPAPER);
265 SET_STRING("surpriseMeLabel", IDS_WALLPAPER_MANAGER_SURPRISE_ME_LABEL);
266 SET_STRING("learnMore", IDS_LEARN_MORE);
267 SET_STRING("currentWallpaperSetByMessage",
268 IDS_CURRENT_WALLPAPER_SET_BY_MESSAGE);
271 webui::SetFontAndTextDirection(dict);
273 chromeos::WallpaperManager* wallpaper_manager =
274 chromeos::WallpaperManager::Get();
275 chromeos::WallpaperInfo info;
277 if (wallpaper_manager->GetLoggedInUserWallpaperInfo(&info))
278 dict->SetString("currentWallpaper", info.location);
280 #if defined(GOOGLE_CHROME_BUILD)
281 dict->SetString("manifestBaseURL", kWallpaperManifestBaseURL);
284 Profile* profile = Profile::FromBrowserContext(browser_context());
285 std::string app_name(
286 profile->GetPrefs()->GetString(prefs::kCurrentWallpaperAppName));
287 if (!app_name.empty())
288 dict->SetString("wallpaperAppName", app_name);
290 dict->SetBoolean("isOEMDefaultWallpaper", IsOEMDefaultWallpaper());
291 dict->SetBoolean("isExperimental", true);
292 dict->SetString("canceledWallpaper",
293 wallpaper_api_util::kCancelWallpaperMessage);
297 bool WallpaperPrivateGetSyncSettingFunction::RunSync() {
298 Profile* profile = Profile::FromBrowserContext(browser_context());
299 ProfileSyncService* sync =
300 ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile);
301 base::DictionaryValue* dict = new base::DictionaryValue();
303 dict->SetBoolean("syncThemes",
304 sync->GetActiveDataTypes().Has(syncer::THEMES));
308 WallpaperPrivateSetWallpaperIfExistsFunction::
309 WallpaperPrivateSetWallpaperIfExistsFunction() {}
311 WallpaperPrivateSetWallpaperIfExistsFunction::
312 ~WallpaperPrivateSetWallpaperIfExistsFunction() {}
314 bool WallpaperPrivateSetWallpaperIfExistsFunction::RunAsync() {
315 #if !defined(USE_ATHENA)
316 // TODO(bshe): Support wallpaper manager in Athena, crbug.com/408734.
317 params = set_wallpaper_if_exists::Params::Create(*args_);
318 EXTENSION_FUNCTION_VALIDATE(params);
320 user_id_ = user_manager::UserManager::Get()->GetActiveUser()->email();
322 base::FilePath wallpaper_path;
323 base::FilePath fallback_path;
324 chromeos::WallpaperManager::WallpaperResolution resolution =
325 chromeos::WallpaperManager::GetAppropriateResolution();
327 std::string file_name = GURL(params->url).ExtractFileName();
328 CHECK(PathService::Get(chrome::DIR_CHROMEOS_WALLPAPERS,
330 fallback_path = wallpaper_path.Append(file_name);
331 if (params->layout != wallpaper_private::WALLPAPER_LAYOUT_STRETCH &&
332 resolution == chromeos::WallpaperManager::WALLPAPER_RESOLUTION_SMALL) {
333 file_name = base::FilePath(file_name).InsertBeforeExtension(
334 chromeos::kSmallWallpaperSuffix).value();
336 wallpaper_path = wallpaper_path.Append(file_name);
338 sequence_token_ = BrowserThread::GetBlockingPool()->
339 GetNamedSequenceToken(chromeos::kWallpaperSequenceTokenName);
340 scoped_refptr<base::SequencedTaskRunner> task_runner =
341 BrowserThread::GetBlockingPool()->
342 GetSequencedTaskRunnerWithShutdownBehavior(sequence_token_,
343 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN);
345 task_runner->PostTask(FROM_HERE,
347 &WallpaperPrivateSetWallpaperIfExistsFunction::
348 ReadFileAndInitiateStartDecode,
349 this, wallpaper_path, fallback_path));
354 void WallpaperPrivateSetWallpaperIfExistsFunction::
355 ReadFileAndInitiateStartDecode(const base::FilePath& file_path,
356 const base::FilePath& fallback_path) {
357 DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
360 base::FilePath path = file_path;
362 if (!base::PathExists(file_path))
363 path = fallback_path;
365 if (base::PathExists(path) &&
366 base::ReadFileToString(path, &data)) {
367 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
368 base::Bind(&WallpaperPrivateSetWallpaperIfExistsFunction::StartDecode,
372 std::string error = base::StringPrintf(
373 "Failed to set wallpaper %s from file system.",
374 path.BaseName().value().c_str());
375 BrowserThread::PostTask(
376 BrowserThread::UI, FROM_HERE,
377 base::Bind(&WallpaperPrivateSetWallpaperIfExistsFunction::OnFileNotExists,
381 void WallpaperPrivateSetWallpaperIfExistsFunction::OnWallpaperDecoded(
382 const gfx::ImageSkia& image) {
383 // Set unsafe_wallpaper_decoder_ to null since the decoding already finished.
384 unsafe_wallpaper_decoder_ = NULL;
386 chromeos::WallpaperManager* wallpaper_manager =
387 chromeos::WallpaperManager::Get();
388 ash::WallpaperLayout layout = wallpaper_api_util::GetLayoutEnum(
389 wallpaper_private::ToString(params->layout));
391 bool update_wallpaper =
392 user_id_ == user_manager::UserManager::Get()->GetActiveUser()->email();
393 wallpaper_manager->SetWallpaperFromImageSkia(
394 user_id_, image, layout, update_wallpaper);
395 bool is_persistent = !user_manager::UserManager::Get()
396 ->IsCurrentUserNonCryptohomeDataEphemeral();
397 chromeos::WallpaperInfo info = {params->url, layout,
398 user_manager::User::ONLINE,
399 base::Time::Now().LocalMidnight()};
400 wallpaper_manager->SetUserWallpaperInfo(user_id_, info, is_persistent);
401 SetResult(new base::FundamentalValue(true));
402 Profile* profile = Profile::FromBrowserContext(browser_context());
403 // This API is only available to the component wallpaper picker. We do not
404 // need to show the app's name if it is the component wallpaper picker. So set
405 // the pref to empty string.
406 profile->GetPrefs()->SetString(prefs::kCurrentWallpaperAppName,
411 void WallpaperPrivateSetWallpaperIfExistsFunction::OnFileNotExists(
412 const std::string& error) {
413 SetResult(new base::FundamentalValue(false));
417 WallpaperPrivateSetWallpaperFunction::WallpaperPrivateSetWallpaperFunction() {
420 WallpaperPrivateSetWallpaperFunction::~WallpaperPrivateSetWallpaperFunction() {
423 bool WallpaperPrivateSetWallpaperFunction::RunAsync() {
424 params = set_wallpaper::Params::Create(*args_);
425 EXTENSION_FUNCTION_VALIDATE(params);
427 // Gets email address while at UI thread.
428 user_id_ = user_manager::UserManager::Get()->GetActiveUser()->email();
430 StartDecode(params->wallpaper);
435 void WallpaperPrivateSetWallpaperFunction::OnWallpaperDecoded(
436 const gfx::ImageSkia& image) {
438 // Set unsafe_wallpaper_decoder_ to null since the decoding already finished.
439 unsafe_wallpaper_decoder_ = NULL;
441 sequence_token_ = BrowserThread::GetBlockingPool()->
442 GetNamedSequenceToken(chromeos::kWallpaperSequenceTokenName);
443 scoped_refptr<base::SequencedTaskRunner> task_runner =
444 BrowserThread::GetBlockingPool()->
445 GetSequencedTaskRunnerWithShutdownBehavior(sequence_token_,
446 base::SequencedWorkerPool::BLOCK_SHUTDOWN);
448 task_runner->PostTask(FROM_HERE,
449 base::Bind(&WallpaperPrivateSetWallpaperFunction::SaveToFile, this));
452 void WallpaperPrivateSetWallpaperFunction::SaveToFile() {
453 DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
455 std::string file_name = GURL(params->url).ExtractFileName();
456 if (SaveData(chrome::DIR_CHROMEOS_WALLPAPERS, file_name, params->wallpaper)) {
457 wallpaper_.EnsureRepsForSupportedScales();
458 scoped_ptr<gfx::ImageSkia> deep_copy(wallpaper_.DeepCopy());
459 // ImageSkia is not RefCountedThreadSafe. Use a deep copied ImageSkia if
460 // post to another thread.
461 BrowserThread::PostTask(
464 base::Bind(&WallpaperPrivateSetWallpaperFunction::SetDecodedWallpaper,
466 base::Passed(deep_copy.Pass())));
468 base::FilePath wallpaper_dir;
469 CHECK(PathService::Get(chrome::DIR_CHROMEOS_WALLPAPERS, &wallpaper_dir));
470 base::FilePath file_path = wallpaper_dir.Append(
471 file_name).InsertBeforeExtension(chromeos::kSmallWallpaperSuffix);
472 if (base::PathExists(file_path))
474 // Generates and saves small resolution wallpaper. Uses CENTER_CROPPED to
475 // maintain the aspect ratio after resize.
476 chromeos::WallpaperManager::Get()->ResizeAndSaveWallpaper(
479 ash::WALLPAPER_LAYOUT_CENTER_CROPPED,
480 chromeos::kSmallWallpaperMaxWidth,
481 chromeos::kSmallWallpaperMaxHeight,
484 std::string error = base::StringPrintf(
485 "Failed to create/write wallpaper to %s.", file_name.c_str());
486 BrowserThread::PostTask(
487 BrowserThread::UI, FROM_HERE,
488 base::Bind(&WallpaperPrivateSetWallpaperFunction::OnFailure,
493 void WallpaperPrivateSetWallpaperFunction::SetDecodedWallpaper(
494 scoped_ptr<gfx::ImageSkia> image) {
495 chromeos::WallpaperManager* wallpaper_manager =
496 chromeos::WallpaperManager::Get();
498 ash::WallpaperLayout layout = wallpaper_api_util::GetLayoutEnum(
499 wallpaper_private::ToString(params->layout));
501 bool update_wallpaper =
502 user_id_ == user_manager::UserManager::Get()->GetActiveUser()->email();
503 wallpaper_manager->SetWallpaperFromImageSkia(
504 user_id_, *image.get(), layout, update_wallpaper);
506 bool is_persistent = !user_manager::UserManager::Get()
507 ->IsCurrentUserNonCryptohomeDataEphemeral();
508 chromeos::WallpaperInfo info = {params->url, layout,
509 user_manager::User::ONLINE,
510 base::Time::Now().LocalMidnight()};
511 Profile* profile = Profile::FromBrowserContext(browser_context());
512 // This API is only available to the component wallpaper picker. We do not
513 // need to show the app's name if it is the component wallpaper picker. So set
514 // the pref to empty string.
515 profile->GetPrefs()->SetString(prefs::kCurrentWallpaperAppName,
517 wallpaper_manager->SetUserWallpaperInfo(user_id_, info, is_persistent);
521 WallpaperPrivateResetWallpaperFunction::
522 WallpaperPrivateResetWallpaperFunction() {}
524 WallpaperPrivateResetWallpaperFunction::
525 ~WallpaperPrivateResetWallpaperFunction() {}
527 bool WallpaperPrivateResetWallpaperFunction::RunAsync() {
528 chromeos::WallpaperManager* wallpaper_manager =
529 chromeos::WallpaperManager::Get();
530 user_manager::UserManager* user_manager = user_manager::UserManager::Get();
532 std::string user_id = user_manager->GetActiveUser()->email();
533 wallpaper_manager->RemoveUserWallpaperInfo(user_id);
535 chromeos::WallpaperInfo info = {std::string(),
536 ash::WALLPAPER_LAYOUT_CENTER,
537 user_manager::User::DEFAULT,
538 base::Time::Now().LocalMidnight()};
540 !user_manager->IsCurrentUserNonCryptohomeDataEphemeral();
541 wallpaper_manager->SetUserWallpaperInfo(user_id, info, is_persistent);
543 wallpaper_manager->SetDefaultWallpaperNow(user_id);
544 Profile* profile = Profile::FromBrowserContext(browser_context());
545 // This API is only available to the component wallpaper picker. We do not
546 // need to show the app's name if it is the component wallpaper picker. So set
547 // the pref to empty string.
548 profile->GetPrefs()->SetString(prefs::kCurrentWallpaperAppName,
553 WallpaperPrivateSetCustomWallpaperFunction::
554 WallpaperPrivateSetCustomWallpaperFunction() {}
556 WallpaperPrivateSetCustomWallpaperFunction::
557 ~WallpaperPrivateSetCustomWallpaperFunction() {}
559 bool WallpaperPrivateSetCustomWallpaperFunction::RunAsync() {
560 params = set_custom_wallpaper::Params::Create(*args_);
561 EXTENSION_FUNCTION_VALIDATE(params);
563 // Gets email address and username hash while at UI thread.
564 user_id_ = user_manager::UserManager::Get()->GetActiveUser()->email();
566 user_manager::UserManager::Get()->GetActiveUser()->username_hash();
568 StartDecode(params->wallpaper);
573 void WallpaperPrivateSetCustomWallpaperFunction::OnWallpaperDecoded(
574 const gfx::ImageSkia& image) {
575 chromeos::WallpaperManager* wallpaper_manager =
576 chromeos::WallpaperManager::Get();
577 base::FilePath thumbnail_path = wallpaper_manager->GetCustomWallpaperPath(
578 chromeos::kThumbnailWallpaperSubDir, user_id_hash_, params->file_name);
580 sequence_token_ = BrowserThread::GetBlockingPool()->
581 GetNamedSequenceToken(chromeos::kWallpaperSequenceTokenName);
582 scoped_refptr<base::SequencedTaskRunner> task_runner =
583 BrowserThread::GetBlockingPool()->
584 GetSequencedTaskRunnerWithShutdownBehavior(sequence_token_,
585 base::SequencedWorkerPool::BLOCK_SHUTDOWN);
587 ash::WallpaperLayout layout = wallpaper_api_util::GetLayoutEnum(
588 wallpaper_private::ToString(params->layout));
590 bool update_wallpaper =
591 user_id_ == user_manager::UserManager::Get()->GetActiveUser()->email();
592 wallpaper_manager->SetCustomWallpaper(user_id_,
596 user_manager::User::CUSTOMIZED,
599 unsafe_wallpaper_decoder_ = NULL;
601 Profile* profile = Profile::FromBrowserContext(browser_context());
602 // This API is only available to the component wallpaper picker. We do not
603 // need to show the app's name if it is the component wallpaper picker. So set
604 // the pref to empty string.
605 profile->GetPrefs()->SetString(prefs::kCurrentWallpaperAppName,
608 if (params->generate_thumbnail) {
609 image.EnsureRepsForSupportedScales();
610 scoped_ptr<gfx::ImageSkia> deep_copy(image.DeepCopy());
611 // Generates thumbnail before call api function callback. We can then
612 // request thumbnail in the javascript callback.
613 task_runner->PostTask(FROM_HERE,
615 &WallpaperPrivateSetCustomWallpaperFunction::GenerateThumbnail,
616 this, thumbnail_path, base::Passed(&deep_copy)));
622 void WallpaperPrivateSetCustomWallpaperFunction::GenerateThumbnail(
623 const base::FilePath& thumbnail_path, scoped_ptr<gfx::ImageSkia> image) {
624 DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
626 if (!base::PathExists(thumbnail_path.DirName()))
627 base::CreateDirectory(thumbnail_path.DirName());
629 scoped_refptr<base::RefCountedBytes> data;
630 chromeos::WallpaperManager::Get()->ResizeImage(
632 ash::WALLPAPER_LAYOUT_STRETCH,
633 chromeos::kWallpaperThumbnailWidth,
634 chromeos::kWallpaperThumbnailHeight,
637 BrowserThread::PostTask(
638 BrowserThread::UI, FROM_HERE,
640 &WallpaperPrivateSetCustomWallpaperFunction::ThumbnailGenerated,
644 void WallpaperPrivateSetCustomWallpaperFunction::ThumbnailGenerated(
645 base::RefCountedBytes* data) {
646 BinaryValue* result = BinaryValue::CreateWithCopiedBuffer(
647 reinterpret_cast<const char*>(data->front()), data->size());
652 WallpaperPrivateSetCustomWallpaperLayoutFunction::
653 WallpaperPrivateSetCustomWallpaperLayoutFunction() {}
655 WallpaperPrivateSetCustomWallpaperLayoutFunction::
656 ~WallpaperPrivateSetCustomWallpaperLayoutFunction() {}
658 bool WallpaperPrivateSetCustomWallpaperLayoutFunction::RunAsync() {
659 scoped_ptr<set_custom_wallpaper_layout::Params> params(
660 set_custom_wallpaper_layout::Params::Create(*args_));
661 EXTENSION_FUNCTION_VALIDATE(params);
663 chromeos::WallpaperManager* wallpaper_manager =
664 chromeos::WallpaperManager::Get();
665 chromeos::WallpaperInfo info;
666 wallpaper_manager->GetLoggedInUserWallpaperInfo(&info);
667 if (info.type != user_manager::User::CUSTOMIZED) {
668 SetError("Only custom wallpaper can change layout.");
672 info.layout = wallpaper_api_util::GetLayoutEnum(
673 wallpaper_private::ToString(params->layout));
676 user_manager::UserManager::Get()->GetActiveUser()->email();
677 bool is_persistent = !user_manager::UserManager::Get()
678 ->IsCurrentUserNonCryptohomeDataEphemeral();
679 wallpaper_manager->SetUserWallpaperInfo(email, info, is_persistent);
680 wallpaper_manager->UpdateWallpaper(false /* clear_cache */);
683 // Gets email address while at UI thread.
687 WallpaperPrivateMinimizeInactiveWindowsFunction::
688 WallpaperPrivateMinimizeInactiveWindowsFunction() {
691 WallpaperPrivateMinimizeInactiveWindowsFunction::
692 ~WallpaperPrivateMinimizeInactiveWindowsFunction() {
695 bool WallpaperPrivateMinimizeInactiveWindowsFunction::RunAsync() {
696 WindowStateManager::MinimizeInactiveWindows(
697 user_manager::UserManager::Get()->GetActiveUser()->username_hash());
701 WallpaperPrivateRestoreMinimizedWindowsFunction::
702 WallpaperPrivateRestoreMinimizedWindowsFunction() {
705 WallpaperPrivateRestoreMinimizedWindowsFunction::
706 ~WallpaperPrivateRestoreMinimizedWindowsFunction() {
709 bool WallpaperPrivateRestoreMinimizedWindowsFunction::RunAsync() {
710 WindowStateManager::RestoreWindows(
711 user_manager::UserManager::Get()->GetActiveUser()->username_hash());
715 WallpaperPrivateGetThumbnailFunction::WallpaperPrivateGetThumbnailFunction() {
718 WallpaperPrivateGetThumbnailFunction::~WallpaperPrivateGetThumbnailFunction() {
721 bool WallpaperPrivateGetThumbnailFunction::RunAsync() {
722 scoped_ptr<get_thumbnail::Params> params(
723 get_thumbnail::Params::Create(*args_));
724 EXTENSION_FUNCTION_VALIDATE(params);
726 base::FilePath thumbnail_path;
728 user_manager::UserManager::Get()->GetActiveUser()->email();
729 if (params->source == get_thumbnail::Params::SOURCE_ONLINE) {
730 std::string file_name = GURL(params->url_or_file).ExtractFileName();
731 CHECK(PathService::Get(chrome::DIR_CHROMEOS_WALLPAPER_THUMBNAILS,
733 thumbnail_path = thumbnail_path.Append(file_name);
735 if (!IsOEMDefaultWallpaper()) {
736 SetError("No OEM wallpaper.");
741 // TODO(bshe): Small resolution wallpaper is used here as wallpaper
742 // thumbnail. We should either resize it or include a wallpaper thumbnail in
743 // addition to large and small wallpaper resolutions.
744 thumbnail_path = CommandLine::ForCurrentProcess()->GetSwitchValuePath(
745 ash::switches::kAshDefaultWallpaperSmall);
748 sequence_token_ = BrowserThread::GetBlockingPool()->
749 GetNamedSequenceToken(chromeos::kWallpaperSequenceTokenName);
750 scoped_refptr<base::SequencedTaskRunner> task_runner =
751 BrowserThread::GetBlockingPool()->
752 GetSequencedTaskRunnerWithShutdownBehavior(sequence_token_,
753 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN);
755 task_runner->PostTask(FROM_HERE,
756 base::Bind(&WallpaperPrivateGetThumbnailFunction::Get, this,
761 void WallpaperPrivateGetThumbnailFunction::Failure(
762 const std::string& file_name) {
763 SetError(base::StringPrintf("Failed to access wallpaper thumbnails for %s.",
768 void WallpaperPrivateGetThumbnailFunction::FileNotLoaded() {
772 void WallpaperPrivateGetThumbnailFunction::FileLoaded(
773 const std::string& data) {
774 BinaryValue* thumbnail = BinaryValue::CreateWithCopiedBuffer(data.c_str(),
776 SetResult(thumbnail);
780 void WallpaperPrivateGetThumbnailFunction::Get(const base::FilePath& path) {
781 DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
784 if (GetData(path, &data)) {
786 BrowserThread::PostTask(
787 BrowserThread::UI, FROM_HERE,
788 base::Bind(&WallpaperPrivateGetThumbnailFunction::FileNotLoaded, this));
790 BrowserThread::PostTask(
791 BrowserThread::UI, FROM_HERE,
792 base::Bind(&WallpaperPrivateGetThumbnailFunction::FileLoaded, this,
796 BrowserThread::PostTask(
797 BrowserThread::UI, FROM_HERE,
798 base::Bind(&WallpaperPrivateGetThumbnailFunction::Failure, this,
799 path.BaseName().value()));
803 WallpaperPrivateSaveThumbnailFunction::WallpaperPrivateSaveThumbnailFunction() {
806 WallpaperPrivateSaveThumbnailFunction::
807 ~WallpaperPrivateSaveThumbnailFunction() {}
809 bool WallpaperPrivateSaveThumbnailFunction::RunAsync() {
810 scoped_ptr<save_thumbnail::Params> params(
811 save_thumbnail::Params::Create(*args_));
812 EXTENSION_FUNCTION_VALIDATE(params);
814 sequence_token_ = BrowserThread::GetBlockingPool()->
815 GetNamedSequenceToken(chromeos::kWallpaperSequenceTokenName);
816 scoped_refptr<base::SequencedTaskRunner> task_runner =
817 BrowserThread::GetBlockingPool()->
818 GetSequencedTaskRunnerWithShutdownBehavior(sequence_token_,
819 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN);
821 task_runner->PostTask(FROM_HERE,
822 base::Bind(&WallpaperPrivateSaveThumbnailFunction::Save,
823 this, params->data, GURL(params->url).ExtractFileName()));
827 void WallpaperPrivateSaveThumbnailFunction::Failure(
828 const std::string& file_name) {
829 SetError(base::StringPrintf("Failed to create/write thumbnail of %s.",
834 void WallpaperPrivateSaveThumbnailFunction::Success() {
838 void WallpaperPrivateSaveThumbnailFunction::Save(const std::string& data,
839 const std::string& file_name) {
840 DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
842 if (SaveData(chrome::DIR_CHROMEOS_WALLPAPER_THUMBNAILS, file_name, data)) {
843 BrowserThread::PostTask(
844 BrowserThread::UI, FROM_HERE,
845 base::Bind(&WallpaperPrivateSaveThumbnailFunction::Success, this));
847 BrowserThread::PostTask(
848 BrowserThread::UI, FROM_HERE,
849 base::Bind(&WallpaperPrivateSaveThumbnailFunction::Failure,
854 WallpaperPrivateGetOfflineWallpaperListFunction::
855 WallpaperPrivateGetOfflineWallpaperListFunction() {
858 WallpaperPrivateGetOfflineWallpaperListFunction::
859 ~WallpaperPrivateGetOfflineWallpaperListFunction() {
862 bool WallpaperPrivateGetOfflineWallpaperListFunction::RunAsync() {
863 sequence_token_ = BrowserThread::GetBlockingPool()->
864 GetNamedSequenceToken(chromeos::kWallpaperSequenceTokenName);
865 scoped_refptr<base::SequencedTaskRunner> task_runner =
866 BrowserThread::GetBlockingPool()->
867 GetSequencedTaskRunnerWithShutdownBehavior(sequence_token_,
868 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN);
870 task_runner->PostTask(FROM_HERE,
871 base::Bind(&WallpaperPrivateGetOfflineWallpaperListFunction::GetList,
876 void WallpaperPrivateGetOfflineWallpaperListFunction::GetList() {
877 DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
879 std::vector<std::string> file_list;
880 base::FilePath wallpaper_dir;
881 CHECK(PathService::Get(chrome::DIR_CHROMEOS_WALLPAPERS, &wallpaper_dir));
882 if (base::DirectoryExists(wallpaper_dir)) {
883 base::FileEnumerator files(wallpaper_dir, false,
884 base::FileEnumerator::FILES);
885 for (base::FilePath current = files.Next(); !current.empty();
886 current = files.Next()) {
887 std::string file_name = current.BaseName().RemoveExtension().value();
888 // Do not add file name of small resolution wallpaper to the list.
889 if (!EndsWith(file_name, chromeos::kSmallWallpaperSuffix, true))
890 file_list.push_back(current.BaseName().value());
893 BrowserThread::PostTask(
894 BrowserThread::UI, FROM_HERE,
895 base::Bind(&WallpaperPrivateGetOfflineWallpaperListFunction::OnComplete,
899 void WallpaperPrivateGetOfflineWallpaperListFunction::OnComplete(
900 const std::vector<std::string>& file_list) {
901 base::ListValue* results = new base::ListValue();
902 results->AppendStrings(file_list);