ozone: evdev: Sync caps lock LED state to evdev
[chromium-blink-merge.git] / chrome / browser / chromeos / extensions / wallpaper_private_api.cc
blobd4983fe60acf9ca1dc046618d3bc2e7c6c96df5e
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/chromeos/extensions/wallpaper_private_api.h"
7 #include <map>
8 #include <set>
9 #include <string>
10 #include <vector>
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"
46 #include "url/gurl.h"
48 using base::BinaryValue;
49 using content::BrowserThread;
51 namespace wallpaper_private = extensions::api::wallpaper_private;
52 namespace set_wallpaper_if_exists = wallpaper_private::SetWallpaperIfExists;
53 namespace set_wallpaper = wallpaper_private::SetWallpaper;
54 namespace set_custom_wallpaper = wallpaper_private::SetCustomWallpaper;
55 namespace set_custom_wallpaper_layout =
56 wallpaper_private::SetCustomWallpaperLayout;
57 namespace get_thumbnail = wallpaper_private::GetThumbnail;
58 namespace save_thumbnail = wallpaper_private::SaveThumbnail;
59 namespace get_offline_wallpaper_list =
60 wallpaper_private::GetOfflineWallpaperList;
62 namespace {
64 #if defined(GOOGLE_CHROME_BUILD)
65 const char kWallpaperManifestBaseURL[] =
66 "https://storage.googleapis.com/chromeos-wallpaper-public/manifest_";
67 #endif
69 bool IsOEMDefaultWallpaper() {
70 return base::CommandLine::ForCurrentProcess()->HasSwitch(
71 chromeos::switches::kDefaultWallpaperIsOem);
74 // Saves |data| as |file_name| to directory with |key|. Return false if the
75 // directory can not be found/created or failed to write file.
76 bool SaveData(int key,
77 const std::string& file_name,
78 const std::vector<char>& data) {
79 base::FilePath data_dir;
80 CHECK(PathService::Get(key, &data_dir));
81 if (!base::DirectoryExists(data_dir) &&
82 !base::CreateDirectory(data_dir)) {
83 return false;
85 base::FilePath file_path = data_dir.Append(file_name);
87 return base::PathExists(file_path) ||
88 base::WriteFile(file_path, vector_as_array(&data), data.size()) != -1;
91 // Gets |file_name| from directory with |key|. Return false if the directory can
92 // not be found or failed to read file to string |data|. Note if the |file_name|
93 // can not be found in the directory, return true with empty |data|. It is
94 // expected that we may try to access file which did not saved yet.
95 bool GetData(const base::FilePath& path, std::string* data) {
96 base::FilePath data_dir = path.DirName();
97 if (!base::DirectoryExists(data_dir) &&
98 !base::CreateDirectory(data_dir))
99 return false;
101 return !base::PathExists(path) ||
102 base::ReadFileToString(path, data);
105 // Gets the |User| for a given |BrowserContext|. The function will only return
106 // valid objects.
107 const user_manager::User* GetUserFromBrowserContext(
108 content::BrowserContext* context) {
109 Profile* profile = Profile::FromBrowserContext(context);
110 DCHECK(profile);
111 const user_manager::User* user =
112 chromeos::ProfileHelper::Get()->GetUserByProfile(profile);
113 DCHECK(user);
114 return user;
117 // WindowStateManager remembers which windows have been minimized in order to
118 // restore them when the wallpaper viewer is hidden.
119 class WindowStateManager : public aura::WindowObserver {
120 public:
121 typedef std::map<std::string, std::set<aura::Window*> >
122 UserIDHashWindowListMap;
124 // Minimizes all windows except the active window.
125 static void MinimizeInactiveWindows(const std::string& user_id_hash);
127 // Unminimizes all minimized windows restoring them to their previous state.
128 // This should only be called after calling MinimizeInactiveWindows.
129 static void RestoreWindows(const std::string& user_id_hash);
131 private:
132 WindowStateManager();
134 ~WindowStateManager() override;
136 // Store all unminimized windows except |active_window| and minimize them.
137 // All the windows are saved in a map and the key value is |user_id_hash|.
138 void BuildWindowListAndMinimizeInactiveForUser(
139 const std::string& user_id_hash, aura::Window* active_window);
141 // Unminimize all the stored windows for |user_id_hash|.
142 void RestoreMinimizedWindows(const std::string& user_id_hash);
144 // Remove the observer from |window| if |window| is no longer referenced in
145 // user_id_hash_window_list_map_.
146 void RemoveObserverIfUnreferenced(aura::Window* window);
148 // aura::WindowObserver overrides.
149 void OnWindowDestroyed(aura::Window* window) override;
151 // Map of user id hash and associated list of minimized windows.
152 UserIDHashWindowListMap user_id_hash_window_list_map_;
154 DISALLOW_COPY_AND_ASSIGN(WindowStateManager);
157 // static
158 WindowStateManager* g_window_state_manager = NULL;
160 // static
161 void WindowStateManager::MinimizeInactiveWindows(
162 const std::string& user_id_hash) {
163 if (!g_window_state_manager)
164 g_window_state_manager = new WindowStateManager();
165 g_window_state_manager->BuildWindowListAndMinimizeInactiveForUser(
166 user_id_hash, ash::wm::GetActiveWindow());
169 // static
170 void WindowStateManager::RestoreWindows(const std::string& user_id_hash) {
171 if (!g_window_state_manager) {
172 DCHECK(false) << "This should only be called after calling "
173 << "MinimizeInactiveWindows.";
174 return;
177 g_window_state_manager->RestoreMinimizedWindows(user_id_hash);
178 if (g_window_state_manager->user_id_hash_window_list_map_.empty()) {
179 delete g_window_state_manager;
180 g_window_state_manager = NULL;
184 WindowStateManager::WindowStateManager() {}
186 WindowStateManager::~WindowStateManager() {}
188 void WindowStateManager::BuildWindowListAndMinimizeInactiveForUser(
189 const std::string& user_id_hash, aura::Window* active_window) {
190 if (user_id_hash_window_list_map_.find(user_id_hash) ==
191 user_id_hash_window_list_map_.end()) {
192 user_id_hash_window_list_map_[user_id_hash] = std::set<aura::Window*>();
194 std::set<aura::Window*>* results =
195 &user_id_hash_window_list_map_[user_id_hash];
197 std::vector<aura::Window*> windows = ash::Shell::GetInstance()->
198 mru_window_tracker()->BuildWindowListIgnoreModal();
200 for (std::vector<aura::Window*>::iterator iter = windows.begin();
201 iter != windows.end(); ++iter) {
202 // Ignore active window and minimized windows.
203 if (*iter == active_window || ash::wm::GetWindowState(*iter)->IsMinimized())
204 continue;
206 // TODO(bshe): Add WindowStateObserver too. http://crbug.com/323252
207 if (!(*iter)->HasObserver(this))
208 (*iter)->AddObserver(this);
210 results->insert(*iter);
211 ash::wm::GetWindowState(*iter)->Minimize();
215 void WindowStateManager::RestoreMinimizedWindows(
216 const std::string& user_id_hash) {
217 UserIDHashWindowListMap::iterator it =
218 user_id_hash_window_list_map_.find(user_id_hash);
219 if (it == user_id_hash_window_list_map_.end()) {
220 DCHECK(false) << "This should only be called after calling "
221 << "MinimizeInactiveWindows.";
222 return;
225 std::set<aura::Window*> removed_windows;
226 removed_windows.swap(it->second);
227 user_id_hash_window_list_map_.erase(it);
229 for (std::set<aura::Window*>::iterator iter = removed_windows.begin();
230 iter != removed_windows.end(); ++iter) {
231 ash::wm::GetWindowState(*iter)->Unminimize();
232 RemoveObserverIfUnreferenced(*iter);
236 void WindowStateManager::RemoveObserverIfUnreferenced(aura::Window* window) {
237 for (UserIDHashWindowListMap::iterator iter =
238 user_id_hash_window_list_map_.begin();
239 iter != user_id_hash_window_list_map_.end();
240 ++iter) {
241 if (iter->second.find(window) != iter->second.end())
242 return;
244 // Remove observer if |window| is not observed by any users.
245 window->RemoveObserver(this);
248 void WindowStateManager::OnWindowDestroyed(aura::Window* window) {
249 for (UserIDHashWindowListMap::iterator iter =
250 user_id_hash_window_list_map_.begin();
251 iter != user_id_hash_window_list_map_.end();
252 ++iter) {
253 iter->second.erase(window);
257 } // namespace
259 bool WallpaperPrivateGetStringsFunction::RunSync() {
260 base::DictionaryValue* dict = new base::DictionaryValue();
261 SetResult(dict);
263 #define SET_STRING(id, idr) \
264 dict->SetString(id, l10n_util::GetStringUTF16(idr))
265 SET_STRING("webFontFamily", IDS_WEB_FONT_FAMILY);
266 SET_STRING("webFontSize", IDS_WEB_FONT_SIZE);
267 SET_STRING("allCategoryLabel", IDS_WALLPAPER_MANAGER_ALL_CATEGORY_LABEL);
268 SET_STRING("deleteCommandLabel", IDS_WALLPAPER_MANAGER_DELETE_COMMAND_LABEL);
269 SET_STRING("customCategoryLabel",
270 IDS_WALLPAPER_MANAGER_CUSTOM_CATEGORY_LABEL);
271 SET_STRING("selectCustomLabel",
272 IDS_WALLPAPER_MANAGER_SELECT_CUSTOM_LABEL);
273 SET_STRING("positionLabel", IDS_WALLPAPER_MANAGER_POSITION_LABEL);
274 SET_STRING("colorLabel", IDS_WALLPAPER_MANAGER_COLOR_LABEL);
275 SET_STRING("centerCroppedLayout",
276 IDS_OPTIONS_WALLPAPER_CENTER_CROPPED_LAYOUT);
277 SET_STRING("centerLayout", IDS_OPTIONS_WALLPAPER_CENTER_LAYOUT);
278 SET_STRING("stretchLayout", IDS_OPTIONS_WALLPAPER_STRETCH_LAYOUT);
279 SET_STRING("connectionFailed", IDS_WALLPAPER_MANAGER_ACCESS_FAIL);
280 SET_STRING("downloadFailed", IDS_WALLPAPER_MANAGER_DOWNLOAD_FAIL);
281 SET_STRING("downloadCanceled", IDS_WALLPAPER_MANAGER_DOWNLOAD_CANCEL);
282 SET_STRING("customWallpaperWarning",
283 IDS_WALLPAPER_MANAGER_SHOW_CUSTOM_WALLPAPER_ON_START_WARNING);
284 SET_STRING("accessFileFailure", IDS_WALLPAPER_MANAGER_ACCESS_FILE_FAILURE);
285 SET_STRING("invalidWallpaper", IDS_WALLPAPER_MANAGER_INVALID_WALLPAPER);
286 SET_STRING("surpriseMeLabel", IDS_WALLPAPER_MANAGER_SURPRISE_ME_LABEL);
287 SET_STRING("learnMore", IDS_LEARN_MORE);
288 SET_STRING("currentWallpaperSetByMessage",
289 IDS_CURRENT_WALLPAPER_SET_BY_MESSAGE);
290 #undef SET_STRING
292 const std::string& app_locale = g_browser_process->GetApplicationLocale();
293 webui::SetLoadTimeDataDefaults(app_locale, dict);
295 chromeos::WallpaperManager* wallpaper_manager =
296 chromeos::WallpaperManager::Get();
297 wallpaper::WallpaperInfo info;
299 if (wallpaper_manager->GetLoggedInUserWallpaperInfo(&info))
300 dict->SetString("currentWallpaper", info.location);
302 #if defined(GOOGLE_CHROME_BUILD)
303 dict->SetString("manifestBaseURL", kWallpaperManifestBaseURL);
304 #endif
306 Profile* profile = Profile::FromBrowserContext(browser_context());
307 std::string app_name(
308 profile->GetPrefs()->GetString(prefs::kCurrentWallpaperAppName));
309 if (!app_name.empty())
310 dict->SetString("wallpaperAppName", app_name);
312 dict->SetBoolean("isOEMDefaultWallpaper", IsOEMDefaultWallpaper());
313 dict->SetString("canceledWallpaper",
314 wallpaper_api_util::kCancelWallpaperMessage);
315 return true;
318 bool WallpaperPrivateGetSyncSettingFunction::RunSync() {
319 Profile* profile = Profile::FromBrowserContext(browser_context());
320 ProfileSyncService* sync =
321 ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile);
322 base::DictionaryValue* dict = new base::DictionaryValue();
323 SetResult(dict);
324 dict->SetBoolean("syncThemes",
325 sync->GetActiveDataTypes().Has(syncer::THEMES));
326 return true;
329 WallpaperPrivateSetWallpaperIfExistsFunction::
330 WallpaperPrivateSetWallpaperIfExistsFunction() {}
332 WallpaperPrivateSetWallpaperIfExistsFunction::
333 ~WallpaperPrivateSetWallpaperIfExistsFunction() {}
335 bool WallpaperPrivateSetWallpaperIfExistsFunction::RunAsync() {
336 params = set_wallpaper_if_exists::Params::Create(*args_);
337 EXTENSION_FUNCTION_VALIDATE(params);
339 // Gets email address from caller, ensuring multiprofile compatibility.
340 const user_manager::User* user = GetUserFromBrowserContext(browser_context());
341 user_id_ = user->email();
343 base::FilePath wallpaper_path;
344 base::FilePath fallback_path;
345 chromeos::WallpaperManager::WallpaperResolution resolution =
346 chromeos::WallpaperManager::Get()->GetAppropriateResolution();
348 std::string file_name = GURL(params->url).ExtractFileName();
349 CHECK(PathService::Get(chrome::DIR_CHROMEOS_WALLPAPERS,
350 &wallpaper_path));
351 fallback_path = wallpaper_path.Append(file_name);
352 if (params->layout != wallpaper_private::WALLPAPER_LAYOUT_STRETCH &&
353 resolution == chromeos::WallpaperManager::WALLPAPER_RESOLUTION_SMALL) {
354 file_name = base::FilePath(file_name)
355 .InsertBeforeExtension(wallpaper::kSmallWallpaperSuffix)
356 .value();
358 wallpaper_path = wallpaper_path.Append(file_name);
360 sequence_token_ = BrowserThread::GetBlockingPool()->GetNamedSequenceToken(
361 wallpaper::kWallpaperSequenceTokenName);
362 scoped_refptr<base::SequencedTaskRunner> task_runner =
363 BrowserThread::GetBlockingPool()->
364 GetSequencedTaskRunnerWithShutdownBehavior(sequence_token_,
365 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN);
367 task_runner->PostTask(FROM_HERE,
368 base::Bind(
369 &WallpaperPrivateSetWallpaperIfExistsFunction::
370 ReadFileAndInitiateStartDecode,
371 this, wallpaper_path, fallback_path));
372 return true;
375 void WallpaperPrivateSetWallpaperIfExistsFunction::
376 ReadFileAndInitiateStartDecode(const base::FilePath& file_path,
377 const base::FilePath& fallback_path) {
378 DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
379 sequence_token_));
380 base::FilePath path = file_path;
382 if (!base::PathExists(file_path))
383 path = fallback_path;
385 std::string data;
386 if (base::PathExists(path) &&
387 base::ReadFileToString(path, &data)) {
388 BrowserThread::PostTask(
389 BrowserThread::UI, FROM_HERE,
390 base::Bind(&WallpaperPrivateSetWallpaperIfExistsFunction::StartDecode,
391 this, std::vector<char>(data.begin(), data.end())));
392 return;
394 std::string error = base::StringPrintf(
395 "Failed to set wallpaper %s from file system.",
396 path.BaseName().value().c_str());
397 BrowserThread::PostTask(
398 BrowserThread::UI, FROM_HERE,
399 base::Bind(&WallpaperPrivateSetWallpaperIfExistsFunction::OnFileNotExists,
400 this, error));
403 void WallpaperPrivateSetWallpaperIfExistsFunction::OnWallpaperDecoded(
404 const gfx::ImageSkia& image) {
405 // Set unsafe_wallpaper_decoder_ to null since the decoding already finished.
406 unsafe_wallpaper_decoder_ = NULL;
408 chromeos::WallpaperManager* wallpaper_manager =
409 chromeos::WallpaperManager::Get();
410 wallpaper::WallpaperLayout layout = wallpaper_api_util::GetLayoutEnum(
411 wallpaper_private::ToString(params->layout));
413 bool update_wallpaper =
414 user_id_ == user_manager::UserManager::Get()->GetActiveUser()->email();
415 wallpaper_manager->SetWallpaperFromImageSkia(
416 user_id_, image, layout, update_wallpaper);
417 bool is_persistent = !user_manager::UserManager::Get()
418 ->IsCurrentUserNonCryptohomeDataEphemeral();
419 wallpaper::WallpaperInfo info = {params->url,
420 layout,
421 user_manager::User::ONLINE,
422 base::Time::Now().LocalMidnight()};
423 wallpaper_manager->SetUserWallpaperInfo(user_id_, info, is_persistent);
424 SetResult(new base::FundamentalValue(true));
425 Profile* profile = Profile::FromBrowserContext(browser_context());
426 // This API is only available to the component wallpaper picker. We do not
427 // need to show the app's name if it is the component wallpaper picker. So set
428 // the pref to empty string.
429 profile->GetPrefs()->SetString(prefs::kCurrentWallpaperAppName,
430 std::string());
431 SendResponse(true);
434 void WallpaperPrivateSetWallpaperIfExistsFunction::OnFileNotExists(
435 const std::string& error) {
436 SetResult(new base::FundamentalValue(false));
437 OnFailure(error);
440 WallpaperPrivateSetWallpaperFunction::WallpaperPrivateSetWallpaperFunction() {
443 WallpaperPrivateSetWallpaperFunction::~WallpaperPrivateSetWallpaperFunction() {
446 bool WallpaperPrivateSetWallpaperFunction::RunAsync() {
447 params = set_wallpaper::Params::Create(*args_);
448 EXTENSION_FUNCTION_VALIDATE(params);
450 // Gets email address from caller, ensuring multiprofile compatibility.
451 const user_manager::User* user = GetUserFromBrowserContext(browser_context());
452 user_id_ = user->email();
454 StartDecode(params->wallpaper);
456 return true;
459 void WallpaperPrivateSetWallpaperFunction::OnWallpaperDecoded(
460 const gfx::ImageSkia& image) {
461 wallpaper_ = image;
462 // Set unsafe_wallpaper_decoder_ to null since the decoding already finished.
463 unsafe_wallpaper_decoder_ = NULL;
465 sequence_token_ = BrowserThread::GetBlockingPool()->GetNamedSequenceToken(
466 wallpaper::kWallpaperSequenceTokenName);
467 scoped_refptr<base::SequencedTaskRunner> task_runner =
468 BrowserThread::GetBlockingPool()->
469 GetSequencedTaskRunnerWithShutdownBehavior(sequence_token_,
470 base::SequencedWorkerPool::BLOCK_SHUTDOWN);
472 task_runner->PostTask(FROM_HERE,
473 base::Bind(&WallpaperPrivateSetWallpaperFunction::SaveToFile, this));
476 void WallpaperPrivateSetWallpaperFunction::SaveToFile() {
477 DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
478 sequence_token_));
479 std::string file_name = GURL(params->url).ExtractFileName();
480 if (SaveData(chrome::DIR_CHROMEOS_WALLPAPERS, file_name, params->wallpaper)) {
481 wallpaper_.EnsureRepsForSupportedScales();
482 scoped_ptr<gfx::ImageSkia> deep_copy(wallpaper_.DeepCopy());
483 // ImageSkia is not RefCountedThreadSafe. Use a deep copied ImageSkia if
484 // post to another thread.
485 BrowserThread::PostTask(
486 BrowserThread::UI,
487 FROM_HERE,
488 base::Bind(&WallpaperPrivateSetWallpaperFunction::SetDecodedWallpaper,
489 this,
490 base::Passed(deep_copy.Pass())));
492 base::FilePath wallpaper_dir;
493 CHECK(PathService::Get(chrome::DIR_CHROMEOS_WALLPAPERS, &wallpaper_dir));
494 base::FilePath file_path =
495 wallpaper_dir.Append(file_name)
496 .InsertBeforeExtension(wallpaper::kSmallWallpaperSuffix);
497 if (base::PathExists(file_path))
498 return;
499 // Generates and saves small resolution wallpaper. Uses CENTER_CROPPED to
500 // maintain the aspect ratio after resize.
501 chromeos::WallpaperManager::Get()->ResizeAndSaveWallpaper(
502 wallpaper_, file_path, wallpaper::WALLPAPER_LAYOUT_CENTER_CROPPED,
503 wallpaper::kSmallWallpaperMaxWidth, wallpaper::kSmallWallpaperMaxHeight,
504 NULL);
505 } else {
506 std::string error = base::StringPrintf(
507 "Failed to create/write wallpaper to %s.", file_name.c_str());
508 BrowserThread::PostTask(
509 BrowserThread::UI, FROM_HERE,
510 base::Bind(&WallpaperPrivateSetWallpaperFunction::OnFailure,
511 this, error));
515 void WallpaperPrivateSetWallpaperFunction::SetDecodedWallpaper(
516 scoped_ptr<gfx::ImageSkia> image) {
517 chromeos::WallpaperManager* wallpaper_manager =
518 chromeos::WallpaperManager::Get();
520 wallpaper::WallpaperLayout layout = wallpaper_api_util::GetLayoutEnum(
521 wallpaper_private::ToString(params->layout));
523 bool update_wallpaper =
524 user_id_ == user_manager::UserManager::Get()->GetActiveUser()->email();
525 wallpaper_manager->SetWallpaperFromImageSkia(
526 user_id_, *image.get(), layout, update_wallpaper);
528 bool is_persistent = !user_manager::UserManager::Get()
529 ->IsCurrentUserNonCryptohomeDataEphemeral();
530 wallpaper::WallpaperInfo info = {params->url,
531 layout,
532 user_manager::User::ONLINE,
533 base::Time::Now().LocalMidnight()};
534 Profile* profile = Profile::FromBrowserContext(browser_context());
535 // This API is only available to the component wallpaper picker. We do not
536 // need to show the app's name if it is the component wallpaper picker. So set
537 // the pref to empty string.
538 profile->GetPrefs()->SetString(prefs::kCurrentWallpaperAppName,
539 std::string());
540 wallpaper_manager->SetUserWallpaperInfo(user_id_, info, is_persistent);
541 SendResponse(true);
544 WallpaperPrivateResetWallpaperFunction::
545 WallpaperPrivateResetWallpaperFunction() {}
547 WallpaperPrivateResetWallpaperFunction::
548 ~WallpaperPrivateResetWallpaperFunction() {}
550 bool WallpaperPrivateResetWallpaperFunction::RunAsync() {
551 chromeos::WallpaperManager* wallpaper_manager =
552 chromeos::WallpaperManager::Get();
553 user_manager::UserManager* user_manager = user_manager::UserManager::Get();
555 std::string user_id = user_manager->GetActiveUser()->email();
556 wallpaper_manager->RemoveUserWallpaperInfo(user_id);
558 wallpaper::WallpaperInfo info = {std::string(),
559 wallpaper::WALLPAPER_LAYOUT_CENTER,
560 user_manager::User::DEFAULT,
561 base::Time::Now().LocalMidnight()};
562 bool is_persistent =
563 !user_manager->IsCurrentUserNonCryptohomeDataEphemeral();
564 wallpaper_manager->SetUserWallpaperInfo(user_id, info, is_persistent);
566 wallpaper_manager->SetDefaultWallpaperNow(user_id);
567 Profile* profile = Profile::FromBrowserContext(browser_context());
568 // This API is only available to the component wallpaper picker. We do not
569 // need to show the app's name if it is the component wallpaper picker. So set
570 // the pref to empty string.
571 profile->GetPrefs()->SetString(prefs::kCurrentWallpaperAppName,
572 std::string());
573 return true;
576 WallpaperPrivateSetCustomWallpaperFunction::
577 WallpaperPrivateSetCustomWallpaperFunction() {}
579 WallpaperPrivateSetCustomWallpaperFunction::
580 ~WallpaperPrivateSetCustomWallpaperFunction() {}
582 bool WallpaperPrivateSetCustomWallpaperFunction::RunAsync() {
583 params = set_custom_wallpaper::Params::Create(*args_);
584 EXTENSION_FUNCTION_VALIDATE(params);
586 // Gets email address from caller, ensuring multiprofile compatibility.
587 const user_manager::User* user = GetUserFromBrowserContext(browser_context());
588 user_id_ = user->email();
589 user_id_hash_ = user->username_hash();
591 StartDecode(params->wallpaper);
593 return true;
596 void WallpaperPrivateSetCustomWallpaperFunction::OnWallpaperDecoded(
597 const gfx::ImageSkia& image) {
598 chromeos::WallpaperManager* wallpaper_manager =
599 chromeos::WallpaperManager::Get();
600 base::FilePath thumbnail_path = wallpaper_manager->GetCustomWallpaperPath(
601 wallpaper::kThumbnailWallpaperSubDir, user_id_hash_, params->file_name);
603 sequence_token_ = BrowserThread::GetBlockingPool()->GetNamedSequenceToken(
604 wallpaper::kWallpaperSequenceTokenName);
605 scoped_refptr<base::SequencedTaskRunner> task_runner =
606 BrowserThread::GetBlockingPool()->
607 GetSequencedTaskRunnerWithShutdownBehavior(sequence_token_,
608 base::SequencedWorkerPool::BLOCK_SHUTDOWN);
610 wallpaper::WallpaperLayout layout = wallpaper_api_util::GetLayoutEnum(
611 wallpaper_private::ToString(params->layout));
613 bool update_wallpaper =
614 user_id_ == user_manager::UserManager::Get()->GetActiveUser()->email();
615 wallpaper_manager->SetCustomWallpaper(user_id_,
616 user_id_hash_,
617 params->file_name,
618 layout,
619 user_manager::User::CUSTOMIZED,
620 image,
621 update_wallpaper);
622 unsafe_wallpaper_decoder_ = NULL;
624 Profile* profile = Profile::FromBrowserContext(browser_context());
625 // This API is only available to the component wallpaper picker. We do not
626 // need to show the app's name if it is the component wallpaper picker. So set
627 // the pref to empty string.
628 profile->GetPrefs()->SetString(prefs::kCurrentWallpaperAppName,
629 std::string());
631 if (params->generate_thumbnail) {
632 image.EnsureRepsForSupportedScales();
633 scoped_ptr<gfx::ImageSkia> deep_copy(image.DeepCopy());
634 // Generates thumbnail before call api function callback. We can then
635 // request thumbnail in the javascript callback.
636 task_runner->PostTask(FROM_HERE,
637 base::Bind(
638 &WallpaperPrivateSetCustomWallpaperFunction::GenerateThumbnail,
639 this, thumbnail_path, base::Passed(&deep_copy)));
640 } else {
641 SendResponse(true);
645 void WallpaperPrivateSetCustomWallpaperFunction::GenerateThumbnail(
646 const base::FilePath& thumbnail_path, scoped_ptr<gfx::ImageSkia> image) {
647 DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
648 sequence_token_));
649 if (!base::PathExists(thumbnail_path.DirName()))
650 base::CreateDirectory(thumbnail_path.DirName());
652 scoped_refptr<base::RefCountedBytes> data;
653 chromeos::WallpaperManager::Get()->ResizeImage(
654 *image, wallpaper::WALLPAPER_LAYOUT_STRETCH,
655 wallpaper::kWallpaperThumbnailWidth, wallpaper::kWallpaperThumbnailHeight,
656 &data, NULL);
657 BrowserThread::PostTask(
658 BrowserThread::UI, FROM_HERE,
659 base::Bind(
660 &WallpaperPrivateSetCustomWallpaperFunction::ThumbnailGenerated,
661 this, data));
664 void WallpaperPrivateSetCustomWallpaperFunction::ThumbnailGenerated(
665 base::RefCountedBytes* data) {
666 BinaryValue* result = BinaryValue::CreateWithCopiedBuffer(
667 reinterpret_cast<const char*>(data->front()), data->size());
668 SetResult(result);
669 SendResponse(true);
672 WallpaperPrivateSetCustomWallpaperLayoutFunction::
673 WallpaperPrivateSetCustomWallpaperLayoutFunction() {}
675 WallpaperPrivateSetCustomWallpaperLayoutFunction::
676 ~WallpaperPrivateSetCustomWallpaperLayoutFunction() {}
678 bool WallpaperPrivateSetCustomWallpaperLayoutFunction::RunAsync() {
679 scoped_ptr<set_custom_wallpaper_layout::Params> params(
680 set_custom_wallpaper_layout::Params::Create(*args_));
681 EXTENSION_FUNCTION_VALIDATE(params);
683 chromeos::WallpaperManager* wallpaper_manager =
684 chromeos::WallpaperManager::Get();
685 wallpaper::WallpaperInfo info;
686 wallpaper_manager->GetLoggedInUserWallpaperInfo(&info);
687 if (info.type != user_manager::User::CUSTOMIZED) {
688 SetError("Only custom wallpaper can change layout.");
689 SendResponse(false);
690 return false;
692 info.layout = wallpaper_api_util::GetLayoutEnum(
693 wallpaper_private::ToString(params->layout));
695 std::string email =
696 user_manager::UserManager::Get()->GetActiveUser()->email();
697 bool is_persistent = !user_manager::UserManager::Get()
698 ->IsCurrentUserNonCryptohomeDataEphemeral();
699 wallpaper_manager->SetUserWallpaperInfo(email, info, is_persistent);
700 wallpaper_manager->UpdateWallpaper(false /* clear_cache */);
701 SendResponse(true);
703 // Gets email address while at UI thread.
704 return true;
707 WallpaperPrivateMinimizeInactiveWindowsFunction::
708 WallpaperPrivateMinimizeInactiveWindowsFunction() {
711 WallpaperPrivateMinimizeInactiveWindowsFunction::
712 ~WallpaperPrivateMinimizeInactiveWindowsFunction() {
715 bool WallpaperPrivateMinimizeInactiveWindowsFunction::RunAsync() {
716 WindowStateManager::MinimizeInactiveWindows(
717 user_manager::UserManager::Get()->GetActiveUser()->username_hash());
718 return true;
721 WallpaperPrivateRestoreMinimizedWindowsFunction::
722 WallpaperPrivateRestoreMinimizedWindowsFunction() {
725 WallpaperPrivateRestoreMinimizedWindowsFunction::
726 ~WallpaperPrivateRestoreMinimizedWindowsFunction() {
729 bool WallpaperPrivateRestoreMinimizedWindowsFunction::RunAsync() {
730 WindowStateManager::RestoreWindows(
731 user_manager::UserManager::Get()->GetActiveUser()->username_hash());
732 return true;
735 WallpaperPrivateGetThumbnailFunction::WallpaperPrivateGetThumbnailFunction() {
738 WallpaperPrivateGetThumbnailFunction::~WallpaperPrivateGetThumbnailFunction() {
741 bool WallpaperPrivateGetThumbnailFunction::RunAsync() {
742 scoped_ptr<get_thumbnail::Params> params(
743 get_thumbnail::Params::Create(*args_));
744 EXTENSION_FUNCTION_VALIDATE(params);
746 base::FilePath thumbnail_path;
747 std::string email =
748 user_manager::UserManager::Get()->GetActiveUser()->email();
749 if (params->source == get_thumbnail::Params::SOURCE_ONLINE) {
750 std::string file_name = GURL(params->url_or_file).ExtractFileName();
751 CHECK(PathService::Get(chrome::DIR_CHROMEOS_WALLPAPER_THUMBNAILS,
752 &thumbnail_path));
753 thumbnail_path = thumbnail_path.Append(file_name);
754 } else {
755 if (!IsOEMDefaultWallpaper()) {
756 SetError("No OEM wallpaper.");
757 SendResponse(false);
758 return false;
761 // TODO(bshe): Small resolution wallpaper is used here as wallpaper
762 // thumbnail. We should either resize it or include a wallpaper thumbnail in
763 // addition to large and small wallpaper resolutions.
764 thumbnail_path = base::CommandLine::ForCurrentProcess()->GetSwitchValuePath(
765 chromeos::switches::kDefaultWallpaperSmall);
768 sequence_token_ = BrowserThread::GetBlockingPool()->GetNamedSequenceToken(
769 wallpaper::kWallpaperSequenceTokenName);
770 scoped_refptr<base::SequencedTaskRunner> task_runner =
771 BrowserThread::GetBlockingPool()->
772 GetSequencedTaskRunnerWithShutdownBehavior(sequence_token_,
773 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN);
775 task_runner->PostTask(FROM_HERE,
776 base::Bind(&WallpaperPrivateGetThumbnailFunction::Get, this,
777 thumbnail_path));
778 return true;
781 void WallpaperPrivateGetThumbnailFunction::Failure(
782 const std::string& file_name) {
783 SetError(base::StringPrintf("Failed to access wallpaper thumbnails for %s.",
784 file_name.c_str()));
785 SendResponse(false);
788 void WallpaperPrivateGetThumbnailFunction::FileNotLoaded() {
789 SendResponse(true);
792 void WallpaperPrivateGetThumbnailFunction::FileLoaded(
793 const std::string& data) {
794 BinaryValue* thumbnail = BinaryValue::CreateWithCopiedBuffer(data.c_str(),
795 data.size());
796 SetResult(thumbnail);
797 SendResponse(true);
800 void WallpaperPrivateGetThumbnailFunction::Get(const base::FilePath& path) {
801 DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
802 sequence_token_));
803 std::string data;
804 if (GetData(path, &data)) {
805 if (data.empty()) {
806 BrowserThread::PostTask(
807 BrowserThread::UI, FROM_HERE,
808 base::Bind(&WallpaperPrivateGetThumbnailFunction::FileNotLoaded, this));
809 } else {
810 BrowserThread::PostTask(
811 BrowserThread::UI, FROM_HERE,
812 base::Bind(&WallpaperPrivateGetThumbnailFunction::FileLoaded, this,
813 data));
815 } else {
816 BrowserThread::PostTask(
817 BrowserThread::UI, FROM_HERE,
818 base::Bind(&WallpaperPrivateGetThumbnailFunction::Failure, this,
819 path.BaseName().value()));
823 WallpaperPrivateSaveThumbnailFunction::WallpaperPrivateSaveThumbnailFunction() {
826 WallpaperPrivateSaveThumbnailFunction::
827 ~WallpaperPrivateSaveThumbnailFunction() {}
829 bool WallpaperPrivateSaveThumbnailFunction::RunAsync() {
830 scoped_ptr<save_thumbnail::Params> params(
831 save_thumbnail::Params::Create(*args_));
832 EXTENSION_FUNCTION_VALIDATE(params);
834 sequence_token_ = BrowserThread::GetBlockingPool()->GetNamedSequenceToken(
835 wallpaper::kWallpaperSequenceTokenName);
836 scoped_refptr<base::SequencedTaskRunner> task_runner =
837 BrowserThread::GetBlockingPool()->
838 GetSequencedTaskRunnerWithShutdownBehavior(sequence_token_,
839 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN);
841 task_runner->PostTask(FROM_HERE,
842 base::Bind(&WallpaperPrivateSaveThumbnailFunction::Save,
843 this, params->data, GURL(params->url).ExtractFileName()));
844 return true;
847 void WallpaperPrivateSaveThumbnailFunction::Failure(
848 const std::string& file_name) {
849 SetError(base::StringPrintf("Failed to create/write thumbnail of %s.",
850 file_name.c_str()));
851 SendResponse(false);
854 void WallpaperPrivateSaveThumbnailFunction::Success() {
855 SendResponse(true);
858 void WallpaperPrivateSaveThumbnailFunction::Save(const std::vector<char>& data,
859 const std::string& file_name) {
860 DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
861 sequence_token_));
862 if (SaveData(chrome::DIR_CHROMEOS_WALLPAPER_THUMBNAILS, file_name, data)) {
863 BrowserThread::PostTask(
864 BrowserThread::UI, FROM_HERE,
865 base::Bind(&WallpaperPrivateSaveThumbnailFunction::Success, this));
866 } else {
867 BrowserThread::PostTask(
868 BrowserThread::UI, FROM_HERE,
869 base::Bind(&WallpaperPrivateSaveThumbnailFunction::Failure,
870 this, file_name));
874 WallpaperPrivateGetOfflineWallpaperListFunction::
875 WallpaperPrivateGetOfflineWallpaperListFunction() {
878 WallpaperPrivateGetOfflineWallpaperListFunction::
879 ~WallpaperPrivateGetOfflineWallpaperListFunction() {
882 bool WallpaperPrivateGetOfflineWallpaperListFunction::RunAsync() {
883 sequence_token_ = BrowserThread::GetBlockingPool()->GetNamedSequenceToken(
884 wallpaper::kWallpaperSequenceTokenName);
885 scoped_refptr<base::SequencedTaskRunner> task_runner =
886 BrowserThread::GetBlockingPool()->
887 GetSequencedTaskRunnerWithShutdownBehavior(sequence_token_,
888 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN);
890 task_runner->PostTask(FROM_HERE,
891 base::Bind(&WallpaperPrivateGetOfflineWallpaperListFunction::GetList,
892 this));
893 return true;
896 void WallpaperPrivateGetOfflineWallpaperListFunction::GetList() {
897 DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
898 sequence_token_));
899 std::vector<std::string> file_list;
900 base::FilePath wallpaper_dir;
901 CHECK(PathService::Get(chrome::DIR_CHROMEOS_WALLPAPERS, &wallpaper_dir));
902 if (base::DirectoryExists(wallpaper_dir)) {
903 base::FileEnumerator files(wallpaper_dir, false,
904 base::FileEnumerator::FILES);
905 for (base::FilePath current = files.Next(); !current.empty();
906 current = files.Next()) {
907 std::string file_name = current.BaseName().RemoveExtension().value();
908 // Do not add file name of small resolution wallpaper to the list.
909 if (!EndsWith(file_name, wallpaper::kSmallWallpaperSuffix, true))
910 file_list.push_back(current.BaseName().value());
913 BrowserThread::PostTask(
914 BrowserThread::UI, FROM_HERE,
915 base::Bind(&WallpaperPrivateGetOfflineWallpaperListFunction::OnComplete,
916 this, file_list));
919 void WallpaperPrivateGetOfflineWallpaperListFunction::OnComplete(
920 const std::vector<std::string>& file_list) {
921 base::ListValue* results = new base::ListValue();
922 results->AppendStrings(file_list);
923 SetResult(results);
924 SendResponse(true);