Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / extensions / wallpaper_private_api.cc
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.
4
5 #include "chrome/browser/chromeos/extensions/wallpaper_private_api.h"
6
7 #include <vector>
8
9 #include "ash/ash_switches.h"
10 #include "ash/desktop_background/desktop_background_controller.h"
11 #include "ash/shell.h"
12 #include "ash/wm/mru_window_tracker.h"
13 #include "ash/wm/window_state.h"
14 #include "ash/wm/window_util.h"
15 #include "base/command_line.h"
16 #include "base/files/file_enumerator.h"
17 #include "base/files/file_util.h"
18 #include "base/memory/scoped_ptr.h"
19 #include "base/path_service.h"
20 #include "base/prefs/pref_service.h"
21 #include "base/strings/string_number_conversions.h"
22 #include "base/strings/stringprintf.h"
23 #include "base/threading/worker_pool.h"
24 #include "chrome/browser/browser_process.h"
25 #include "chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.h"
26 #include "chrome/browser/profiles/profile.h"
27 #include "chrome/browser/sync/profile_sync_service.h"
28 #include "chrome/browser/sync/profile_sync_service_factory.h"
29 #include "chrome/common/chrome_paths.h"
30 #include "chrome/common/pref_names.h"
31 #include "chrome/grit/generated_resources.h"
32 #include "components/user_manager/user.h"
33 #include "components/user_manager/user_manager.h"
34 #include "content/public/browser/browser_thread.h"
35 #include "extensions/browser/event_router.h"
36 #include "grit/components_strings.h"
37 #include "ui/base/l10n/l10n_util.h"
38 #include "ui/base/webui/web_ui_util.h"
39 #include "ui/strings/grit/app_locale_settings.h"
40 #include "url/gurl.h"
41
42 using base::BinaryValue;
43 using content::BrowserThread;
44 namespace wallpaper_private = extensions::api::wallpaper_private;
45 namespace set_wallpaper_if_exists = wallpaper_private::SetWallpaperIfExists;
46 namespace set_wallpaper = wallpaper_private::SetWallpaper;
47 namespace set_custom_wallpaper = wallpaper_private::SetCustomWallpaper;
48 namespace set_custom_wallpaper_layout =
49     wallpaper_private::SetCustomWallpaperLayout;
50 namespace get_thumbnail = wallpaper_private::GetThumbnail;
51 namespace save_thumbnail = wallpaper_private::SaveThumbnail;
52 namespace get_offline_wallpaper_list =
53     wallpaper_private::GetOfflineWallpaperList;
54
55 namespace {
56
57 #if defined(GOOGLE_CHROME_BUILD)
58 const char kWallpaperManifestBaseURL[] =
59     "https://storage.googleapis.com/chromeos-wallpaper-public/manifest_";
60 #endif
61
62 bool IsOEMDefaultWallpaper() {
63   return CommandLine::ForCurrentProcess()->HasSwitch(
64       ash::switches::kAshDefaultWallpaperIsOem);
65 }
66
67 // Saves |data| as |file_name| to directory with |key|. Return false if the
68 // directory can not be found/created or failed to write file.
69 bool SaveData(int key, const std::string& file_name, const std::string& data) {
70   base::FilePath data_dir;
71   CHECK(PathService::Get(key, &data_dir));
72   if (!base::DirectoryExists(data_dir) &&
73       !base::CreateDirectory(data_dir)) {
74     return false;
75   }
76   base::FilePath file_path = data_dir.Append(file_name);
77
78   return base::PathExists(file_path) ||
79          (base::WriteFile(file_path, data.c_str(), data.size()) != -1);
80 }
81
82 // Gets |file_name| from directory with |key|. Return false if the directory can
83 // not be found or failed to read file to string |data|. Note if the |file_name|
84 // can not be found in the directory, return true with empty |data|. It is
85 // expected that we may try to access file which did not saved yet.
86 bool GetData(const base::FilePath& path, std::string* data) {
87   base::FilePath data_dir = path.DirName();
88   if (!base::DirectoryExists(data_dir) &&
89       !base::CreateDirectory(data_dir))
90     return false;
91
92   return !base::PathExists(path) ||
93          base::ReadFileToString(path, data);
94 }
95
96 // WindowStateManager remembers which windows have been minimized in order to
97 // restore them when the wallpaper viewer is hidden.
98 class WindowStateManager : public aura::WindowObserver {
99  public:
100   typedef std::map<std::string, std::set<aura::Window*> >
101       UserIDHashWindowListMap;
102
103   // Minimizes all windows except the active window.
104   static void MinimizeInactiveWindows(const std::string& user_id_hash);
105
106   // Unminimizes all minimized windows restoring them to their previous state.
107   // This should only be called after calling MinimizeInactiveWindows.
108   static void RestoreWindows(const std::string& user_id_hash);
109
110  private:
111   WindowStateManager();
112
113   virtual ~WindowStateManager();
114
115   // Store all unminimized windows except |active_window| and minimize them.
116   // All the windows are saved in a map and the key value is |user_id_hash|.
117   void BuildWindowListAndMinimizeInactiveForUser(
118       const std::string& user_id_hash, aura::Window* active_window);
119
120   // Unminimize all the stored windows for |user_id_hash|.
121   void RestoreMinimizedWindows(const std::string& user_id_hash);
122
123   // Remove the observer from |window| if |window| is no longer referenced in
124   // user_id_hash_window_list_map_.
125   void RemoveObserverIfUnreferenced(aura::Window* window);
126
127   // aura::WindowObserver overrides.
128   virtual void OnWindowDestroyed(aura::Window* window) override;
129
130   // Map of user id hash and associated list of minimized windows.
131   UserIDHashWindowListMap user_id_hash_window_list_map_;
132
133   DISALLOW_COPY_AND_ASSIGN(WindowStateManager);
134 };
135
136 // static
137 WindowStateManager* g_window_state_manager = NULL;
138
139 // static
140 void WindowStateManager::MinimizeInactiveWindows(
141     const std::string& user_id_hash) {
142   if (!g_window_state_manager)
143     g_window_state_manager = new WindowStateManager();
144   g_window_state_manager->BuildWindowListAndMinimizeInactiveForUser(
145       user_id_hash, ash::wm::GetActiveWindow());
146 }
147
148 // static
149 void WindowStateManager::RestoreWindows(const std::string& user_id_hash) {
150   if (!g_window_state_manager) {
151     DCHECK(false) << "This should only be called after calling "
152                   << "MinimizeInactiveWindows.";
153     return;
154   }
155
156   g_window_state_manager->RestoreMinimizedWindows(user_id_hash);
157   if (g_window_state_manager->user_id_hash_window_list_map_.empty()) {
158     delete g_window_state_manager;
159     g_window_state_manager = NULL;
160   }
161 }
162
163 WindowStateManager::WindowStateManager() {}
164
165 WindowStateManager::~WindowStateManager() {}
166
167 void WindowStateManager::BuildWindowListAndMinimizeInactiveForUser(
168     const std::string& user_id_hash, aura::Window* active_window) {
169   if (user_id_hash_window_list_map_.find(user_id_hash) ==
170       user_id_hash_window_list_map_.end()) {
171     user_id_hash_window_list_map_[user_id_hash] = std::set<aura::Window*>();
172   }
173   std::set<aura::Window*>* results =
174       &user_id_hash_window_list_map_[user_id_hash];
175
176   std::vector<aura::Window*> windows =
177       ash::MruWindowTracker::BuildWindowList(false);
178
179   for (std::vector<aura::Window*>::iterator iter = windows.begin();
180        iter != windows.end(); ++iter) {
181     // Ignore active window and minimized windows.
182     if (*iter == active_window || ash::wm::GetWindowState(*iter)->IsMinimized())
183       continue;
184
185     // TODO(bshe): Add WindowStateObserver too. http://crbug.com/323252
186     if (!(*iter)->HasObserver(this))
187       (*iter)->AddObserver(this);
188
189     results->insert(*iter);
190     ash::wm::GetWindowState(*iter)->Minimize();
191   }
192 }
193
194 void WindowStateManager::RestoreMinimizedWindows(
195     const std::string& user_id_hash) {
196   UserIDHashWindowListMap::iterator it =
197       user_id_hash_window_list_map_.find(user_id_hash);
198   if (it == user_id_hash_window_list_map_.end()) {
199     DCHECK(false) << "This should only be called after calling "
200                   << "MinimizeInactiveWindows.";
201     return;
202   }
203
204   std::set<aura::Window*> removed_windows;
205   removed_windows.swap(it->second);
206   user_id_hash_window_list_map_.erase(it);
207
208   for (std::set<aura::Window*>::iterator iter = removed_windows.begin();
209        iter != removed_windows.end(); ++iter) {
210     ash::wm::GetWindowState(*iter)->Unminimize();
211     RemoveObserverIfUnreferenced(*iter);
212   }
213 }
214
215 void WindowStateManager::RemoveObserverIfUnreferenced(aura::Window* window) {
216   for (UserIDHashWindowListMap::iterator iter =
217            user_id_hash_window_list_map_.begin();
218        iter != user_id_hash_window_list_map_.end();
219        ++iter) {
220     if (iter->second.find(window) != iter->second.end())
221       return;
222   }
223   // Remove observer if |window| is not observed by any users.
224   window->RemoveObserver(this);
225 }
226
227 void WindowStateManager::OnWindowDestroyed(aura::Window* window) {
228   for (UserIDHashWindowListMap::iterator iter =
229            user_id_hash_window_list_map_.begin();
230        iter != user_id_hash_window_list_map_.end();
231        ++iter) {
232     iter->second.erase(window);
233   }
234 }
235
236 }  // namespace
237
238 bool WallpaperPrivateGetStringsFunction::RunSync() {
239   base::DictionaryValue* dict = new base::DictionaryValue();
240   SetResult(dict);
241
242 #define SET_STRING(id, idr) \
243   dict->SetString(id, l10n_util::GetStringUTF16(idr))
244   SET_STRING("webFontFamily", IDS_WEB_FONT_FAMILY);
245   SET_STRING("webFontSize", IDS_WEB_FONT_SIZE);
246   SET_STRING("allCategoryLabel", IDS_WALLPAPER_MANAGER_ALL_CATEGORY_LABEL);
247   SET_STRING("deleteCommandLabel", IDS_WALLPAPER_MANAGER_DELETE_COMMAND_LABEL);
248   SET_STRING("customCategoryLabel",
249              IDS_WALLPAPER_MANAGER_CUSTOM_CATEGORY_LABEL);
250   SET_STRING("selectCustomLabel",
251              IDS_WALLPAPER_MANAGER_SELECT_CUSTOM_LABEL);
252   SET_STRING("positionLabel", IDS_WALLPAPER_MANAGER_POSITION_LABEL);
253   SET_STRING("colorLabel", IDS_WALLPAPER_MANAGER_COLOR_LABEL);
254   SET_STRING("centerCroppedLayout",
255              IDS_OPTIONS_WALLPAPER_CENTER_CROPPED_LAYOUT);
256   SET_STRING("centerLayout", IDS_OPTIONS_WALLPAPER_CENTER_LAYOUT);
257   SET_STRING("stretchLayout", IDS_OPTIONS_WALLPAPER_STRETCH_LAYOUT);
258   SET_STRING("connectionFailed", IDS_WALLPAPER_MANAGER_ACCESS_FAIL);
259   SET_STRING("downloadFailed", IDS_WALLPAPER_MANAGER_DOWNLOAD_FAIL);
260   SET_STRING("downloadCanceled", IDS_WALLPAPER_MANAGER_DOWNLOAD_CANCEL);
261   SET_STRING("customWallpaperWarning",
262              IDS_WALLPAPER_MANAGER_SHOW_CUSTOM_WALLPAPER_ON_START_WARNING);
263   SET_STRING("accessFileFailure", IDS_WALLPAPER_MANAGER_ACCESS_FILE_FAILURE);
264   SET_STRING("invalidWallpaper", IDS_WALLPAPER_MANAGER_INVALID_WALLPAPER);
265   SET_STRING("surpriseMeLabel", IDS_WALLPAPER_MANAGER_SURPRISE_ME_LABEL);
266   SET_STRING("learnMore", IDS_LEARN_MORE);
267   SET_STRING("currentWallpaperSetByMessage",
268              IDS_CURRENT_WALLPAPER_SET_BY_MESSAGE);
269 #undef SET_STRING
270
271   webui::SetFontAndTextDirection(dict);
272
273   chromeos::WallpaperManager* wallpaper_manager =
274       chromeos::WallpaperManager::Get();
275   chromeos::WallpaperInfo info;
276
277   if (wallpaper_manager->GetLoggedInUserWallpaperInfo(&info))
278     dict->SetString("currentWallpaper", info.location);
279
280 #if defined(GOOGLE_CHROME_BUILD)
281   dict->SetString("manifestBaseURL", kWallpaperManifestBaseURL);
282 #endif
283
284   Profile* profile = Profile::FromBrowserContext(browser_context());
285   std::string app_name(
286       profile->GetPrefs()->GetString(prefs::kCurrentWallpaperAppName));
287   if (!app_name.empty())
288     dict->SetString("wallpaperAppName", app_name);
289
290   dict->SetBoolean("isOEMDefaultWallpaper", IsOEMDefaultWallpaper());
291   dict->SetBoolean("isExperimental", true);
292   dict->SetString("canceledWallpaper",
293                   wallpaper_api_util::kCancelWallpaperMessage);
294   return true;
295 }
296
297 bool WallpaperPrivateGetSyncSettingFunction::RunSync() {
298   Profile* profile =  Profile::FromBrowserContext(browser_context());
299   ProfileSyncService* sync =
300       ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile);
301   base::DictionaryValue* dict = new base::DictionaryValue();
302   SetResult(dict);
303   dict->SetBoolean("syncThemes",
304                    sync->GetActiveDataTypes().Has(syncer::THEMES));
305   return true;
306 }
307
308 WallpaperPrivateSetWallpaperIfExistsFunction::
309     WallpaperPrivateSetWallpaperIfExistsFunction() {}
310
311 WallpaperPrivateSetWallpaperIfExistsFunction::
312     ~WallpaperPrivateSetWallpaperIfExistsFunction() {}
313
314 bool WallpaperPrivateSetWallpaperIfExistsFunction::RunAsync() {
315 #if !defined(USE_ATHENA)
316   // TODO(bshe): Support wallpaper manager in Athena, crbug.com/408734.
317   params = set_wallpaper_if_exists::Params::Create(*args_);
318   EXTENSION_FUNCTION_VALIDATE(params);
319
320   user_id_ = user_manager::UserManager::Get()->GetActiveUser()->email();
321
322   base::FilePath wallpaper_path;
323   base::FilePath fallback_path;
324   chromeos::WallpaperManager::WallpaperResolution resolution =
325       chromeos::WallpaperManager::GetAppropriateResolution();
326
327   std::string file_name = GURL(params->url).ExtractFileName();
328   CHECK(PathService::Get(chrome::DIR_CHROMEOS_WALLPAPERS,
329                          &wallpaper_path));
330   fallback_path = wallpaper_path.Append(file_name);
331   if (params->layout != wallpaper_private::WALLPAPER_LAYOUT_STRETCH &&
332       resolution == chromeos::WallpaperManager::WALLPAPER_RESOLUTION_SMALL) {
333     file_name = base::FilePath(file_name).InsertBeforeExtension(
334         chromeos::kSmallWallpaperSuffix).value();
335   }
336   wallpaper_path = wallpaper_path.Append(file_name);
337
338   sequence_token_ = BrowserThread::GetBlockingPool()->
339       GetNamedSequenceToken(chromeos::kWallpaperSequenceTokenName);
340   scoped_refptr<base::SequencedTaskRunner> task_runner =
341       BrowserThread::GetBlockingPool()->
342           GetSequencedTaskRunnerWithShutdownBehavior(sequence_token_,
343               base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN);
344
345   task_runner->PostTask(FROM_HERE,
346       base::Bind(
347           &WallpaperPrivateSetWallpaperIfExistsFunction::
348               ReadFileAndInitiateStartDecode,
349           this, wallpaper_path, fallback_path));
350 #endif
351   return true;
352 }
353
354 void WallpaperPrivateSetWallpaperIfExistsFunction::
355     ReadFileAndInitiateStartDecode(const base::FilePath& file_path,
356                                    const base::FilePath& fallback_path) {
357   DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
358       sequence_token_));
359   std::string data;
360   base::FilePath path = file_path;
361
362   if (!base::PathExists(file_path))
363     path = fallback_path;
364
365   if (base::PathExists(path) &&
366       base::ReadFileToString(path, &data)) {
367     BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
368         base::Bind(&WallpaperPrivateSetWallpaperIfExistsFunction::StartDecode,
369                    this, data));
370     return;
371   }
372   std::string error = base::StringPrintf(
373         "Failed to set wallpaper %s from file system.",
374         path.BaseName().value().c_str());
375   BrowserThread::PostTask(
376       BrowserThread::UI, FROM_HERE,
377       base::Bind(&WallpaperPrivateSetWallpaperIfExistsFunction::OnFileNotExists,
378                  this, error));
379 }
380
381 void WallpaperPrivateSetWallpaperIfExistsFunction::OnWallpaperDecoded(
382     const gfx::ImageSkia& image) {
383   // Set unsafe_wallpaper_decoder_ to null since the decoding already finished.
384   unsafe_wallpaper_decoder_ = NULL;
385
386   chromeos::WallpaperManager* wallpaper_manager =
387       chromeos::WallpaperManager::Get();
388   ash::WallpaperLayout layout = wallpaper_api_util::GetLayoutEnum(
389       wallpaper_private::ToString(params->layout));
390
391   bool update_wallpaper =
392       user_id_ == user_manager::UserManager::Get()->GetActiveUser()->email();
393   wallpaper_manager->SetWallpaperFromImageSkia(
394       user_id_, image, layout, update_wallpaper);
395   bool is_persistent = !user_manager::UserManager::Get()
396                             ->IsCurrentUserNonCryptohomeDataEphemeral();
397   chromeos::WallpaperInfo info = {params->url, layout,
398                                   user_manager::User::ONLINE,
399                                   base::Time::Now().LocalMidnight()};
400   wallpaper_manager->SetUserWallpaperInfo(user_id_, info, is_persistent);
401   SetResult(new base::FundamentalValue(true));
402   Profile* profile = Profile::FromBrowserContext(browser_context());
403   // This API is only available to the component wallpaper picker. We do not
404   // need to show the app's name if it is the component wallpaper picker. So set
405   // the pref to empty string.
406   profile->GetPrefs()->SetString(prefs::kCurrentWallpaperAppName,
407                                  std::string());
408   SendResponse(true);
409 }
410
411 void WallpaperPrivateSetWallpaperIfExistsFunction::OnFileNotExists(
412     const std::string& error) {
413   SetResult(new base::FundamentalValue(false));
414   OnFailure(error);
415 }
416
417 WallpaperPrivateSetWallpaperFunction::WallpaperPrivateSetWallpaperFunction() {
418 }
419
420 WallpaperPrivateSetWallpaperFunction::~WallpaperPrivateSetWallpaperFunction() {
421 }
422
423 bool WallpaperPrivateSetWallpaperFunction::RunAsync() {
424   params = set_wallpaper::Params::Create(*args_);
425   EXTENSION_FUNCTION_VALIDATE(params);
426
427   // Gets email address while at UI thread.
428   user_id_ = user_manager::UserManager::Get()->GetActiveUser()->email();
429
430   StartDecode(params->wallpaper);
431
432   return true;
433 }
434
435 void WallpaperPrivateSetWallpaperFunction::OnWallpaperDecoded(
436     const gfx::ImageSkia& image) {
437   wallpaper_ = image;
438   // Set unsafe_wallpaper_decoder_ to null since the decoding already finished.
439   unsafe_wallpaper_decoder_ = NULL;
440
441   sequence_token_ = BrowserThread::GetBlockingPool()->
442       GetNamedSequenceToken(chromeos::kWallpaperSequenceTokenName);
443   scoped_refptr<base::SequencedTaskRunner> task_runner =
444       BrowserThread::GetBlockingPool()->
445           GetSequencedTaskRunnerWithShutdownBehavior(sequence_token_,
446               base::SequencedWorkerPool::BLOCK_SHUTDOWN);
447
448   task_runner->PostTask(FROM_HERE,
449       base::Bind(&WallpaperPrivateSetWallpaperFunction::SaveToFile, this));
450 }
451
452 void WallpaperPrivateSetWallpaperFunction::SaveToFile() {
453   DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
454       sequence_token_));
455   std::string file_name = GURL(params->url).ExtractFileName();
456   if (SaveData(chrome::DIR_CHROMEOS_WALLPAPERS, file_name, params->wallpaper)) {
457     wallpaper_.EnsureRepsForSupportedScales();
458     scoped_ptr<gfx::ImageSkia> deep_copy(wallpaper_.DeepCopy());
459     // ImageSkia is not RefCountedThreadSafe. Use a deep copied ImageSkia if
460     // post to another thread.
461     BrowserThread::PostTask(
462         BrowserThread::UI,
463         FROM_HERE,
464         base::Bind(&WallpaperPrivateSetWallpaperFunction::SetDecodedWallpaper,
465                    this,
466                    base::Passed(deep_copy.Pass())));
467
468     base::FilePath wallpaper_dir;
469     CHECK(PathService::Get(chrome::DIR_CHROMEOS_WALLPAPERS, &wallpaper_dir));
470     base::FilePath file_path = wallpaper_dir.Append(
471         file_name).InsertBeforeExtension(chromeos::kSmallWallpaperSuffix);
472     if (base::PathExists(file_path))
473       return;
474     // Generates and saves small resolution wallpaper. Uses CENTER_CROPPED to
475     // maintain the aspect ratio after resize.
476     chromeos::WallpaperManager::Get()->ResizeAndSaveWallpaper(
477         wallpaper_,
478         file_path,
479         ash::WALLPAPER_LAYOUT_CENTER_CROPPED,
480         chromeos::kSmallWallpaperMaxWidth,
481         chromeos::kSmallWallpaperMaxHeight,
482         NULL);
483   } else {
484     std::string error = base::StringPrintf(
485         "Failed to create/write wallpaper to %s.", file_name.c_str());
486     BrowserThread::PostTask(
487         BrowserThread::UI, FROM_HERE,
488         base::Bind(&WallpaperPrivateSetWallpaperFunction::OnFailure,
489                    this, error));
490   }
491 }
492
493 void WallpaperPrivateSetWallpaperFunction::SetDecodedWallpaper(
494     scoped_ptr<gfx::ImageSkia> image) {
495   chromeos::WallpaperManager* wallpaper_manager =
496       chromeos::WallpaperManager::Get();
497
498   ash::WallpaperLayout layout = wallpaper_api_util::GetLayoutEnum(
499       wallpaper_private::ToString(params->layout));
500
501   bool update_wallpaper =
502       user_id_ == user_manager::UserManager::Get()->GetActiveUser()->email();
503   wallpaper_manager->SetWallpaperFromImageSkia(
504       user_id_, *image.get(), layout, update_wallpaper);
505
506   bool is_persistent = !user_manager::UserManager::Get()
507                             ->IsCurrentUserNonCryptohomeDataEphemeral();
508   chromeos::WallpaperInfo info = {params->url, layout,
509                                   user_manager::User::ONLINE,
510                                   base::Time::Now().LocalMidnight()};
511   Profile* profile = Profile::FromBrowserContext(browser_context());
512   // This API is only available to the component wallpaper picker. We do not
513   // need to show the app's name if it is the component wallpaper picker. So set
514   // the pref to empty string.
515   profile->GetPrefs()->SetString(prefs::kCurrentWallpaperAppName,
516                                  std::string());
517   wallpaper_manager->SetUserWallpaperInfo(user_id_, info, is_persistent);
518   SendResponse(true);
519 }
520
521 WallpaperPrivateResetWallpaperFunction::
522     WallpaperPrivateResetWallpaperFunction() {}
523
524 WallpaperPrivateResetWallpaperFunction::
525     ~WallpaperPrivateResetWallpaperFunction() {}
526
527 bool WallpaperPrivateResetWallpaperFunction::RunAsync() {
528   chromeos::WallpaperManager* wallpaper_manager =
529       chromeos::WallpaperManager::Get();
530   user_manager::UserManager* user_manager = user_manager::UserManager::Get();
531
532   std::string user_id = user_manager->GetActiveUser()->email();
533   wallpaper_manager->RemoveUserWallpaperInfo(user_id);
534
535   chromeos::WallpaperInfo info = {std::string(),
536                                   ash::WALLPAPER_LAYOUT_CENTER,
537                                   user_manager::User::DEFAULT,
538                                   base::Time::Now().LocalMidnight()};
539   bool is_persistent =
540       !user_manager->IsCurrentUserNonCryptohomeDataEphemeral();
541   wallpaper_manager->SetUserWallpaperInfo(user_id, info, is_persistent);
542
543   wallpaper_manager->SetDefaultWallpaperNow(user_id);
544   Profile* profile = Profile::FromBrowserContext(browser_context());
545   // This API is only available to the component wallpaper picker. We do not
546   // need to show the app's name if it is the component wallpaper picker. So set
547   // the pref to empty string.
548   profile->GetPrefs()->SetString(prefs::kCurrentWallpaperAppName,
549                                  std::string());
550   return true;
551 }
552
553 WallpaperPrivateSetCustomWallpaperFunction::
554     WallpaperPrivateSetCustomWallpaperFunction() {}
555
556 WallpaperPrivateSetCustomWallpaperFunction::
557     ~WallpaperPrivateSetCustomWallpaperFunction() {}
558
559 bool WallpaperPrivateSetCustomWallpaperFunction::RunAsync() {
560   params = set_custom_wallpaper::Params::Create(*args_);
561   EXTENSION_FUNCTION_VALIDATE(params);
562
563   // Gets email address and username hash while at UI thread.
564   user_id_ = user_manager::UserManager::Get()->GetActiveUser()->email();
565   user_id_hash_ =
566       user_manager::UserManager::Get()->GetActiveUser()->username_hash();
567
568   StartDecode(params->wallpaper);
569
570   return true;
571 }
572
573 void WallpaperPrivateSetCustomWallpaperFunction::OnWallpaperDecoded(
574     const gfx::ImageSkia& image) {
575   chromeos::WallpaperManager* wallpaper_manager =
576       chromeos::WallpaperManager::Get();
577   base::FilePath thumbnail_path = wallpaper_manager->GetCustomWallpaperPath(
578       chromeos::kThumbnailWallpaperSubDir, user_id_hash_, params->file_name);
579
580   sequence_token_ = BrowserThread::GetBlockingPool()->
581       GetNamedSequenceToken(chromeos::kWallpaperSequenceTokenName);
582   scoped_refptr<base::SequencedTaskRunner> task_runner =
583       BrowserThread::GetBlockingPool()->
584           GetSequencedTaskRunnerWithShutdownBehavior(sequence_token_,
585               base::SequencedWorkerPool::BLOCK_SHUTDOWN);
586
587   ash::WallpaperLayout layout = wallpaper_api_util::GetLayoutEnum(
588       wallpaper_private::ToString(params->layout));
589
590   bool update_wallpaper =
591       user_id_ == user_manager::UserManager::Get()->GetActiveUser()->email();
592   wallpaper_manager->SetCustomWallpaper(user_id_,
593                                         user_id_hash_,
594                                         params->file_name,
595                                         layout,
596                                         user_manager::User::CUSTOMIZED,
597                                         image,
598                                         update_wallpaper);
599   unsafe_wallpaper_decoder_ = NULL;
600
601   Profile* profile = Profile::FromBrowserContext(browser_context());
602   // This API is only available to the component wallpaper picker. We do not
603   // need to show the app's name if it is the component wallpaper picker. So set
604   // the pref to empty string.
605   profile->GetPrefs()->SetString(prefs::kCurrentWallpaperAppName,
606                                  std::string());
607
608   if (params->generate_thumbnail) {
609     image.EnsureRepsForSupportedScales();
610     scoped_ptr<gfx::ImageSkia> deep_copy(image.DeepCopy());
611     // Generates thumbnail before call api function callback. We can then
612     // request thumbnail in the javascript callback.
613     task_runner->PostTask(FROM_HERE,
614         base::Bind(
615             &WallpaperPrivateSetCustomWallpaperFunction::GenerateThumbnail,
616             this, thumbnail_path, base::Passed(&deep_copy)));
617   } else {
618     SendResponse(true);
619   }
620 }
621
622 void WallpaperPrivateSetCustomWallpaperFunction::GenerateThumbnail(
623     const base::FilePath& thumbnail_path, scoped_ptr<gfx::ImageSkia> image) {
624   DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
625       sequence_token_));
626   if (!base::PathExists(thumbnail_path.DirName()))
627     base::CreateDirectory(thumbnail_path.DirName());
628
629   scoped_refptr<base::RefCountedBytes> data;
630   chromeos::WallpaperManager::Get()->ResizeImage(
631       *image,
632       ash::WALLPAPER_LAYOUT_STRETCH,
633       chromeos::kWallpaperThumbnailWidth,
634       chromeos::kWallpaperThumbnailHeight,
635       &data,
636       NULL);
637   BrowserThread::PostTask(
638         BrowserThread::UI, FROM_HERE,
639         base::Bind(
640             &WallpaperPrivateSetCustomWallpaperFunction::ThumbnailGenerated,
641             this, data));
642 }
643
644 void WallpaperPrivateSetCustomWallpaperFunction::ThumbnailGenerated(
645     base::RefCountedBytes* data) {
646   BinaryValue* result = BinaryValue::CreateWithCopiedBuffer(
647       reinterpret_cast<const char*>(data->front()), data->size());
648   SetResult(result);
649   SendResponse(true);
650 }
651
652 WallpaperPrivateSetCustomWallpaperLayoutFunction::
653     WallpaperPrivateSetCustomWallpaperLayoutFunction() {}
654
655 WallpaperPrivateSetCustomWallpaperLayoutFunction::
656     ~WallpaperPrivateSetCustomWallpaperLayoutFunction() {}
657
658 bool WallpaperPrivateSetCustomWallpaperLayoutFunction::RunAsync() {
659   scoped_ptr<set_custom_wallpaper_layout::Params> params(
660       set_custom_wallpaper_layout::Params::Create(*args_));
661   EXTENSION_FUNCTION_VALIDATE(params);
662
663   chromeos::WallpaperManager* wallpaper_manager =
664       chromeos::WallpaperManager::Get();
665   chromeos::WallpaperInfo info;
666   wallpaper_manager->GetLoggedInUserWallpaperInfo(&info);
667   if (info.type != user_manager::User::CUSTOMIZED) {
668     SetError("Only custom wallpaper can change layout.");
669     SendResponse(false);
670     return false;
671   }
672   info.layout = wallpaper_api_util::GetLayoutEnum(
673       wallpaper_private::ToString(params->layout));
674
675   std::string email =
676       user_manager::UserManager::Get()->GetActiveUser()->email();
677   bool is_persistent = !user_manager::UserManager::Get()
678                             ->IsCurrentUserNonCryptohomeDataEphemeral();
679   wallpaper_manager->SetUserWallpaperInfo(email, info, is_persistent);
680   wallpaper_manager->UpdateWallpaper(false /* clear_cache */);
681   SendResponse(true);
682
683   // Gets email address while at UI thread.
684   return true;
685 }
686
687 WallpaperPrivateMinimizeInactiveWindowsFunction::
688     WallpaperPrivateMinimizeInactiveWindowsFunction() {
689 }
690
691 WallpaperPrivateMinimizeInactiveWindowsFunction::
692     ~WallpaperPrivateMinimizeInactiveWindowsFunction() {
693 }
694
695 bool WallpaperPrivateMinimizeInactiveWindowsFunction::RunAsync() {
696   WindowStateManager::MinimizeInactiveWindows(
697       user_manager::UserManager::Get()->GetActiveUser()->username_hash());
698   return true;
699 }
700
701 WallpaperPrivateRestoreMinimizedWindowsFunction::
702     WallpaperPrivateRestoreMinimizedWindowsFunction() {
703 }
704
705 WallpaperPrivateRestoreMinimizedWindowsFunction::
706     ~WallpaperPrivateRestoreMinimizedWindowsFunction() {
707 }
708
709 bool WallpaperPrivateRestoreMinimizedWindowsFunction::RunAsync() {
710   WindowStateManager::RestoreWindows(
711       user_manager::UserManager::Get()->GetActiveUser()->username_hash());
712   return true;
713 }
714
715 WallpaperPrivateGetThumbnailFunction::WallpaperPrivateGetThumbnailFunction() {
716 }
717
718 WallpaperPrivateGetThumbnailFunction::~WallpaperPrivateGetThumbnailFunction() {
719 }
720
721 bool WallpaperPrivateGetThumbnailFunction::RunAsync() {
722   scoped_ptr<get_thumbnail::Params> params(
723       get_thumbnail::Params::Create(*args_));
724   EXTENSION_FUNCTION_VALIDATE(params);
725
726   base::FilePath thumbnail_path;
727   std::string email =
728       user_manager::UserManager::Get()->GetActiveUser()->email();
729   if (params->source == get_thumbnail::Params::SOURCE_ONLINE) {
730     std::string file_name = GURL(params->url_or_file).ExtractFileName();
731     CHECK(PathService::Get(chrome::DIR_CHROMEOS_WALLPAPER_THUMBNAILS,
732                            &thumbnail_path));
733     thumbnail_path = thumbnail_path.Append(file_name);
734   } else {
735     if (!IsOEMDefaultWallpaper()) {
736       SetError("No OEM wallpaper.");
737       SendResponse(false);
738       return false;
739     }
740
741     // TODO(bshe): Small resolution wallpaper is used here as wallpaper
742     // thumbnail. We should either resize it or include a wallpaper thumbnail in
743     // addition to large and small wallpaper resolutions.
744     thumbnail_path = CommandLine::ForCurrentProcess()->GetSwitchValuePath(
745         ash::switches::kAshDefaultWallpaperSmall);
746   }
747
748   sequence_token_ = BrowserThread::GetBlockingPool()->
749       GetNamedSequenceToken(chromeos::kWallpaperSequenceTokenName);
750   scoped_refptr<base::SequencedTaskRunner> task_runner =
751       BrowserThread::GetBlockingPool()->
752           GetSequencedTaskRunnerWithShutdownBehavior(sequence_token_,
753               base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN);
754
755   task_runner->PostTask(FROM_HERE,
756       base::Bind(&WallpaperPrivateGetThumbnailFunction::Get, this,
757                  thumbnail_path));
758   return true;
759 }
760
761 void WallpaperPrivateGetThumbnailFunction::Failure(
762     const std::string& file_name) {
763   SetError(base::StringPrintf("Failed to access wallpaper thumbnails for %s.",
764                               file_name.c_str()));
765   SendResponse(false);
766 }
767
768 void WallpaperPrivateGetThumbnailFunction::FileNotLoaded() {
769   SendResponse(true);
770 }
771
772 void WallpaperPrivateGetThumbnailFunction::FileLoaded(
773     const std::string& data) {
774   BinaryValue* thumbnail = BinaryValue::CreateWithCopiedBuffer(data.c_str(),
775                                                                data.size());
776   SetResult(thumbnail);
777   SendResponse(true);
778 }
779
780 void WallpaperPrivateGetThumbnailFunction::Get(const base::FilePath& path) {
781   DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
782       sequence_token_));
783   std::string data;
784   if (GetData(path, &data)) {
785     if (data.empty()) {
786       BrowserThread::PostTask(
787         BrowserThread::UI, FROM_HERE,
788         base::Bind(&WallpaperPrivateGetThumbnailFunction::FileNotLoaded, this));
789     } else {
790       BrowserThread::PostTask(
791         BrowserThread::UI, FROM_HERE,
792         base::Bind(&WallpaperPrivateGetThumbnailFunction::FileLoaded, this,
793                    data));
794     }
795   } else {
796     BrowserThread::PostTask(
797         BrowserThread::UI, FROM_HERE,
798         base::Bind(&WallpaperPrivateGetThumbnailFunction::Failure, this,
799                    path.BaseName().value()));
800   }
801 }
802
803 WallpaperPrivateSaveThumbnailFunction::WallpaperPrivateSaveThumbnailFunction() {
804 }
805
806 WallpaperPrivateSaveThumbnailFunction::
807     ~WallpaperPrivateSaveThumbnailFunction() {}
808
809 bool WallpaperPrivateSaveThumbnailFunction::RunAsync() {
810   scoped_ptr<save_thumbnail::Params> params(
811       save_thumbnail::Params::Create(*args_));
812   EXTENSION_FUNCTION_VALIDATE(params);
813
814   sequence_token_ = BrowserThread::GetBlockingPool()->
815       GetNamedSequenceToken(chromeos::kWallpaperSequenceTokenName);
816   scoped_refptr<base::SequencedTaskRunner> task_runner =
817       BrowserThread::GetBlockingPool()->
818           GetSequencedTaskRunnerWithShutdownBehavior(sequence_token_,
819               base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN);
820
821   task_runner->PostTask(FROM_HERE,
822       base::Bind(&WallpaperPrivateSaveThumbnailFunction::Save,
823                  this, params->data, GURL(params->url).ExtractFileName()));
824   return true;
825 }
826
827 void WallpaperPrivateSaveThumbnailFunction::Failure(
828     const std::string& file_name) {
829   SetError(base::StringPrintf("Failed to create/write thumbnail of %s.",
830                               file_name.c_str()));
831   SendResponse(false);
832 }
833
834 void WallpaperPrivateSaveThumbnailFunction::Success() {
835   SendResponse(true);
836 }
837
838 void WallpaperPrivateSaveThumbnailFunction::Save(const std::string& data,
839                                           const std::string& file_name) {
840   DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
841       sequence_token_));
842   if (SaveData(chrome::DIR_CHROMEOS_WALLPAPER_THUMBNAILS, file_name, data)) {
843     BrowserThread::PostTask(
844       BrowserThread::UI, FROM_HERE,
845       base::Bind(&WallpaperPrivateSaveThumbnailFunction::Success, this));
846   } else {
847     BrowserThread::PostTask(
848           BrowserThread::UI, FROM_HERE,
849           base::Bind(&WallpaperPrivateSaveThumbnailFunction::Failure,
850                      this, file_name));
851   }
852 }
853
854 WallpaperPrivateGetOfflineWallpaperListFunction::
855     WallpaperPrivateGetOfflineWallpaperListFunction() {
856 }
857
858 WallpaperPrivateGetOfflineWallpaperListFunction::
859     ~WallpaperPrivateGetOfflineWallpaperListFunction() {
860 }
861
862 bool WallpaperPrivateGetOfflineWallpaperListFunction::RunAsync() {
863   sequence_token_ = BrowserThread::GetBlockingPool()->
864       GetNamedSequenceToken(chromeos::kWallpaperSequenceTokenName);
865   scoped_refptr<base::SequencedTaskRunner> task_runner =
866       BrowserThread::GetBlockingPool()->
867           GetSequencedTaskRunnerWithShutdownBehavior(sequence_token_,
868               base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN);
869
870   task_runner->PostTask(FROM_HERE,
871       base::Bind(&WallpaperPrivateGetOfflineWallpaperListFunction::GetList,
872                  this));
873   return true;
874 }
875
876 void WallpaperPrivateGetOfflineWallpaperListFunction::GetList() {
877   DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
878       sequence_token_));
879   std::vector<std::string> file_list;
880   base::FilePath wallpaper_dir;
881   CHECK(PathService::Get(chrome::DIR_CHROMEOS_WALLPAPERS, &wallpaper_dir));
882   if (base::DirectoryExists(wallpaper_dir)) {
883     base::FileEnumerator files(wallpaper_dir, false,
884                                base::FileEnumerator::FILES);
885     for (base::FilePath current = files.Next(); !current.empty();
886          current = files.Next()) {
887       std::string file_name = current.BaseName().RemoveExtension().value();
888       // Do not add file name of small resolution wallpaper to the list.
889       if (!EndsWith(file_name, chromeos::kSmallWallpaperSuffix, true))
890         file_list.push_back(current.BaseName().value());
891     }
892   }
893   BrowserThread::PostTask(
894       BrowserThread::UI, FROM_HERE,
895       base::Bind(&WallpaperPrivateGetOfflineWallpaperListFunction::OnComplete,
896                  this, file_list));
897 }
898
899 void WallpaperPrivateGetOfflineWallpaperListFunction::OnComplete(
900     const std::vector<std::string>& file_list) {
901   base::ListValue* results = new base::ListValue();
902   results->AppendStrings(file_list);
903   SetResult(results);
904   SendResponse(true);
905 }