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