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