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