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