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"
12 #include "ash/desktop_background/desktop_background_controller.h"
13 #include "ash/shell.h"
14 #include "ash/wm/mru_window_tracker.h"
15 #include "ash/wm/window_state.h"
16 #include "ash/wm/window_util.h"
17 #include "base/command_line.h"
18 #include "base/files/file_enumerator.h"
19 #include "base/files/file_util.h"
20 #include "base/memory/scoped_ptr.h"
21 #include "base/path_service.h"
22 #include "base/prefs/pref_service.h"
23 #include "base/stl_util.h"
24 #include "base/strings/string_number_conversions.h"
25 #include "base/strings/stringprintf.h"
26 #include "base/threading/worker_pool.h"
27 #include "chrome/browser/browser_process.h"
28 #include "chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.h"
29 #include "chrome/browser/chromeos/profiles/profile_helper.h"
30 #include "chrome/browser/profiles/profile.h"
31 #include "chrome/browser/sync/profile_sync_service.h"
32 #include "chrome/browser/sync/profile_sync_service_factory.h"
33 #include "chrome/common/chrome_paths.h"
34 #include "chrome/common/pref_names.h"
35 #include "chrome/grit/generated_resources.h"
36 #include "chromeos/chromeos_switches.h"
37 #include "components/user_manager/user.h"
38 #include "components/user_manager/user_manager.h"
39 #include "components/wallpaper/wallpaper_layout.h"
40 #include "content/public/browser/browser_thread.h"
41 #include "extensions/browser/event_router.h"
42 #include "grit/components_strings.h"
43 #include "ui/base/l10n/l10n_util.h"
44 #include "ui/base/webui/web_ui_util.h"
45 #include "ui/strings/grit/app_locale_settings.h"
48 using base::BinaryValue
;
49 using content::BrowserThread
;
51 namespace wallpaper_base
= extensions::api::wallpaper
;
52 namespace wallpaper_private
= extensions::api::wallpaper_private
;
53 namespace set_wallpaper_if_exists
= wallpaper_private::SetWallpaperIfExists
;
54 namespace set_wallpaper
= wallpaper_private::SetWallpaper
;
55 namespace set_custom_wallpaper
= wallpaper_private::SetCustomWallpaper
;
56 namespace set_custom_wallpaper_layout
=
57 wallpaper_private::SetCustomWallpaperLayout
;
58 namespace get_thumbnail
= wallpaper_private::GetThumbnail
;
59 namespace save_thumbnail
= wallpaper_private::SaveThumbnail
;
60 namespace get_offline_wallpaper_list
=
61 wallpaper_private::GetOfflineWallpaperList
;
65 #if defined(GOOGLE_CHROME_BUILD)
66 const char kWallpaperManifestBaseURL
[] =
67 "https://storage.googleapis.com/chromeos-wallpaper-public/manifest_";
70 bool IsOEMDefaultWallpaper() {
71 return base::CommandLine::ForCurrentProcess()->HasSwitch(
72 chromeos::switches::kDefaultWallpaperIsOem
);
75 // Saves |data| as |file_name| to directory with |key|. Return false if the
76 // directory can not be found/created or failed to write file.
77 bool SaveData(int key
,
78 const std::string
& file_name
,
79 const std::vector
<char>& data
) {
80 base::FilePath data_dir
;
81 CHECK(PathService::Get(key
, &data_dir
));
82 if (!base::DirectoryExists(data_dir
) &&
83 !base::CreateDirectory(data_dir
)) {
86 base::FilePath file_path
= data_dir
.Append(file_name
);
88 return base::PathExists(file_path
) ||
89 base::WriteFile(file_path
, vector_as_array(&data
), data
.size()) != -1;
92 // Gets |file_name| from directory with |key|. Return false if the directory can
93 // not be found or failed to read file to string |data|. Note if the |file_name|
94 // can not be found in the directory, return true with empty |data|. It is
95 // expected that we may try to access file which did not saved yet.
96 bool GetData(const base::FilePath
& path
, std::string
* data
) {
97 base::FilePath data_dir
= path
.DirName();
98 if (!base::DirectoryExists(data_dir
) &&
99 !base::CreateDirectory(data_dir
))
102 return !base::PathExists(path
) ||
103 base::ReadFileToString(path
, data
);
106 // Gets the |User| for a given |BrowserContext|. The function will only return
108 const user_manager::User
* GetUserFromBrowserContext(
109 content::BrowserContext
* context
) {
110 Profile
* profile
= Profile::FromBrowserContext(context
);
112 const user_manager::User
* user
=
113 chromeos::ProfileHelper::Get()->GetUserByProfile(profile
);
118 // WindowStateManager remembers which windows have been minimized in order to
119 // restore them when the wallpaper viewer is hidden.
120 class WindowStateManager
: public aura::WindowObserver
{
122 typedef std::map
<std::string
, std::set
<aura::Window
*> >
123 UserIDHashWindowListMap
;
125 // Minimizes all windows except the active window.
126 static void MinimizeInactiveWindows(const std::string
& user_id_hash
);
128 // Unminimizes all minimized windows restoring them to their previous state.
129 // This should only be called after calling MinimizeInactiveWindows.
130 static void RestoreWindows(const std::string
& user_id_hash
);
133 WindowStateManager();
135 ~WindowStateManager() override
;
137 // Store all unminimized windows except |active_window| and minimize them.
138 // All the windows are saved in a map and the key value is |user_id_hash|.
139 void BuildWindowListAndMinimizeInactiveForUser(
140 const std::string
& user_id_hash
, aura::Window
* active_window
);
142 // Unminimize all the stored windows for |user_id_hash|.
143 void RestoreMinimizedWindows(const std::string
& user_id_hash
);
145 // Remove the observer from |window| if |window| is no longer referenced in
146 // user_id_hash_window_list_map_.
147 void RemoveObserverIfUnreferenced(aura::Window
* window
);
149 // aura::WindowObserver overrides.
150 void OnWindowDestroyed(aura::Window
* window
) override
;
152 // aura::WindowObserver overrides.
153 void OnWindowStackingChanged(aura::Window
* window
) override
;
155 // Map of user id hash and associated list of minimized windows.
156 UserIDHashWindowListMap user_id_hash_window_list_map_
;
158 DISALLOW_COPY_AND_ASSIGN(WindowStateManager
);
162 WindowStateManager
* g_window_state_manager
= NULL
;
165 void WindowStateManager::MinimizeInactiveWindows(
166 const std::string
& user_id_hash
) {
167 if (!g_window_state_manager
)
168 g_window_state_manager
= new WindowStateManager();
169 g_window_state_manager
->BuildWindowListAndMinimizeInactiveForUser(
170 user_id_hash
, ash::wm::GetActiveWindow());
174 void WindowStateManager::RestoreWindows(const std::string
& user_id_hash
) {
175 if (!g_window_state_manager
) {
176 DCHECK(false) << "This should only be called after calling "
177 << "MinimizeInactiveWindows.";
181 g_window_state_manager
->RestoreMinimizedWindows(user_id_hash
);
182 if (g_window_state_manager
->user_id_hash_window_list_map_
.empty()) {
183 delete g_window_state_manager
;
184 g_window_state_manager
= NULL
;
188 WindowStateManager::WindowStateManager() {}
190 WindowStateManager::~WindowStateManager() {}
192 void WindowStateManager::BuildWindowListAndMinimizeInactiveForUser(
193 const std::string
& user_id_hash
, aura::Window
* active_window
) {
194 if (user_id_hash_window_list_map_
.find(user_id_hash
) ==
195 user_id_hash_window_list_map_
.end()) {
196 user_id_hash_window_list_map_
[user_id_hash
] = std::set
<aura::Window
*>();
198 std::set
<aura::Window
*>* results
=
199 &user_id_hash_window_list_map_
[user_id_hash
];
201 std::vector
<aura::Window
*> windows
= ash::Shell::GetInstance()->
202 mru_window_tracker()->BuildWindowListIgnoreModal();
204 for (std::vector
<aura::Window
*>::iterator iter
= windows
.begin();
205 iter
!= windows
.end(); ++iter
) {
206 // Ignore active window and minimized windows.
207 if (*iter
== active_window
|| ash::wm::GetWindowState(*iter
)->IsMinimized())
210 if (!(*iter
)->HasObserver(this))
211 (*iter
)->AddObserver(this);
213 results
->insert(*iter
);
214 ash::wm::GetWindowState(*iter
)->Minimize();
218 void WindowStateManager::RestoreMinimizedWindows(
219 const std::string
& user_id_hash
) {
220 UserIDHashWindowListMap::iterator it
=
221 user_id_hash_window_list_map_
.find(user_id_hash
);
222 if (it
== user_id_hash_window_list_map_
.end()) {
223 DCHECK(false) << "This should only be called after calling "
224 << "MinimizeInactiveWindows.";
228 std::set
<aura::Window
*> removed_windows
;
229 removed_windows
.swap(it
->second
);
230 user_id_hash_window_list_map_
.erase(it
);
232 for (std::set
<aura::Window
*>::iterator iter
= removed_windows
.begin();
233 iter
!= removed_windows
.end(); ++iter
) {
234 ash::wm::GetWindowState(*iter
)->Unminimize();
235 RemoveObserverIfUnreferenced(*iter
);
239 void WindowStateManager::RemoveObserverIfUnreferenced(aura::Window
* window
) {
240 for (UserIDHashWindowListMap::iterator iter
=
241 user_id_hash_window_list_map_
.begin();
242 iter
!= user_id_hash_window_list_map_
.end();
244 if (iter
->second
.find(window
) != iter
->second
.end())
247 // Remove observer if |window| is not observed by any users.
248 window
->RemoveObserver(this);
251 void WindowStateManager::OnWindowDestroyed(aura::Window
* window
) {
252 for (UserIDHashWindowListMap::iterator iter
=
253 user_id_hash_window_list_map_
.begin();
254 iter
!= user_id_hash_window_list_map_
.end();
256 iter
->second
.erase(window
);
260 void WindowStateManager::OnWindowStackingChanged(aura::Window
* window
) {
261 // If user interacted with the |window| while wallpaper picker is opening,
262 // removes the |window| from observed list.
263 for (auto iter
= user_id_hash_window_list_map_
.begin();
264 iter
!= user_id_hash_window_list_map_
.end(); ++iter
) {
265 iter
->second
.erase(window
);
267 window
->RemoveObserver(this);
272 bool WallpaperPrivateGetStringsFunction::RunSync() {
273 base::DictionaryValue
* dict
= new base::DictionaryValue();
276 #define SET_STRING(id, idr) \
277 dict->SetString(id, l10n_util::GetStringUTF16(idr))
278 SET_STRING("webFontFamily", IDS_WEB_FONT_FAMILY
);
279 SET_STRING("webFontSize", IDS_WEB_FONT_SIZE
);
280 SET_STRING("allCategoryLabel", IDS_WALLPAPER_MANAGER_ALL_CATEGORY_LABEL
);
281 SET_STRING("deleteCommandLabel", IDS_WALLPAPER_MANAGER_DELETE_COMMAND_LABEL
);
282 SET_STRING("customCategoryLabel",
283 IDS_WALLPAPER_MANAGER_CUSTOM_CATEGORY_LABEL
);
284 SET_STRING("selectCustomLabel",
285 IDS_WALLPAPER_MANAGER_SELECT_CUSTOM_LABEL
);
286 SET_STRING("positionLabel", IDS_WALLPAPER_MANAGER_POSITION_LABEL
);
287 SET_STRING("colorLabel", IDS_WALLPAPER_MANAGER_COLOR_LABEL
);
288 SET_STRING("centerCroppedLayout",
289 IDS_OPTIONS_WALLPAPER_CENTER_CROPPED_LAYOUT
);
290 SET_STRING("centerLayout", IDS_OPTIONS_WALLPAPER_CENTER_LAYOUT
);
291 SET_STRING("stretchLayout", IDS_OPTIONS_WALLPAPER_STRETCH_LAYOUT
);
292 SET_STRING("connectionFailed", IDS_WALLPAPER_MANAGER_ACCESS_FAIL
);
293 SET_STRING("downloadFailed", IDS_WALLPAPER_MANAGER_DOWNLOAD_FAIL
);
294 SET_STRING("downloadCanceled", IDS_WALLPAPER_MANAGER_DOWNLOAD_CANCEL
);
295 SET_STRING("customWallpaperWarning",
296 IDS_WALLPAPER_MANAGER_SHOW_CUSTOM_WALLPAPER_ON_START_WARNING
);
297 SET_STRING("accessFileFailure", IDS_WALLPAPER_MANAGER_ACCESS_FILE_FAILURE
);
298 SET_STRING("invalidWallpaper", IDS_WALLPAPER_MANAGER_INVALID_WALLPAPER
);
299 SET_STRING("surpriseMeLabel", IDS_WALLPAPER_MANAGER_SURPRISE_ME_LABEL
);
300 SET_STRING("learnMore", IDS_LEARN_MORE
);
301 SET_STRING("currentWallpaperSetByMessage",
302 IDS_CURRENT_WALLPAPER_SET_BY_MESSAGE
);
305 const std::string
& app_locale
= g_browser_process
->GetApplicationLocale();
306 webui::SetLoadTimeDataDefaults(app_locale
, dict
);
308 chromeos::WallpaperManager
* wallpaper_manager
=
309 chromeos::WallpaperManager::Get();
310 wallpaper::WallpaperInfo info
;
312 if (wallpaper_manager
->GetLoggedInUserWallpaperInfo(&info
))
313 dict
->SetString("currentWallpaper", info
.location
);
315 #if defined(GOOGLE_CHROME_BUILD)
316 dict
->SetString("manifestBaseURL", kWallpaperManifestBaseURL
);
319 Profile
* profile
= Profile::FromBrowserContext(browser_context());
320 std::string
app_name(
321 profile
->GetPrefs()->GetString(prefs::kCurrentWallpaperAppName
));
322 if (!app_name
.empty())
323 dict
->SetString("wallpaperAppName", app_name
);
325 dict
->SetBoolean("isOEMDefaultWallpaper", IsOEMDefaultWallpaper());
326 dict
->SetString("canceledWallpaper",
327 wallpaper_api_util::kCancelWallpaperMessage
);
331 bool WallpaperPrivateGetSyncSettingFunction::RunSync() {
332 Profile
* profile
= Profile::FromBrowserContext(browser_context());
333 ProfileSyncService
* sync
=
334 ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile
);
335 base::DictionaryValue
* dict
= new base::DictionaryValue();
337 dict
->SetBoolean("syncThemes",
338 sync
->GetActiveDataTypes().Has(syncer::THEMES
));
342 WallpaperPrivateSetWallpaperIfExistsFunction::
343 WallpaperPrivateSetWallpaperIfExistsFunction() {}
345 WallpaperPrivateSetWallpaperIfExistsFunction::
346 ~WallpaperPrivateSetWallpaperIfExistsFunction() {}
348 bool WallpaperPrivateSetWallpaperIfExistsFunction::RunAsync() {
349 params
= set_wallpaper_if_exists::Params::Create(*args_
);
350 EXTENSION_FUNCTION_VALIDATE(params
);
352 // Gets email address from caller, ensuring multiprofile compatibility.
353 const user_manager::User
* user
= GetUserFromBrowserContext(browser_context());
354 user_id_
= user
->email();
356 base::FilePath wallpaper_path
;
357 base::FilePath fallback_path
;
358 chromeos::WallpaperManager::WallpaperResolution resolution
=
359 chromeos::WallpaperManager::Get()->GetAppropriateResolution();
361 std::string file_name
= GURL(params
->url
).ExtractFileName();
362 CHECK(PathService::Get(chrome::DIR_CHROMEOS_WALLPAPERS
,
364 fallback_path
= wallpaper_path
.Append(file_name
);
365 if (params
->layout
!= wallpaper_base::WALLPAPER_LAYOUT_STRETCH
&&
366 resolution
== chromeos::WallpaperManager::WALLPAPER_RESOLUTION_SMALL
) {
367 file_name
= base::FilePath(file_name
)
368 .InsertBeforeExtension(wallpaper::kSmallWallpaperSuffix
)
371 wallpaper_path
= wallpaper_path
.Append(file_name
);
373 sequence_token_
= BrowserThread::GetBlockingPool()->GetNamedSequenceToken(
374 wallpaper::kWallpaperSequenceTokenName
);
375 scoped_refptr
<base::SequencedTaskRunner
> task_runner
=
376 BrowserThread::GetBlockingPool()->
377 GetSequencedTaskRunnerWithShutdownBehavior(sequence_token_
,
378 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN
);
380 task_runner
->PostTask(FROM_HERE
,
382 &WallpaperPrivateSetWallpaperIfExistsFunction::
383 ReadFileAndInitiateStartDecode
,
384 this, wallpaper_path
, fallback_path
));
388 void WallpaperPrivateSetWallpaperIfExistsFunction::
389 ReadFileAndInitiateStartDecode(const base::FilePath
& file_path
,
390 const base::FilePath
& fallback_path
) {
391 DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
393 base::FilePath path
= file_path
;
395 if (!base::PathExists(file_path
))
396 path
= fallback_path
;
399 if (base::PathExists(path
) &&
400 base::ReadFileToString(path
, &data
)) {
401 BrowserThread::PostTask(
402 BrowserThread::UI
, FROM_HERE
,
403 base::Bind(&WallpaperPrivateSetWallpaperIfExistsFunction::StartDecode
,
404 this, std::vector
<char>(data
.begin(), data
.end())));
407 std::string error
= base::StringPrintf(
408 "Failed to set wallpaper %s from file system.",
409 path
.BaseName().value().c_str());
410 BrowserThread::PostTask(
411 BrowserThread::UI
, FROM_HERE
,
412 base::Bind(&WallpaperPrivateSetWallpaperIfExistsFunction::OnFileNotExists
,
416 void WallpaperPrivateSetWallpaperIfExistsFunction::OnWallpaperDecoded(
417 const gfx::ImageSkia
& image
) {
418 // Set unsafe_wallpaper_decoder_ to null since the decoding already finished.
419 unsafe_wallpaper_decoder_
= NULL
;
421 chromeos::WallpaperManager
* wallpaper_manager
=
422 chromeos::WallpaperManager::Get();
423 wallpaper::WallpaperLayout layout
= wallpaper_api_util::GetLayoutEnum(
424 wallpaper_base::ToString(params
->layout
));
426 bool update_wallpaper
=
427 user_id_
== user_manager::UserManager::Get()->GetActiveUser()->email();
428 wallpaper_manager
->SetWallpaperFromImageSkia(
429 user_id_
, image
, layout
, update_wallpaper
);
430 bool is_persistent
= !user_manager::UserManager::Get()
431 ->IsCurrentUserNonCryptohomeDataEphemeral();
432 wallpaper::WallpaperInfo info
= {params
->url
,
434 user_manager::User::ONLINE
,
435 base::Time::Now().LocalMidnight()};
436 wallpaper_manager
->SetUserWallpaperInfo(user_id_
, info
, is_persistent
);
437 SetResult(new base::FundamentalValue(true));
438 Profile
* profile
= Profile::FromBrowserContext(browser_context());
439 // This API is only available to the component wallpaper picker. We do not
440 // need to show the app's name if it is the component wallpaper picker. So set
441 // the pref to empty string.
442 profile
->GetPrefs()->SetString(prefs::kCurrentWallpaperAppName
,
447 void WallpaperPrivateSetWallpaperIfExistsFunction::OnFileNotExists(
448 const std::string
& error
) {
449 SetResult(new base::FundamentalValue(false));
453 WallpaperPrivateSetWallpaperFunction::WallpaperPrivateSetWallpaperFunction() {
456 WallpaperPrivateSetWallpaperFunction::~WallpaperPrivateSetWallpaperFunction() {
459 bool WallpaperPrivateSetWallpaperFunction::RunAsync() {
460 params
= set_wallpaper::Params::Create(*args_
);
461 EXTENSION_FUNCTION_VALIDATE(params
);
463 // Gets email address from caller, ensuring multiprofile compatibility.
464 const user_manager::User
* user
= GetUserFromBrowserContext(browser_context());
465 user_id_
= user
->email();
467 StartDecode(params
->wallpaper
);
472 void WallpaperPrivateSetWallpaperFunction::OnWallpaperDecoded(
473 const gfx::ImageSkia
& image
) {
475 // Set unsafe_wallpaper_decoder_ to null since the decoding already finished.
476 unsafe_wallpaper_decoder_
= NULL
;
478 sequence_token_
= BrowserThread::GetBlockingPool()->GetNamedSequenceToken(
479 wallpaper::kWallpaperSequenceTokenName
);
480 scoped_refptr
<base::SequencedTaskRunner
> task_runner
=
481 BrowserThread::GetBlockingPool()->
482 GetSequencedTaskRunnerWithShutdownBehavior(sequence_token_
,
483 base::SequencedWorkerPool::BLOCK_SHUTDOWN
);
485 task_runner
->PostTask(FROM_HERE
,
486 base::Bind(&WallpaperPrivateSetWallpaperFunction::SaveToFile
, this));
489 void WallpaperPrivateSetWallpaperFunction::SaveToFile() {
490 DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
492 std::string file_name
= GURL(params
->url
).ExtractFileName();
493 if (SaveData(chrome::DIR_CHROMEOS_WALLPAPERS
, file_name
, params
->wallpaper
)) {
494 wallpaper_
.EnsureRepsForSupportedScales();
495 scoped_ptr
<gfx::ImageSkia
> deep_copy(wallpaper_
.DeepCopy());
496 // ImageSkia is not RefCountedThreadSafe. Use a deep copied ImageSkia if
497 // post to another thread.
498 BrowserThread::PostTask(
501 base::Bind(&WallpaperPrivateSetWallpaperFunction::SetDecodedWallpaper
,
503 base::Passed(deep_copy
.Pass())));
505 base::FilePath wallpaper_dir
;
506 CHECK(PathService::Get(chrome::DIR_CHROMEOS_WALLPAPERS
, &wallpaper_dir
));
507 base::FilePath file_path
=
508 wallpaper_dir
.Append(file_name
)
509 .InsertBeforeExtension(wallpaper::kSmallWallpaperSuffix
);
510 if (base::PathExists(file_path
))
512 // Generates and saves small resolution wallpaper. Uses CENTER_CROPPED to
513 // maintain the aspect ratio after resize.
514 chromeos::WallpaperManager::Get()->ResizeAndSaveWallpaper(
515 wallpaper_
, file_path
, wallpaper::WALLPAPER_LAYOUT_CENTER_CROPPED
,
516 wallpaper::kSmallWallpaperMaxWidth
, wallpaper::kSmallWallpaperMaxHeight
,
519 std::string error
= base::StringPrintf(
520 "Failed to create/write wallpaper to %s.", file_name
.c_str());
521 BrowserThread::PostTask(
522 BrowserThread::UI
, FROM_HERE
,
523 base::Bind(&WallpaperPrivateSetWallpaperFunction::OnFailure
,
528 void WallpaperPrivateSetWallpaperFunction::SetDecodedWallpaper(
529 scoped_ptr
<gfx::ImageSkia
> image
) {
530 chromeos::WallpaperManager
* wallpaper_manager
=
531 chromeos::WallpaperManager::Get();
533 wallpaper::WallpaperLayout layout
= wallpaper_api_util::GetLayoutEnum(
534 wallpaper_base::ToString(params
->layout
));
536 bool update_wallpaper
=
537 user_id_
== user_manager::UserManager::Get()->GetActiveUser()->email();
538 wallpaper_manager
->SetWallpaperFromImageSkia(
539 user_id_
, *image
.get(), layout
, update_wallpaper
);
541 bool is_persistent
= !user_manager::UserManager::Get()
542 ->IsCurrentUserNonCryptohomeDataEphemeral();
543 wallpaper::WallpaperInfo info
= {params
->url
,
545 user_manager::User::ONLINE
,
546 base::Time::Now().LocalMidnight()};
547 Profile
* profile
= Profile::FromBrowserContext(browser_context());
548 // This API is only available to the component wallpaper picker. We do not
549 // need to show the app's name if it is the component wallpaper picker. So set
550 // the pref to empty string.
551 profile
->GetPrefs()->SetString(prefs::kCurrentWallpaperAppName
,
553 wallpaper_manager
->SetUserWallpaperInfo(user_id_
, info
, is_persistent
);
557 WallpaperPrivateResetWallpaperFunction::
558 WallpaperPrivateResetWallpaperFunction() {}
560 WallpaperPrivateResetWallpaperFunction::
561 ~WallpaperPrivateResetWallpaperFunction() {}
563 bool WallpaperPrivateResetWallpaperFunction::RunAsync() {
564 chromeos::WallpaperManager
* wallpaper_manager
=
565 chromeos::WallpaperManager::Get();
566 user_manager::UserManager
* user_manager
= user_manager::UserManager::Get();
568 std::string user_id
= user_manager
->GetActiveUser()->email();
569 wallpaper_manager
->RemoveUserWallpaperInfo(user_id
);
571 wallpaper::WallpaperInfo info
= {std::string(),
572 wallpaper::WALLPAPER_LAYOUT_CENTER
,
573 user_manager::User::DEFAULT
,
574 base::Time::Now().LocalMidnight()};
576 !user_manager
->IsCurrentUserNonCryptohomeDataEphemeral();
577 wallpaper_manager
->SetUserWallpaperInfo(user_id
, info
, is_persistent
);
579 wallpaper_manager
->SetDefaultWallpaperNow(user_id
);
580 Profile
* profile
= Profile::FromBrowserContext(browser_context());
581 // This API is only available to the component wallpaper picker. We do not
582 // need to show the app's name if it is the component wallpaper picker. So set
583 // the pref to empty string.
584 profile
->GetPrefs()->SetString(prefs::kCurrentWallpaperAppName
,
589 WallpaperPrivateSetCustomWallpaperFunction::
590 WallpaperPrivateSetCustomWallpaperFunction() {}
592 WallpaperPrivateSetCustomWallpaperFunction::
593 ~WallpaperPrivateSetCustomWallpaperFunction() {}
595 bool WallpaperPrivateSetCustomWallpaperFunction::RunAsync() {
596 params
= set_custom_wallpaper::Params::Create(*args_
);
597 EXTENSION_FUNCTION_VALIDATE(params
);
599 // Gets email address from caller, ensuring multiprofile compatibility.
600 const user_manager::User
* user
= GetUserFromBrowserContext(browser_context());
601 user_id_
= user
->email();
602 user_id_hash_
= user
->username_hash();
604 StartDecode(params
->wallpaper
);
609 void WallpaperPrivateSetCustomWallpaperFunction::OnWallpaperDecoded(
610 const gfx::ImageSkia
& image
) {
611 chromeos::WallpaperManager
* wallpaper_manager
=
612 chromeos::WallpaperManager::Get();
613 base::FilePath thumbnail_path
= wallpaper_manager
->GetCustomWallpaperPath(
614 wallpaper::kThumbnailWallpaperSubDir
, user_id_hash_
, params
->file_name
);
616 sequence_token_
= BrowserThread::GetBlockingPool()->GetNamedSequenceToken(
617 wallpaper::kWallpaperSequenceTokenName
);
618 scoped_refptr
<base::SequencedTaskRunner
> task_runner
=
619 BrowserThread::GetBlockingPool()->
620 GetSequencedTaskRunnerWithShutdownBehavior(sequence_token_
,
621 base::SequencedWorkerPool::BLOCK_SHUTDOWN
);
623 wallpaper::WallpaperLayout layout
= wallpaper_api_util::GetLayoutEnum(
624 wallpaper_base::ToString(params
->layout
));
626 bool update_wallpaper
=
627 user_id_
== user_manager::UserManager::Get()->GetActiveUser()->email();
628 wallpaper_manager
->SetCustomWallpaper(user_id_
,
632 user_manager::User::CUSTOMIZED
,
635 unsafe_wallpaper_decoder_
= NULL
;
637 Profile
* profile
= Profile::FromBrowserContext(browser_context());
638 // This API is only available to the component wallpaper picker. We do not
639 // need to show the app's name if it is the component wallpaper picker. So set
640 // the pref to empty string.
641 profile
->GetPrefs()->SetString(prefs::kCurrentWallpaperAppName
,
644 if (params
->generate_thumbnail
) {
645 image
.EnsureRepsForSupportedScales();
646 scoped_ptr
<gfx::ImageSkia
> deep_copy(image
.DeepCopy());
647 // Generates thumbnail before call api function callback. We can then
648 // request thumbnail in the javascript callback.
649 task_runner
->PostTask(FROM_HERE
,
651 &WallpaperPrivateSetCustomWallpaperFunction::GenerateThumbnail
,
652 this, thumbnail_path
, base::Passed(&deep_copy
)));
658 void WallpaperPrivateSetCustomWallpaperFunction::GenerateThumbnail(
659 const base::FilePath
& thumbnail_path
, scoped_ptr
<gfx::ImageSkia
> image
) {
660 DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
662 if (!base::PathExists(thumbnail_path
.DirName()))
663 base::CreateDirectory(thumbnail_path
.DirName());
665 scoped_refptr
<base::RefCountedBytes
> data
;
666 chromeos::WallpaperManager::Get()->ResizeImage(
667 *image
, wallpaper::WALLPAPER_LAYOUT_STRETCH
,
668 wallpaper::kWallpaperThumbnailWidth
, wallpaper::kWallpaperThumbnailHeight
,
670 BrowserThread::PostTask(
671 BrowserThread::UI
, FROM_HERE
,
673 &WallpaperPrivateSetCustomWallpaperFunction::ThumbnailGenerated
,
677 void WallpaperPrivateSetCustomWallpaperFunction::ThumbnailGenerated(
678 base::RefCountedBytes
* data
) {
679 BinaryValue
* result
= BinaryValue::CreateWithCopiedBuffer(
680 reinterpret_cast<const char*>(data
->front()), data
->size());
685 WallpaperPrivateSetCustomWallpaperLayoutFunction::
686 WallpaperPrivateSetCustomWallpaperLayoutFunction() {}
688 WallpaperPrivateSetCustomWallpaperLayoutFunction::
689 ~WallpaperPrivateSetCustomWallpaperLayoutFunction() {}
691 bool WallpaperPrivateSetCustomWallpaperLayoutFunction::RunAsync() {
692 scoped_ptr
<set_custom_wallpaper_layout::Params
> params(
693 set_custom_wallpaper_layout::Params::Create(*args_
));
694 EXTENSION_FUNCTION_VALIDATE(params
);
696 chromeos::WallpaperManager
* wallpaper_manager
=
697 chromeos::WallpaperManager::Get();
698 wallpaper::WallpaperInfo info
;
699 wallpaper_manager
->GetLoggedInUserWallpaperInfo(&info
);
700 if (info
.type
!= user_manager::User::CUSTOMIZED
) {
701 SetError("Only custom wallpaper can change layout.");
705 info
.layout
= wallpaper_api_util::GetLayoutEnum(
706 wallpaper_base::ToString(params
->layout
));
709 user_manager::UserManager::Get()->GetActiveUser()->email();
710 bool is_persistent
= !user_manager::UserManager::Get()
711 ->IsCurrentUserNonCryptohomeDataEphemeral();
712 wallpaper_manager
->SetUserWallpaperInfo(email
, info
, is_persistent
);
713 wallpaper_manager
->UpdateWallpaper(false /* clear_cache */);
716 // Gets email address while at UI thread.
720 WallpaperPrivateMinimizeInactiveWindowsFunction::
721 WallpaperPrivateMinimizeInactiveWindowsFunction() {
724 WallpaperPrivateMinimizeInactiveWindowsFunction::
725 ~WallpaperPrivateMinimizeInactiveWindowsFunction() {
728 bool WallpaperPrivateMinimizeInactiveWindowsFunction::RunAsync() {
729 WindowStateManager::MinimizeInactiveWindows(
730 user_manager::UserManager::Get()->GetActiveUser()->username_hash());
734 WallpaperPrivateRestoreMinimizedWindowsFunction::
735 WallpaperPrivateRestoreMinimizedWindowsFunction() {
738 WallpaperPrivateRestoreMinimizedWindowsFunction::
739 ~WallpaperPrivateRestoreMinimizedWindowsFunction() {
742 bool WallpaperPrivateRestoreMinimizedWindowsFunction::RunAsync() {
743 WindowStateManager::RestoreWindows(
744 user_manager::UserManager::Get()->GetActiveUser()->username_hash());
748 WallpaperPrivateGetThumbnailFunction::WallpaperPrivateGetThumbnailFunction() {
751 WallpaperPrivateGetThumbnailFunction::~WallpaperPrivateGetThumbnailFunction() {
754 bool WallpaperPrivateGetThumbnailFunction::RunAsync() {
755 scoped_ptr
<get_thumbnail::Params
> params(
756 get_thumbnail::Params::Create(*args_
));
757 EXTENSION_FUNCTION_VALIDATE(params
);
759 base::FilePath thumbnail_path
;
761 user_manager::UserManager::Get()->GetActiveUser()->email();
762 if (params
->source
== wallpaper_private::WALLPAPER_SOURCE_ONLINE
) {
763 std::string file_name
= GURL(params
->url_or_file
).ExtractFileName();
764 CHECK(PathService::Get(chrome::DIR_CHROMEOS_WALLPAPER_THUMBNAILS
,
766 thumbnail_path
= thumbnail_path
.Append(file_name
);
768 if (!IsOEMDefaultWallpaper()) {
769 SetError("No OEM wallpaper.");
774 // TODO(bshe): Small resolution wallpaper is used here as wallpaper
775 // thumbnail. We should either resize it or include a wallpaper thumbnail in
776 // addition to large and small wallpaper resolutions.
777 thumbnail_path
= base::CommandLine::ForCurrentProcess()->GetSwitchValuePath(
778 chromeos::switches::kDefaultWallpaperSmall
);
781 sequence_token_
= BrowserThread::GetBlockingPool()->GetNamedSequenceToken(
782 wallpaper::kWallpaperSequenceTokenName
);
783 scoped_refptr
<base::SequencedTaskRunner
> task_runner
=
784 BrowserThread::GetBlockingPool()->
785 GetSequencedTaskRunnerWithShutdownBehavior(sequence_token_
,
786 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN
);
788 task_runner
->PostTask(FROM_HERE
,
789 base::Bind(&WallpaperPrivateGetThumbnailFunction::Get
, this,
794 void WallpaperPrivateGetThumbnailFunction::Failure(
795 const std::string
& file_name
) {
796 SetError(base::StringPrintf("Failed to access wallpaper thumbnails for %s.",
801 void WallpaperPrivateGetThumbnailFunction::FileNotLoaded() {
805 void WallpaperPrivateGetThumbnailFunction::FileLoaded(
806 const std::string
& data
) {
807 BinaryValue
* thumbnail
= BinaryValue::CreateWithCopiedBuffer(data
.c_str(),
809 SetResult(thumbnail
);
813 void WallpaperPrivateGetThumbnailFunction::Get(const base::FilePath
& path
) {
814 DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
817 if (GetData(path
, &data
)) {
819 BrowserThread::PostTask(
820 BrowserThread::UI
, FROM_HERE
,
821 base::Bind(&WallpaperPrivateGetThumbnailFunction::FileNotLoaded
, this));
823 BrowserThread::PostTask(
824 BrowserThread::UI
, FROM_HERE
,
825 base::Bind(&WallpaperPrivateGetThumbnailFunction::FileLoaded
, this,
829 BrowserThread::PostTask(
830 BrowserThread::UI
, FROM_HERE
,
831 base::Bind(&WallpaperPrivateGetThumbnailFunction::Failure
, this,
832 path
.BaseName().value()));
836 WallpaperPrivateSaveThumbnailFunction::WallpaperPrivateSaveThumbnailFunction() {
839 WallpaperPrivateSaveThumbnailFunction::
840 ~WallpaperPrivateSaveThumbnailFunction() {}
842 bool WallpaperPrivateSaveThumbnailFunction::RunAsync() {
843 scoped_ptr
<save_thumbnail::Params
> params(
844 save_thumbnail::Params::Create(*args_
));
845 EXTENSION_FUNCTION_VALIDATE(params
);
847 sequence_token_
= BrowserThread::GetBlockingPool()->GetNamedSequenceToken(
848 wallpaper::kWallpaperSequenceTokenName
);
849 scoped_refptr
<base::SequencedTaskRunner
> task_runner
=
850 BrowserThread::GetBlockingPool()->
851 GetSequencedTaskRunnerWithShutdownBehavior(sequence_token_
,
852 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN
);
854 task_runner
->PostTask(FROM_HERE
,
855 base::Bind(&WallpaperPrivateSaveThumbnailFunction::Save
,
856 this, params
->data
, GURL(params
->url
).ExtractFileName()));
860 void WallpaperPrivateSaveThumbnailFunction::Failure(
861 const std::string
& file_name
) {
862 SetError(base::StringPrintf("Failed to create/write thumbnail of %s.",
867 void WallpaperPrivateSaveThumbnailFunction::Success() {
871 void WallpaperPrivateSaveThumbnailFunction::Save(const std::vector
<char>& data
,
872 const std::string
& file_name
) {
873 DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
875 if (SaveData(chrome::DIR_CHROMEOS_WALLPAPER_THUMBNAILS
, file_name
, data
)) {
876 BrowserThread::PostTask(
877 BrowserThread::UI
, FROM_HERE
,
878 base::Bind(&WallpaperPrivateSaveThumbnailFunction::Success
, this));
880 BrowserThread::PostTask(
881 BrowserThread::UI
, FROM_HERE
,
882 base::Bind(&WallpaperPrivateSaveThumbnailFunction::Failure
,
887 WallpaperPrivateGetOfflineWallpaperListFunction::
888 WallpaperPrivateGetOfflineWallpaperListFunction() {
891 WallpaperPrivateGetOfflineWallpaperListFunction::
892 ~WallpaperPrivateGetOfflineWallpaperListFunction() {
895 bool WallpaperPrivateGetOfflineWallpaperListFunction::RunAsync() {
896 sequence_token_
= BrowserThread::GetBlockingPool()->GetNamedSequenceToken(
897 wallpaper::kWallpaperSequenceTokenName
);
898 scoped_refptr
<base::SequencedTaskRunner
> task_runner
=
899 BrowserThread::GetBlockingPool()->
900 GetSequencedTaskRunnerWithShutdownBehavior(sequence_token_
,
901 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN
);
903 task_runner
->PostTask(FROM_HERE
,
904 base::Bind(&WallpaperPrivateGetOfflineWallpaperListFunction::GetList
,
909 void WallpaperPrivateGetOfflineWallpaperListFunction::GetList() {
910 DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
912 std::vector
<std::string
> file_list
;
913 base::FilePath wallpaper_dir
;
914 CHECK(PathService::Get(chrome::DIR_CHROMEOS_WALLPAPERS
, &wallpaper_dir
));
915 if (base::DirectoryExists(wallpaper_dir
)) {
916 base::FileEnumerator
files(wallpaper_dir
, false,
917 base::FileEnumerator::FILES
);
918 for (base::FilePath current
= files
.Next(); !current
.empty();
919 current
= files
.Next()) {
920 std::string file_name
= current
.BaseName().RemoveExtension().value();
921 // Do not add file name of small resolution wallpaper to the list.
922 if (!base::EndsWith(file_name
, wallpaper::kSmallWallpaperSuffix
,
923 base::CompareCase::SENSITIVE
))
924 file_list
.push_back(current
.BaseName().value());
927 BrowserThread::PostTask(
928 BrowserThread::UI
, FROM_HERE
,
929 base::Bind(&WallpaperPrivateGetOfflineWallpaperListFunction::OnComplete
,
933 void WallpaperPrivateGetOfflineWallpaperListFunction::OnComplete(
934 const std::vector
<std::string
>& file_list
) {
935 base::ListValue
* results
= new base::ListValue();
936 results
->AppendStrings(file_list
);