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