Popular sites on the NTP: check that experiment group StartsWith (rather than IS...
[chromium-blink-merge.git] / chrome / browser / chromeos / extensions / wallpaper_private_api.cc
bloba0a3c739296fe27bc53fb790a87ff032afbeb79b
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_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;
63 namespace {
65 #if defined(GOOGLE_CHROME_BUILD)
66 const char kWallpaperManifestBaseURL[] =
67 "https://storage.googleapis.com/chromeos-wallpaper-public/manifest_";
68 #endif
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)) {
84 return false;
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))
100 return false;
102 return !base::PathExists(path) ||
103 base::ReadFileToString(path, data);
106 // Gets the |User| for a given |BrowserContext|. The function will only return
107 // valid objects.
108 const user_manager::User* GetUserFromBrowserContext(
109 content::BrowserContext* context) {
110 Profile* profile = Profile::FromBrowserContext(context);
111 DCHECK(profile);
112 const user_manager::User* user =
113 chromeos::ProfileHelper::Get()->GetUserByProfile(profile);
114 DCHECK(user);
115 return user;
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 {
121 public:
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);
132 private:
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);
161 // static
162 WindowStateManager* g_window_state_manager = NULL;
164 // static
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());
173 // static
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.";
178 return;
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())
208 continue;
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.";
225 return;
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();
243 ++iter) {
244 if (iter->second.find(window) != iter->second.end())
245 return;
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();
255 ++iter) {
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);
270 } // namespace
272 bool WallpaperPrivateGetStringsFunction::RunSync() {
273 base::DictionaryValue* dict = new base::DictionaryValue();
274 SetResult(dict);
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);
303 #undef SET_STRING
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);
317 #endif
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);
328 return true;
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();
336 SetResult(dict);
337 dict->SetBoolean("syncThemes",
338 sync->GetActiveDataTypes().Has(syncer::THEMES));
339 return true;
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,
363 &wallpaper_path));
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)
369 .value();
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,
381 base::Bind(
382 &WallpaperPrivateSetWallpaperIfExistsFunction::
383 ReadFileAndInitiateStartDecode,
384 this, wallpaper_path, fallback_path));
385 return true;
388 void WallpaperPrivateSetWallpaperIfExistsFunction::
389 ReadFileAndInitiateStartDecode(const base::FilePath& file_path,
390 const base::FilePath& fallback_path) {
391 DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
392 sequence_token_));
393 base::FilePath path = file_path;
395 if (!base::PathExists(file_path))
396 path = fallback_path;
398 std::string data;
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())));
405 return;
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,
413 this, error));
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,
433 layout,
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,
443 std::string());
444 SendResponse(true);
447 void WallpaperPrivateSetWallpaperIfExistsFunction::OnFileNotExists(
448 const std::string& error) {
449 SetResult(new base::FundamentalValue(false));
450 OnFailure(error);
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);
469 return true;
472 void WallpaperPrivateSetWallpaperFunction::OnWallpaperDecoded(
473 const gfx::ImageSkia& image) {
474 wallpaper_ = 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(
491 sequence_token_));
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(
499 BrowserThread::UI,
500 FROM_HERE,
501 base::Bind(&WallpaperPrivateSetWallpaperFunction::SetDecodedWallpaper,
502 this,
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))
511 return;
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,
517 NULL);
518 } else {
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,
524 this, error));
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,
544 layout,
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,
552 std::string());
553 wallpaper_manager->SetUserWallpaperInfo(user_id_, info, is_persistent);
554 SendResponse(true);
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()};
575 bool is_persistent =
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,
585 std::string());
586 return true;
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);
606 return true;
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));
625 wallpaper_api_util::RecordCustomWallpaperLayout(layout);
627 bool update_wallpaper =
628 user_id_ == user_manager::UserManager::Get()->GetActiveUser()->email();
629 wallpaper_manager->SetCustomWallpaper(user_id_,
630 user_id_hash_,
631 params->file_name,
632 layout,
633 user_manager::User::CUSTOMIZED,
634 image,
635 update_wallpaper);
636 unsafe_wallpaper_decoder_ = NULL;
638 Profile* profile = Profile::FromBrowserContext(browser_context());
639 // This API is only available to the component wallpaper picker. We do not
640 // need to show the app's name if it is the component wallpaper picker. So set
641 // the pref to empty string.
642 profile->GetPrefs()->SetString(prefs::kCurrentWallpaperAppName,
643 std::string());
645 if (params->generate_thumbnail) {
646 image.EnsureRepsForSupportedScales();
647 scoped_ptr<gfx::ImageSkia> deep_copy(image.DeepCopy());
648 // Generates thumbnail before call api function callback. We can then
649 // request thumbnail in the javascript callback.
650 task_runner->PostTask(FROM_HERE,
651 base::Bind(
652 &WallpaperPrivateSetCustomWallpaperFunction::GenerateThumbnail,
653 this, thumbnail_path, base::Passed(&deep_copy)));
654 } else {
655 SendResponse(true);
659 void WallpaperPrivateSetCustomWallpaperFunction::GenerateThumbnail(
660 const base::FilePath& thumbnail_path, scoped_ptr<gfx::ImageSkia> image) {
661 DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
662 sequence_token_));
663 if (!base::PathExists(thumbnail_path.DirName()))
664 base::CreateDirectory(thumbnail_path.DirName());
666 scoped_refptr<base::RefCountedBytes> data;
667 chromeos::WallpaperManager::Get()->ResizeImage(
668 *image, wallpaper::WALLPAPER_LAYOUT_STRETCH,
669 wallpaper::kWallpaperThumbnailWidth, wallpaper::kWallpaperThumbnailHeight,
670 &data, NULL);
671 BrowserThread::PostTask(
672 BrowserThread::UI, FROM_HERE,
673 base::Bind(
674 &WallpaperPrivateSetCustomWallpaperFunction::ThumbnailGenerated,
675 this, data));
678 void WallpaperPrivateSetCustomWallpaperFunction::ThumbnailGenerated(
679 base::RefCountedBytes* data) {
680 BinaryValue* result = BinaryValue::CreateWithCopiedBuffer(
681 reinterpret_cast<const char*>(data->front()), data->size());
682 SetResult(result);
683 SendResponse(true);
686 WallpaperPrivateSetCustomWallpaperLayoutFunction::
687 WallpaperPrivateSetCustomWallpaperLayoutFunction() {}
689 WallpaperPrivateSetCustomWallpaperLayoutFunction::
690 ~WallpaperPrivateSetCustomWallpaperLayoutFunction() {}
692 bool WallpaperPrivateSetCustomWallpaperLayoutFunction::RunAsync() {
693 scoped_ptr<set_custom_wallpaper_layout::Params> params(
694 set_custom_wallpaper_layout::Params::Create(*args_));
695 EXTENSION_FUNCTION_VALIDATE(params);
697 chromeos::WallpaperManager* wallpaper_manager =
698 chromeos::WallpaperManager::Get();
699 wallpaper::WallpaperInfo info;
700 wallpaper_manager->GetLoggedInUserWallpaperInfo(&info);
701 if (info.type != user_manager::User::CUSTOMIZED) {
702 SetError("Only custom wallpaper can change layout.");
703 SendResponse(false);
704 return false;
706 info.layout = wallpaper_api_util::GetLayoutEnum(
707 wallpaper_base::ToString(params->layout));
708 wallpaper_api_util::RecordCustomWallpaperLayout(info.layout);
710 std::string email =
711 user_manager::UserManager::Get()->GetActiveUser()->email();
712 bool is_persistent = !user_manager::UserManager::Get()
713 ->IsCurrentUserNonCryptohomeDataEphemeral();
714 wallpaper_manager->SetUserWallpaperInfo(email, info, is_persistent);
715 wallpaper_manager->UpdateWallpaper(false /* clear_cache */);
716 SendResponse(true);
718 // Gets email address while at UI thread.
719 return true;
722 WallpaperPrivateMinimizeInactiveWindowsFunction::
723 WallpaperPrivateMinimizeInactiveWindowsFunction() {
726 WallpaperPrivateMinimizeInactiveWindowsFunction::
727 ~WallpaperPrivateMinimizeInactiveWindowsFunction() {
730 bool WallpaperPrivateMinimizeInactiveWindowsFunction::RunAsync() {
731 WindowStateManager::MinimizeInactiveWindows(
732 user_manager::UserManager::Get()->GetActiveUser()->username_hash());
733 return true;
736 WallpaperPrivateRestoreMinimizedWindowsFunction::
737 WallpaperPrivateRestoreMinimizedWindowsFunction() {
740 WallpaperPrivateRestoreMinimizedWindowsFunction::
741 ~WallpaperPrivateRestoreMinimizedWindowsFunction() {
744 bool WallpaperPrivateRestoreMinimizedWindowsFunction::RunAsync() {
745 WindowStateManager::RestoreWindows(
746 user_manager::UserManager::Get()->GetActiveUser()->username_hash());
747 return true;
750 WallpaperPrivateGetThumbnailFunction::WallpaperPrivateGetThumbnailFunction() {
753 WallpaperPrivateGetThumbnailFunction::~WallpaperPrivateGetThumbnailFunction() {
756 bool WallpaperPrivateGetThumbnailFunction::RunAsync() {
757 scoped_ptr<get_thumbnail::Params> params(
758 get_thumbnail::Params::Create(*args_));
759 EXTENSION_FUNCTION_VALIDATE(params);
761 base::FilePath thumbnail_path;
762 std::string email =
763 user_manager::UserManager::Get()->GetActiveUser()->email();
764 if (params->source == wallpaper_private::WALLPAPER_SOURCE_ONLINE) {
765 std::string file_name = GURL(params->url_or_file).ExtractFileName();
766 CHECK(PathService::Get(chrome::DIR_CHROMEOS_WALLPAPER_THUMBNAILS,
767 &thumbnail_path));
768 thumbnail_path = thumbnail_path.Append(file_name);
769 } else {
770 if (!IsOEMDefaultWallpaper()) {
771 SetError("No OEM wallpaper.");
772 SendResponse(false);
773 return false;
776 // TODO(bshe): Small resolution wallpaper is used here as wallpaper
777 // thumbnail. We should either resize it or include a wallpaper thumbnail in
778 // addition to large and small wallpaper resolutions.
779 thumbnail_path = base::CommandLine::ForCurrentProcess()->GetSwitchValuePath(
780 chromeos::switches::kDefaultWallpaperSmall);
783 sequence_token_ = BrowserThread::GetBlockingPool()->GetNamedSequenceToken(
784 wallpaper::kWallpaperSequenceTokenName);
785 scoped_refptr<base::SequencedTaskRunner> task_runner =
786 BrowserThread::GetBlockingPool()->
787 GetSequencedTaskRunnerWithShutdownBehavior(sequence_token_,
788 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN);
790 task_runner->PostTask(FROM_HERE,
791 base::Bind(&WallpaperPrivateGetThumbnailFunction::Get, this,
792 thumbnail_path));
793 return true;
796 void WallpaperPrivateGetThumbnailFunction::Failure(
797 const std::string& file_name) {
798 SetError(base::StringPrintf("Failed to access wallpaper thumbnails for %s.",
799 file_name.c_str()));
800 SendResponse(false);
803 void WallpaperPrivateGetThumbnailFunction::FileNotLoaded() {
804 SendResponse(true);
807 void WallpaperPrivateGetThumbnailFunction::FileLoaded(
808 const std::string& data) {
809 BinaryValue* thumbnail = BinaryValue::CreateWithCopiedBuffer(data.c_str(),
810 data.size());
811 SetResult(thumbnail);
812 SendResponse(true);
815 void WallpaperPrivateGetThumbnailFunction::Get(const base::FilePath& path) {
816 DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
817 sequence_token_));
818 std::string data;
819 if (GetData(path, &data)) {
820 if (data.empty()) {
821 BrowserThread::PostTask(
822 BrowserThread::UI, FROM_HERE,
823 base::Bind(&WallpaperPrivateGetThumbnailFunction::FileNotLoaded, this));
824 } else {
825 BrowserThread::PostTask(
826 BrowserThread::UI, FROM_HERE,
827 base::Bind(&WallpaperPrivateGetThumbnailFunction::FileLoaded, this,
828 data));
830 } else {
831 BrowserThread::PostTask(
832 BrowserThread::UI, FROM_HERE,
833 base::Bind(&WallpaperPrivateGetThumbnailFunction::Failure, this,
834 path.BaseName().value()));
838 WallpaperPrivateSaveThumbnailFunction::WallpaperPrivateSaveThumbnailFunction() {
841 WallpaperPrivateSaveThumbnailFunction::
842 ~WallpaperPrivateSaveThumbnailFunction() {}
844 bool WallpaperPrivateSaveThumbnailFunction::RunAsync() {
845 scoped_ptr<save_thumbnail::Params> params(
846 save_thumbnail::Params::Create(*args_));
847 EXTENSION_FUNCTION_VALIDATE(params);
849 sequence_token_ = BrowserThread::GetBlockingPool()->GetNamedSequenceToken(
850 wallpaper::kWallpaperSequenceTokenName);
851 scoped_refptr<base::SequencedTaskRunner> task_runner =
852 BrowserThread::GetBlockingPool()->
853 GetSequencedTaskRunnerWithShutdownBehavior(sequence_token_,
854 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN);
856 task_runner->PostTask(FROM_HERE,
857 base::Bind(&WallpaperPrivateSaveThumbnailFunction::Save,
858 this, params->data, GURL(params->url).ExtractFileName()));
859 return true;
862 void WallpaperPrivateSaveThumbnailFunction::Failure(
863 const std::string& file_name) {
864 SetError(base::StringPrintf("Failed to create/write thumbnail of %s.",
865 file_name.c_str()));
866 SendResponse(false);
869 void WallpaperPrivateSaveThumbnailFunction::Success() {
870 SendResponse(true);
873 void WallpaperPrivateSaveThumbnailFunction::Save(const std::vector<char>& data,
874 const std::string& file_name) {
875 DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
876 sequence_token_));
877 if (SaveData(chrome::DIR_CHROMEOS_WALLPAPER_THUMBNAILS, file_name, data)) {
878 BrowserThread::PostTask(
879 BrowserThread::UI, FROM_HERE,
880 base::Bind(&WallpaperPrivateSaveThumbnailFunction::Success, this));
881 } else {
882 BrowserThread::PostTask(
883 BrowserThread::UI, FROM_HERE,
884 base::Bind(&WallpaperPrivateSaveThumbnailFunction::Failure,
885 this, file_name));
889 WallpaperPrivateGetOfflineWallpaperListFunction::
890 WallpaperPrivateGetOfflineWallpaperListFunction() {
893 WallpaperPrivateGetOfflineWallpaperListFunction::
894 ~WallpaperPrivateGetOfflineWallpaperListFunction() {
897 bool WallpaperPrivateGetOfflineWallpaperListFunction::RunAsync() {
898 sequence_token_ = BrowserThread::GetBlockingPool()->GetNamedSequenceToken(
899 wallpaper::kWallpaperSequenceTokenName);
900 scoped_refptr<base::SequencedTaskRunner> task_runner =
901 BrowserThread::GetBlockingPool()->
902 GetSequencedTaskRunnerWithShutdownBehavior(sequence_token_,
903 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN);
905 task_runner->PostTask(FROM_HERE,
906 base::Bind(&WallpaperPrivateGetOfflineWallpaperListFunction::GetList,
907 this));
908 return true;
911 void WallpaperPrivateGetOfflineWallpaperListFunction::GetList() {
912 DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
913 sequence_token_));
914 std::vector<std::string> file_list;
915 base::FilePath wallpaper_dir;
916 CHECK(PathService::Get(chrome::DIR_CHROMEOS_WALLPAPERS, &wallpaper_dir));
917 if (base::DirectoryExists(wallpaper_dir)) {
918 base::FileEnumerator files(wallpaper_dir, false,
919 base::FileEnumerator::FILES);
920 for (base::FilePath current = files.Next(); !current.empty();
921 current = files.Next()) {
922 std::string file_name = current.BaseName().RemoveExtension().value();
923 // Do not add file name of small resolution wallpaper to the list.
924 if (!base::EndsWith(file_name, wallpaper::kSmallWallpaperSuffix,
925 base::CompareCase::SENSITIVE))
926 file_list.push_back(current.BaseName().value());
929 BrowserThread::PostTask(
930 BrowserThread::UI, FROM_HERE,
931 base::Bind(&WallpaperPrivateGetOfflineWallpaperListFunction::OnComplete,
932 this, file_list));
935 void WallpaperPrivateGetOfflineWallpaperListFunction::OnComplete(
936 const std::vector<std::string>& file_list) {
937 base::ListValue* results = new base::ListValue();
938 results->AppendStrings(file_list);
939 SetResult(results);
940 SendResponse(true);