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