diff options
author | alemate@chromium.org <alemate@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-23 14:17:57 +0000 |
---|---|---|
committer | alemate@chromium.org <alemate@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-23 14:17:57 +0000 |
commit | 94365820697621536ee32326ac4e77f720337a26 (patch) | |
tree | 9e80f1be42c03f0fc20729e378a993d275237cb0 | |
parent | 9b9ed013945b7f2cdefc595a4c0384ada51f8d56 (diff) | |
download | chromium_src-94365820697621536ee32326ac4e77f720337a26.zip chromium_src-94365820697621536ee32326ac4e77f720337a26.tar.gz chromium_src-94365820697621536ee32326ac4e77f720337a26.tar.bz2 |
Apply default wallpaper from customization manifest.
This CL also fixes bug with default wallpaper cache.
BUG=348136,363134
TEST=manual
Review URL: https://codereview.chromium.org/236013002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@265636 0039d316-1c4b-4281-b951-d872f2087c98
21 files changed, 1132 insertions, 75 deletions
diff --git a/ash/desktop_background/desktop_background_controller.cc b/ash/desktop_background/desktop_background_controller.cc index 8b54cb5..e756997 100644 --- a/ash/desktop_background/desktop_background_controller.cc +++ b/ash/desktop_background/desktop_background_controller.cc @@ -43,6 +43,8 @@ const int kWallpaperReloadDelayMs = 2000; } // namespace +const int DesktopBackgroundController::kInvalidResourceID = -1; + DesktopBackgroundController::DesktopBackgroundController() : locked_(false), desktop_background_mode_(BACKGROUND_NONE), @@ -83,7 +85,8 @@ bool DesktopBackgroundController::SetWallpaperImage(const gfx::ImageSkia& image, VLOG(1) << "SetWallpaper: image_id=" << WallpaperResizer::GetImageId(image) << " layout=" << layout; - if (WallpaperIsAlreadyLoaded(&image, kInvalidResourceID, layout)) { + if (WallpaperIsAlreadyLoaded( + &image, kInvalidResourceID, true /* compare_layouts */, layout)) { VLOG(1) << "Wallpaper is already loaded"; return false; } @@ -104,7 +107,8 @@ bool DesktopBackgroundController::SetWallpaperResource(int resource_id, VLOG(1) << "SetWallpaper: resource_id=" << resource_id << " layout=" << layout; - if (WallpaperIsAlreadyLoaded(NULL, resource_id, layout)) { + if (WallpaperIsAlreadyLoaded( + NULL, resource_id, true /* compare_layouts */, layout)) { VLOG(1) << "Wallpaper is already loaded"; return false; } @@ -196,11 +200,13 @@ gfx::Size DesktopBackgroundController::GetMaxDisplaySizeInNative() { bool DesktopBackgroundController::WallpaperIsAlreadyLoaded( const gfx::ImageSkia* image, int resource_id, + bool compare_layouts, WallpaperLayout layout) const { if (!current_wallpaper_.get()) return false; - if (layout != current_wallpaper_->layout()) + // Compare layouts only if necessary. + if (compare_layouts && layout != current_wallpaper_->layout()) return false; if (image) { diff --git a/ash/desktop_background/desktop_background_controller.h b/ash/desktop_background/desktop_background_controller.h index b1099c6..8d9f698 100644 --- a/ash/desktop_background/desktop_background_controller.h +++ b/ash/desktop_background/desktop_background_controller.h @@ -37,7 +37,7 @@ enum WallpaperLayout { // desktop's size. WALLPAPER_LAYOUT_STRETCH, // Tile the wallpaper over the background without scaling it. - WALLPAPER_LAYOUT_TILE, + WALLPAPER_LAYOUT_TILE }; const SkColor kLoginWallpaperColor = 0xFEFEFE; @@ -57,6 +57,10 @@ class ASH_EXPORT DesktopBackgroundController BACKGROUND_IMAGE, }; + // This is used to initialize Resource ID variables and to denote "no + // resource ID" in parameters. + static const int kInvalidResourceID; + DesktopBackgroundController(); virtual ~DesktopBackgroundController(); @@ -110,18 +114,20 @@ class ASH_EXPORT DesktopBackgroundController // maximum width of all displays, and the maximum height of all displays. static gfx::Size GetMaxDisplaySizeInNative(); - private: - friend class DesktopBackgroundControllerTest; - // friend class chromeos::WallpaperManagerBrowserTestDefaultWallpaper; - FRIEND_TEST_ALL_PREFIXES(DesktopBackgroundControllerTest, GetMaxDisplaySize); - // Returns true if the specified wallpaper is already stored // in |current_wallpaper_|. // If |image| is NULL, resource_id is compared. + // If |compare_layouts| is false, layout is ignored. bool WallpaperIsAlreadyLoaded(const gfx::ImageSkia* image, int resource_id, + bool compare_layouts, WallpaperLayout layout) const; + private: + friend class DesktopBackgroundControllerTest; + // friend class chromeos::WallpaperManagerBrowserTestDefaultWallpaper; + FRIEND_TEST_ALL_PREFIXES(DesktopBackgroundControllerTest, GetMaxDisplaySize); + // Creates view for all root windows, or notifies them to repaint if they // already exist. void SetDesktopBackgroundImageMode(); diff --git a/ash/desktop_background/wallpaper_resizer.cc b/ash/desktop_background/wallpaper_resizer.cc index 46497b2..4bd0264 100644 --- a/ash/desktop_background/wallpaper_resizer.cc +++ b/ash/desktop_background/wallpaper_resizer.cc @@ -93,8 +93,6 @@ void Resize(SkBitmap orig_bitmap, } // namespace -const int kInvalidResourceID = -1; - // static uint32_t WallpaperResizer::GetImageId(const gfx::ImageSkia& image) { const gfx::ImageSkiaRep& image_rep = image.GetRepresentation(1.0f); @@ -120,7 +118,7 @@ WallpaperResizer::WallpaperResizer(const gfx::ImageSkia& image, WallpaperLayout layout) : image_(image), original_image_id_(GetImageId(image_)), - resource_id_(kInvalidResourceID), + resource_id_(DesktopBackgroundController::kInvalidResourceID), target_size_(target_size), layout_(layout), weak_ptr_factory_(this) { diff --git a/ash/desktop_background/wallpaper_resizer.h b/ash/desktop_background/wallpaper_resizer.h index 2b867994..989dbdb 100644 --- a/ash/desktop_background/wallpaper_resizer.h +++ b/ash/desktop_background/wallpaper_resizer.h @@ -18,8 +18,6 @@ namespace ash { class WallpaperResizerObserver; -extern const int kInvalidResourceID; - // Stores the current wallpaper data and resize it to |target_size| if needed. class ASH_EXPORT WallpaperResizer { public: diff --git a/chrome/browser/chromeos/customization_document.cc b/chrome/browser/chromeos/customization_document.cc index f6edd98..07304d5 100644 --- a/chrome/browser/chromeos/customization_document.cc +++ b/chrome/browser/chromeos/customization_document.cc @@ -14,6 +14,7 @@ #include "base/logging.h" #include "base/memory/weak_ptr.h" #include "base/metrics/histogram.h" +#include "base/path_service.h" #include "base/prefs/pref_registry_simple.h" #include "base/prefs/pref_service.h" #include "base/strings/string_split.h" @@ -22,7 +23,9 @@ #include "base/strings/utf_string_conversions.h" #include "base/time/time.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/chromeos/customization_wallpaper_downloader.h" #include "chrome/browser/chromeos/extensions/default_app_order.h" +#include "chrome/browser/chromeos/login/wallpaper_manager.h" #include "chrome/browser/chromeos/login/wizard_controller.h" #include "chrome/browser/chromeos/net/delay_network_call.h" #include "chrome/browser/extensions/external_loader.h" @@ -30,7 +33,9 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/app_list/app_list_syncable_service.h" #include "chrome/browser/ui/app_list/app_list_syncable_service_factory.h" +#include "chrome/common/chrome_paths.h" #include "chrome/common/extensions/extension_constants.h" +#include "chrome/common/pref_names.h" #include "chromeos/network/network_state.h" #include "chromeos/network/network_state_handler.h" #include "chromeos/system/statistics_provider.h" @@ -68,6 +73,14 @@ const char kAcceptedManifestVersion[] = "1.0"; const char kStartupCustomizationManifestPath[] = "/opt/oem/etc/startup_manifest.json"; +// This is subdirectory relative to PathService(DIR_CHROMEOS_CUSTOM_WALLPAPERS), +// where downloaded (and resized) wallpaper is stored. +const char kCustomizationDefaultWallpaperDir[] = "customization"; + +// The original downloaded image file is stored under this name. +const char kCustomizationDefaultWallpaperDownloadedFile[] = + "default_downloaded_wallpaper.bin"; + // Name of local state option that tracks if services customization has been // applied. const char kServicesCustomizationAppliedPref[] = "ServicesCustomizationApplied"; @@ -130,6 +143,12 @@ std::string GetLocaleSpecificStringImpl( return std::string(); } +void CheckWallpaperCacheExists(const base::FilePath& path, bool* exists) { + DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread()); + DCHECK(exists); + *exists = base::PathExists(path); +} + } // anonymous namespace // Template URL where to fetch OEM services customization manifest from. @@ -160,7 +179,7 @@ class ServicesCustomizationExternalLoader ServicesCustomizationDocument::GetInstance()->StartFetching(); // In case of missing customization ID, SetCurrentApps will be called // synchronously from StartFetching and this function will be called - // recursively so we need to return to don't call LoadFinished twice. + // recursively so we need to return to avoid calling LoadFinished twice. // In case of async load it is safe to return empty list because this // provider didn't install any app yet so no app can be removed due to // returning empty list. @@ -341,20 +360,63 @@ std::string StartupCustomizationDocument::GetEULAPage( // ServicesCustomizationDocument implementation. ------------------------------- +class ServicesCustomizationDocument::ApplyingTask { + public: + // Registers in ServicesCustomizationDocument; + explicit ApplyingTask(ServicesCustomizationDocument* document); + + // Do not automatically deregister as we might be called on invalid thread. + ~ApplyingTask(); + + // Mark task finished and check for customization applied. + void Finished(bool success); + + private: + ServicesCustomizationDocument* document_; + + // This is error-checking flag to prevent destroying unfinished task + // or double finish. + bool engaged_; +}; + +ServicesCustomizationDocument::ApplyingTask::ApplyingTask( + ServicesCustomizationDocument* document) + : document_(document), engaged_(true) { + document->ApplyingTaskStarted(); +} + +ServicesCustomizationDocument::ApplyingTask::~ApplyingTask() { + DCHECK(!engaged_); +} + +void ServicesCustomizationDocument::ApplyingTask::Finished(bool success) { + DCHECK(engaged_); + if (engaged_) { + engaged_ = false; + document_->ApplyingTaskFinished(success); + } +} + ServicesCustomizationDocument::ServicesCustomizationDocument() : CustomizationDocument(kAcceptedManifestVersion), num_retries_(0), fetch_started_(false), - network_delay_(base::TimeDelta::FromMilliseconds( - kDefaultNetworkRetryDelayMS)), + network_delay_( + base::TimeDelta::FromMilliseconds(kDefaultNetworkRetryDelayMS)), + apply_tasks_started_(0), + apply_tasks_finished_(0), + apply_tasks_success_(0), weak_ptr_factory_(this) { } ServicesCustomizationDocument::ServicesCustomizationDocument( const std::string& manifest) : CustomizationDocument(kAcceptedManifestVersion), - network_delay_(base::TimeDelta::FromMilliseconds( - kDefaultNetworkRetryDelayMS)), + network_delay_( + base::TimeDelta::FromMilliseconds(kDefaultNetworkRetryDelayMS)), + apply_tasks_started_(0), + apply_tasks_finished_(0), + apply_tasks_success_(0), weak_ptr_factory_(this) { LoadManifestFromString(manifest); } @@ -374,6 +436,8 @@ ServicesCustomizationDocument* ServicesCustomizationDocument::GetInstance() { void ServicesCustomizationDocument::RegisterPrefs( PrefRegistrySimple* registry) { registry->RegisterBooleanPref(kServicesCustomizationAppliedPref, false); + registry->RegisterStringPref(prefs::kCustomizationDefaultWallpaperURL, + std::string()); } // static @@ -402,6 +466,45 @@ void ServicesCustomizationDocument::SetApplied(bool val) { prefs->SetBoolean(kServicesCustomizationAppliedPref, val); } +// static +base::FilePath ServicesCustomizationDocument::GetCustomizedWallpaperCacheDir() { + base::FilePath custom_wallpaper_dir; + if (!PathService::Get(chrome::DIR_CHROMEOS_CUSTOM_WALLPAPERS, + &custom_wallpaper_dir)) { + LOG(DFATAL) << "Unable to get custom wallpaper dir."; + return base::FilePath(); + } + return custom_wallpaper_dir.Append(kCustomizationDefaultWallpaperDir); +} + +// static +base::FilePath +ServicesCustomizationDocument::GetCustomizedWallpaperDownloadedFileName() { + const base::FilePath dir = GetCustomizedWallpaperCacheDir(); + if (dir.empty()) { + NOTREACHED(); + return dir; + } + return dir.Append(kCustomizationDefaultWallpaperDownloadedFile); +} + +void ServicesCustomizationDocument::EnsureCustomizationApplied() { + if (WasOOBECustomizationApplied()) + return; + + // When customization manifest is fetched, applying will start automatically. + if (IsReady()) + return; + + StartFetching(); +} + +base::Closure +ServicesCustomizationDocument::EnsureCustomizationAppliedClosure() { + return base::Bind(&ServicesCustomizationDocument::EnsureCustomizationApplied, + weak_ptr_factory_.GetWeakPtr()); +} + void ServicesCustomizationDocument::StartFetching() { if (IsReady() || fetch_started_) return; @@ -416,7 +519,7 @@ void ServicesCustomizationDocument::StartFetching() { url_ = GURL(base::StringPrintf( kManifestUrl, StringToLowerASCII(customization_id).c_str())); } else { - // There is no customization ID in VPD remember that. + // Remember that there is no customization ID in VPD. OnCustomizationNotFound(); return; } @@ -493,7 +596,7 @@ bool ServicesCustomizationDocument::LoadManifestFromString( } void ServicesCustomizationDocument::OnManifestLoaded() { - if (!ServicesCustomizationDocument::WasOOBECustomizationApplied()) + if (!WasOOBECustomizationApplied()) ApplyOOBECustomization(); scoped_ptr<base::DictionaryValue> prefs = @@ -545,18 +648,24 @@ void ServicesCustomizationDocument::OnURLFetchComplete( } bool ServicesCustomizationDocument::ApplyOOBECustomization() { - // TODO(dpolukhin): apply default wallpaper, crbug.com/348136. - SetApplied(true); - return true; + if (apply_tasks_started_) + return false; + + CheckAndApplyWallpaper(); + return false; } -GURL ServicesCustomizationDocument::GetDefaultWallpaperUrl() const { +bool ServicesCustomizationDocument::GetDefaultWallpaperUrl( + GURL* out_url) const { if (!IsReady()) - return GURL(); + return false; std::string url; - root_->GetString(kDefaultWallpaperAttr, &url); - return GURL(url); + if (!root_->GetString(kDefaultWallpaperAttr, &url)) + return false; + + *out_url = GURL(url); + return true; } bool ServicesCustomizationDocument::GetDefaultApps( @@ -689,4 +798,172 @@ void ServicesCustomizationDocument::ShutdownForTesting() { g_test_services_customization_document = NULL; } +void ServicesCustomizationDocument::StartOEMWallpaperDownload( + const GURL& wallpaper_url, + scoped_ptr<ServicesCustomizationDocument::ApplyingTask> applying) { + DCHECK(wallpaper_url.is_valid()); + + const base::FilePath dir = GetCustomizedWallpaperCacheDir(); + const base::FilePath file = GetCustomizedWallpaperDownloadedFileName(); + if (dir.empty() || file.empty()) { + NOTREACHED(); + applying->Finished(false); + return; + } + + wallpaper_downloader_.reset(new CustomizationWallpaperDownloader( + g_browser_process->system_request_context(), + wallpaper_url, + dir, + file, + base::Bind(&ServicesCustomizationDocument::OnOEMWallpaperDownloaded, + weak_ptr_factory_.GetWeakPtr(), + base::Passed(applying.Pass())))); + + wallpaper_downloader_->Start(); +} + +void ServicesCustomizationDocument::CheckAndApplyWallpaper() { + if (wallpaper_downloader_.get()) { + VLOG(1) << "CheckAndApplyWallpaper(): download has already started."; + return; + } + scoped_ptr<ServicesCustomizationDocument::ApplyingTask> applying( + new ServicesCustomizationDocument::ApplyingTask(this)); + + GURL wallpaper_url; + if (!GetDefaultWallpaperUrl(&wallpaper_url)) { + PrefService* pref_service = g_browser_process->local_state(); + std::string current_url = + pref_service->GetString(prefs::kCustomizationDefaultWallpaperURL); + if (!current_url.empty()) { + VLOG(1) << "ServicesCustomizationDocument::CheckAndApplyWallpaper() : " + << "No wallpaper URL attribute in customization document, " + << "but current value is non-empty: '" << current_url + << "'. Ignored."; + } + applying->Finished(true); + return; + } + + // Should fail if this ever happens in tests. + DCHECK(wallpaper_url.is_valid()); + if (!wallpaper_url.is_valid()) { + if (!wallpaper_url.is_empty()) { + LOG(WARNING) << "Invalid Customized Wallpaper URL '" + << wallpaper_url.spec() << "'."; + } + applying->Finished(false); + return; + } + + scoped_ptr<bool> exists(new bool(false)); + + base::Closure check_file_exists = + base::Bind(&CheckWallpaperCacheExists, + GetCustomizedWallpaperDownloadedFileName(), + base::Unretained(exists.get())); + base::Closure on_checked_closure = + base::Bind(&ServicesCustomizationDocument::OnCheckedWallpaperCacheExists, + weak_ptr_factory_.GetWeakPtr(), + base::Passed(exists.Pass()), + base::Passed(applying.Pass())); + if (!content::BrowserThread::PostBlockingPoolTaskAndReply( + FROM_HERE, check_file_exists, on_checked_closure)) { + LOG(WARNING) << "Failed to start check Wallpaper cache exists."; + } +} + +void ServicesCustomizationDocument::OnCheckedWallpaperCacheExists( + scoped_ptr<bool> exists, + scoped_ptr<ServicesCustomizationDocument::ApplyingTask> applying) { + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK(exists); + DCHECK(applying); + + ApplyWallpaper(*exists, applying.Pass()); +} + +void ServicesCustomizationDocument::ApplyWallpaper( + bool default_wallpaper_file_exists, + scoped_ptr<ServicesCustomizationDocument::ApplyingTask> applying) { + GURL wallpaper_url; + const bool wallpaper_url_present = GetDefaultWallpaperUrl(&wallpaper_url); + + PrefService* pref_service = g_browser_process->local_state(); + + std::string current_url = + pref_service->GetString(prefs::kCustomizationDefaultWallpaperURL); + if (current_url != wallpaper_url.spec()) { + if (wallpaper_url_present) { + VLOG(1) << "ServicesCustomizationDocument::ApplyWallpaper() : " + << "Wallpaper URL in customization document '" + << wallpaper_url.spec() << "' differs from current '" + << current_url << "'." + << (GURL(current_url).is_valid() && default_wallpaper_file_exists + ? " Ignored." + : " Will refetch."); + } else { + VLOG(1) << "ServicesCustomizationDocument::ApplyWallpaper() : " + << "No wallpaper URL attribute in customization document, " + << "but current value is non-empty: '" << current_url + << "'. Ignored."; + } + } + if (!wallpaper_url_present) { + applying->Finished(true); + return; + } + + DCHECK(wallpaper_url.is_valid()); + + // Never update system-wide wallpaper (i.e. do not check + // current_url == wallpaper_url.spec() ) + if (GURL(current_url).is_valid() && default_wallpaper_file_exists) { + VLOG(1) + << "ServicesCustomizationDocument::ApplyWallpaper() : reuse existing"; + OnOEMWallpaperDownloaded(applying.Pass(), true, GURL(current_url)); + } else { + VLOG(1) + << "ServicesCustomizationDocument::ApplyWallpaper() : start download"; + StartOEMWallpaperDownload(wallpaper_url, applying.Pass()); + } +} + +void ServicesCustomizationDocument::OnOEMWallpaperDownloaded( + scoped_ptr<ServicesCustomizationDocument::ApplyingTask> applying, + bool success, + const GURL& wallpaper_url) { + if (success) { + DCHECK(wallpaper_url.is_valid()); + + VLOG(1) << "Setting default wallpaper to '" + << GetCustomizedWallpaperDownloadedFileName().value() << "' ('" + << wallpaper_url.spec() << "')"; + WallpaperManager::Get()->SetCustomizedDefaultWallpaper( + wallpaper_url, + GetCustomizedWallpaperDownloadedFileName(), + GetCustomizedWallpaperCacheDir()); + } + wallpaper_downloader_.reset(); + applying->Finished(success); +} + +void ServicesCustomizationDocument::ApplyingTaskStarted() { + ++apply_tasks_started_; +} + +void ServicesCustomizationDocument::ApplyingTaskFinished(bool success) { + DCHECK_GT(apply_tasks_started_, apply_tasks_finished_); + ++apply_tasks_finished_; + + apply_tasks_success_ += success; + + if (apply_tasks_started_ != apply_tasks_finished_) + return; + + if (apply_tasks_success_ == apply_tasks_finished_) + SetApplied(true); +} + } // namespace chromeos diff --git a/chrome/browser/chromeos/customization_document.h b/chrome/browser/chromeos/customization_document.h index 1c0ea8f..97e166d 100644 --- a/chrome/browser/chromeos/customization_document.h +++ b/chrome/browser/chromeos/customization_document.h @@ -42,6 +42,7 @@ void Test__InitStartupCustomizationDocument(const std::string& manifest); namespace chromeos { +class CustomizationWallpaperDownloader; class ServicesCustomizationExternalLoader; namespace system { @@ -135,7 +136,8 @@ class StartupCustomizationDocument : public CustomizationDocument { // OEM services customization document class. // ServicesCustomizationDocument is fetched from network therefore it is not // ready just after creation. Fetching of the manifest should be initiated -// outside this class by calling StartFetching() method. +// outside this class by calling StartFetching() or EnsureCustomizationApplied() +// methods. // User of the file should check IsReady before use it. class ServicesCustomizationDocument : public CustomizationDocument, private net::URLFetcherDelegate { @@ -152,6 +154,12 @@ class ServicesCustomizationDocument : public CustomizationDocument, // once per machine. static bool WasOOBECustomizationApplied(); + // If customization has not been applied, start fetching and applying. + void EnsureCustomizationApplied(); + + // Returns Closure with the EnsureCustomizationApplied() method. + base::Closure EnsureCustomizationAppliedClosure(); + // Start fetching customization document. void StartFetching(); @@ -159,8 +167,9 @@ class ServicesCustomizationDocument : public CustomizationDocument, // applied successfully. Return true if customization was applied. bool ApplyOOBECustomization(); - // Returns default wallpaper URL. - GURL GetDefaultWallpaperUrl() const; + // Returns true if default wallpaper URL attribute found in manifest. + // |out_url| is set to attribute value. + bool GetDefaultWallpaperUrl(GURL* out_url) const; // Returns list of default apps. bool GetDefaultApps(std::vector<std::string>* ids) const; @@ -179,12 +188,21 @@ class ServicesCustomizationDocument : public CustomizationDocument, // Remove instance of ServicesCustomizationDocument for tests. static void ShutdownForTesting(); + // These methods are also called by WallpaperManager to get "global default" + // customized wallpaper path (and to init default wallpaper path from it) + // before first wallpaper is shown. + static base::FilePath GetCustomizedWallpaperCacheDir(); + static base::FilePath GetCustomizedWallpaperDownloadedFileName(); + private: friend struct DefaultSingletonTraits<ServicesCustomizationDocument>; typedef std::vector<base::WeakPtr<ServicesCustomizationExternalLoader> > ExternalLoaders; + // Guard for a single application task (wallpaper downloading, for example). + class ApplyingTask; + // C-tor for singleton construction. ServicesCustomizationDocument(); @@ -237,6 +255,36 @@ class ServicesCustomizationDocument : public CustomizationDocument, const std::string& locale, const base::DictionaryValue& root) const; + // Start download of wallpaper image if needed. + void StartOEMWallpaperDownload(const GURL& wallpaper_url, + scoped_ptr<ApplyingTask> applying); + + // Check that current customized wallpaper cache exists. Once wallpaper is + // downloaded, it's never updated (even if manifest is re-fetched). + // Start wallpaper download if needed. + void CheckAndApplyWallpaper(); + + // Intermediate function to pass the result of PathExists to ApplyWallpaper. + void OnCheckedWallpaperCacheExists(scoped_ptr<bool> exists, + scoped_ptr<ApplyingTask> applying); + + // Called after downloaded wallpaper has been checked. + void ApplyWallpaper(bool default_wallpaper_file_exists, + scoped_ptr<ApplyingTask> applying); + + // Set Shell default wallpaper to customized. + // It's wrapped as a callback and passed as a parameter to + // CustomizationWallpaperDownloader. + void OnOEMWallpaperDownloaded(scoped_ptr<ApplyingTask> applying, + bool success, + const GURL& wallpaper_url); + + // Register one of Customization applying tasks. + void ApplyingTaskStarted(); + + // Mark task finished and check for "all customization applied". + void ApplyingTaskFinished(bool success); + // Services customization manifest URL. GURL url_; @@ -255,6 +303,19 @@ class ServicesCustomizationDocument : public CustomizationDocument, // Known external loaders. ExternalLoaders external_loaders_; + scoped_ptr<CustomizationWallpaperDownloader> wallpaper_downloader_; + + // This is barrier until customization is applied. + // When number of finished tasks match number of started - customization is + // applied. + size_t apply_tasks_started_; + size_t apply_tasks_finished_; + + // This is the number of successfully finished customization tasks. + // If it matches number of tasks finished - customization is applied + // successfully. + size_t apply_tasks_success_; + // Weak factory for callbacks. base::WeakPtrFactory<ServicesCustomizationDocument> weak_ptr_factory_; diff --git a/chrome/browser/chromeos/customization_document_unittest.cc b/chrome/browser/chromeos/customization_document_unittest.cc index 4eae520..cb91510 100644 --- a/chrome/browser/chromeos/customization_document_unittest.cc +++ b/chrome/browser/chromeos/customization_document_unittest.cc @@ -76,7 +76,6 @@ const char kBadManifest[] = "{\"version\": \"1\"}"; const char kGoodServicesManifest[] = "{" " \"version\": \"1.0\"," - " \"default_wallpaper\": \"http://somedomain.com/image.png\",\n" " \"default_apps\": [\n" " \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\n" " \"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\"\n" @@ -323,19 +322,20 @@ TEST_F(ServicesCustomizationDocumentTest, Basic) { RunUntilIdle(); EXPECT_TRUE(doc->IsReady()); - EXPECT_EQ(doc->GetDefaultWallpaperUrl().spec(), - "http://somedomain.com/image.png"); + GURL wallpaper_url; + EXPECT_FALSE(doc->GetDefaultWallpaperUrl(&wallpaper_url)); + EXPECT_EQ("", wallpaper_url.spec()); std::vector<std::string> default_apps; EXPECT_TRUE(doc->GetDefaultApps(&default_apps)); ASSERT_EQ(default_apps.size(), 2u); - EXPECT_EQ(default_apps[0], "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); - EXPECT_EQ(default_apps[1], "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"); + EXPECT_EQ("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", default_apps[0]); + EXPECT_EQ("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", default_apps[1]); - EXPECT_EQ(doc->GetOemAppsFolderName("en-US"), "EN-US OEM Name"); - EXPECT_EQ(doc->GetOemAppsFolderName("en"), "EN OEM Name"); - EXPECT_EQ(doc->GetOemAppsFolderName("ru"), "Default OEM Name"); + EXPECT_EQ("EN-US OEM Name", doc->GetOemAppsFolderName("en-US")); + EXPECT_EQ("EN OEM Name", doc->GetOemAppsFolderName("en")); + EXPECT_EQ("Default OEM Name", doc->GetOemAppsFolderName("ru")); } TEST_F(ServicesCustomizationDocumentTest, NoCustomizationIdInVpd) { @@ -427,7 +427,7 @@ TEST_F(ServicesCustomizationDocumentTest, DefaultApps) { app_list::AppListSyncableService* service = app_list::AppListSyncableServiceFactory::GetForProfile(profile.get()); ASSERT_TRUE(service); - EXPECT_EQ(service->GetOemFolderNameForTest(), "EN OEM Name"); + EXPECT_EQ("EN OEM Name", service->GetOemFolderNameForTest()); } TEST_F(ServicesCustomizationDocumentTest, CustomizationManifestNotFound) { diff --git a/chrome/browser/chromeos/customization_wallpaper_downloader.cc b/chrome/browser/chromeos/customization_wallpaper_downloader.cc new file mode 100644 index 0000000..d672945 --- /dev/null +++ b/chrome/browser/chromeos/customization_wallpaper_downloader.cc @@ -0,0 +1,194 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/customization_wallpaper_downloader.h" + +#include <math.h> +#include <algorithm> + +#include "base/file_util.h" +#include "content/public/browser/browser_thread.h" +#include "net/base/load_flags.h" +#include "net/http/http_status_code.h" +#include "net/url_request/url_fetcher.h" +#include "net/url_request/url_request_context_getter.h" +#include "url/gurl.h" + +namespace chromeos { +namespace { +// This is temporary file suffix (for downloading or resizing). +const char kTemporarySuffix[] = ".tmp"; + +// Sleep between wallpaper retries (used multiplied by squared retry number). +const unsigned kRetrySleepSeconds = 10; + +// Retry is infinite with increasing intervals. When calculated delay becomes +// longer than maximum (kMaxRetrySleepSeconds) it is set to the maximum. +const double kMaxRetrySleepSeconds = 6 * 3600; // 6 hours + +void CreateWallpaperDirectory(const base::FilePath& wallpaper_dir, + bool* success) { + DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread()); + DCHECK(success); + + *success = CreateDirectoryAndGetError(wallpaper_dir, NULL); + if (!*success) { + NOTREACHED() << "Failed to create directory '" << wallpaper_dir.value() + << "'"; + } +} + +void RenameTemporaryFile(const base::FilePath& from, + const base::FilePath& to, + bool* success) { + DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread()); + DCHECK(success); + + base::File::Error error; + if (base::ReplaceFile(from, to, &error)) { + *success = true; + } else { + LOG(WARNING) + << "Failed to rename temporary file of Customized Wallpaper. error=" + << error; + *success = false; + } +} + +} // namespace + +CustomizationWallpaperDownloader::CustomizationWallpaperDownloader( + net::URLRequestContextGetter* url_context_getter, + const GURL& wallpaper_url, + const base::FilePath& wallpaper_dir, + const base::FilePath& wallpaper_downloaded_file, + base::Callback<void(bool success, const GURL&)> + on_wallpaper_fetch_completed) + : url_context_getter_(url_context_getter), + wallpaper_url_(wallpaper_url), + wallpaper_dir_(wallpaper_dir), + wallpaper_downloaded_file_(wallpaper_downloaded_file), + wallpaper_temporary_file_(wallpaper_downloaded_file.value() + + kTemporarySuffix), + retries_(0), + on_wallpaper_fetch_completed_(on_wallpaper_fetch_completed), + weak_factory_(this) { + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); +} + +CustomizationWallpaperDownloader::~CustomizationWallpaperDownloader() { + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); +} + +void CustomizationWallpaperDownloader::StartRequest() { + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK(wallpaper_url_.is_valid()); + + url_fetcher_.reset( + net::URLFetcher::Create(wallpaper_url_, net::URLFetcher::GET, this)); + url_fetcher_->SetRequestContext(url_context_getter_); + url_fetcher_->SetLoadFlags(net::LOAD_BYPASS_CACHE | + net::LOAD_DISABLE_CACHE | + net::LOAD_DO_NOT_SAVE_COOKIES | + net::LOAD_DO_NOT_SEND_COOKIES | + net::LOAD_DO_NOT_SEND_AUTH_DATA); + base::SequencedWorkerPool* blocking_pool = + content::BrowserThread::GetBlockingPool(); + url_fetcher_->SaveResponseToFileAtPath( + wallpaper_temporary_file_, + blocking_pool->GetSequencedTaskRunner(blocking_pool->GetSequenceToken())); + url_fetcher_->Start(); +} + +void CustomizationWallpaperDownloader::Retry() { + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + ++retries_; + + const double delay_seconds = + std::min(kMaxRetrySleepSeconds, + static_cast<double>(retries_) * retries_ * kRetrySleepSeconds); + const base::TimeDelta delay = + base::TimeDelta::FromSeconds(lround(delay_seconds)); + + VLOG(1) << "Schedule Customized Wallpaper download in " << delay.InSecondsF() + << " seconds (retry = " << retries_ << ")."; + request_scheduled_.Start( + FROM_HERE, delay, this, &CustomizationWallpaperDownloader::StartRequest); +} + +void CustomizationWallpaperDownloader::Start() { + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + scoped_ptr<bool> success(new bool(false)); + + base::Closure mkdir_closure = base::Bind(&CreateWallpaperDirectory, + wallpaper_dir_, + base::Unretained(success.get())); + base::Closure on_created_closure = + base::Bind(&CustomizationWallpaperDownloader::OnWallpaperDirectoryCreated, + weak_factory_.GetWeakPtr(), + base::Passed(success.Pass())); + if (!content::BrowserThread::PostBlockingPoolTaskAndReply( + FROM_HERE, mkdir_closure, on_created_closure)) { + LOG(WARNING) << "Failed to start Customized Wallpaper download."; + } +} + +void CustomizationWallpaperDownloader::OnWallpaperDirectoryCreated( + scoped_ptr<bool> success) { + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + if (*success) + StartRequest(); +} + +void CustomizationWallpaperDownloader::OnURLFetchComplete( + const net::URLFetcher* source) { + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_EQ(url_fetcher_.get(), source); + + const net::URLRequestStatus status = source->GetStatus(); + const int response_code = source->GetResponseCode(); + + const bool server_error = + !status.is_success() || + (response_code >= net::HTTP_INTERNAL_SERVER_ERROR && + response_code < (net::HTTP_INTERNAL_SERVER_ERROR + 100)); + + VLOG(1) << "CustomizationWallpaperDownloader::OnURLFetchComplete(): status=" + << status.status(); + + if (server_error) { + url_fetcher_.reset(); + Retry(); + return; + } + + base::FilePath response_path; + url_fetcher_->GetResponseAsFilePath(true, &response_path); + url_fetcher_.reset(); + + scoped_ptr<bool> success(new bool(false)); + + base::Closure rename_closure = base::Bind(&RenameTemporaryFile, + response_path, + wallpaper_downloaded_file_, + base::Unretained(success.get())); + base::Closure on_rename_closure = + base::Bind(&CustomizationWallpaperDownloader::OnTemporaryFileRenamed, + weak_factory_.GetWeakPtr(), + base::Passed(success.Pass())); + if (!content::BrowserThread::PostBlockingPoolTaskAndReply( + FROM_HERE, rename_closure, on_rename_closure)) { + LOG(WARNING) + << "Failed to start Customized Wallpaper Rename DownloadedFile."; + on_wallpaper_fetch_completed_.Run(false, wallpaper_url_); + } +} + +void CustomizationWallpaperDownloader::OnTemporaryFileRenamed( + scoped_ptr<bool> success) { + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + on_wallpaper_fetch_completed_.Run(*success, wallpaper_url_); +} + +} // namespace chromeos diff --git a/chrome/browser/chromeos/customization_wallpaper_downloader.h b/chrome/browser/chromeos/customization_wallpaper_downloader.h new file mode 100644 index 0000000..9922ffb --- /dev/null +++ b/chrome/browser/chromeos/customization_wallpaper_downloader.h @@ -0,0 +1,102 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_CHROMEOS_CUSTOMIZATION_WALLPAPER_DOWNLOADER_H_ +#define CHROME_BROWSER_CHROMEOS_CUSTOMIZATION_WALLPAPER_DOWNLOADER_H_ + +#include <string> + +#include "base/bind.h" +#include "base/files/file_path.h" +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "base/time/time.h" +#include "base/timer/timer.h" +#include "net/url_request/url_fetcher_delegate.h" +#include "url/gurl.h" + +namespace net { +class URLRequestContextGetter; +} // namespace net + +namespace chromeos { + +// Download customized wallpaper. +// Owner of this class must provide callback, which will be called on +// finished (either successful or failed) wallpaper download. +class CustomizationWallpaperDownloader : public net::URLFetcherDelegate { + public: + // - |url_context_getter| - Context to initialize net::URLFetcher. + // - |wallpaper_url| - wallpaper URL to download. + // - |wallpaper_dir| - directory, where wallpaper will be downloaded + // (it will be created). + // - |wallpaper_downloaded_file| - full path to local file to store downloaded + // wallpaper file. File is downloaded to temporary location + // |wallpaper_downloaded_file| + ".tmp", so directory must be writable. + // After download is completed, temporary file will be renamed to + // |wallpaper_downloaded_file|. + CustomizationWallpaperDownloader( + net::URLRequestContextGetter* url_context_getter, + const GURL& wallpaper_url, + const base::FilePath& wallpaper_dir, + const base::FilePath& wallpaper_downloaded_file, + base::Callback<void(bool success, const GURL&)> + on_wallpaper_fetch_completed); + + virtual ~CustomizationWallpaperDownloader(); + + // Start download. + void Start(); + + // net::URLFetcherDelegate + virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE; + + private: + // Start new request. + void StartRequest(); + + // Schedules retry. + void Retry(); + + // Called on UI thread. + void OnWallpaperDirectoryCreated(scoped_ptr<bool> success); + + // Called on UI thread. + void OnTemporaryFileRenamed(scoped_ptr<bool> success); + + // This is used to initialize net::URLFetcher object. + scoped_refptr<net::URLRequestContextGetter> url_context_getter_; + + // This fetcher is used to download wallpaper file. + scoped_ptr<net::URLFetcher> url_fetcher_; + + // The wallpaper URL to fetch. + const GURL wallpaper_url_; + + // Wallpaper directory (to be created). + const base::FilePath wallpaper_dir_; + + // Full path to local file to save downloaded wallpaper. + const base::FilePath wallpaper_downloaded_file_; + + // Full path to temporary file to fetch downloaded wallpper. + const base::FilePath wallpaper_temporary_file_; + + // Pending retry. + base::OneShotTimer<CustomizationWallpaperDownloader> request_scheduled_; + + // Number of download retries (first attempt is not counted as retry). + size_t retries_; + + // Callback supplied by caller. + base::Callback<void(bool success, const GURL&)> on_wallpaper_fetch_completed_; + + base::WeakPtrFactory<CustomizationWallpaperDownloader> weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(CustomizationWallpaperDownloader); +}; + +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_CUSTOMIZATION_WALLPAPER_DOWNLOADER_H_ diff --git a/chrome/browser/chromeos/login/login_display_host_impl.cc b/chrome/browser/chromeos/login/login_display_host_impl.cc index 76d675d..4692b4e 100644 --- a/chrome/browser/chromeos/login/login_display_host_impl.cc +++ b/chrome/browser/chromeos/login/login_display_host_impl.cc @@ -48,6 +48,7 @@ #include "chrome/browser/chromeos/login/webui_login_view.h" #include "chrome/browser/chromeos/login/wizard_controller.h" #include "chrome/browser/chromeos/mobile_config.h" +#include "chrome/browser/chromeos/net/delay_network_call.h" #include "chrome/browser/chromeos/policy/auto_enrollment_client.h" #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" #include "chrome/browser/chromeos/system/input_device_settings.h" @@ -1186,6 +1187,13 @@ void ShowLoginWizard(const std::string& first_screen_name) { return; } + if (StartupUtils::IsEulaAccepted()) { + DelayNetworkCall( + ServicesCustomizationDocument::GetInstance() + ->EnsureCustomizationAppliedClosure(), + base::TimeDelta::FromMilliseconds(kDefaultNetworkRetryDelayMS)); + } + bool show_login_screen = (first_screen_name.empty() && oobe_complete) || first_screen_name == chromeos::WizardController::kLoginScreenName; diff --git a/chrome/browser/chromeos/login/user_image.h b/chrome/browser/chromeos/login/user_image.h index b1e3933..a228c90 100644 --- a/chrome/browser/chromeos/login/user_image.h +++ b/chrome/browser/chromeos/login/user_image.h @@ -5,6 +5,7 @@ #ifndef CHROME_BROWSER_CHROMEOS_LOGIN_USER_IMAGE_H_ #define CHROME_BROWSER_CHROMEOS_LOGIN_USER_IMAGE_H_ +#include <string> #include <vector> #include "ui/gfx/image/image_skia.h" @@ -61,6 +62,9 @@ class UserImage { bool is_safe_format() const { return is_safe_format_; } void MarkAsSafe(); + const std::string& file_path() const { return file_path_; } + void set_file_path(const std::string& file_path) { file_path_ = file_path; } + private: gfx::ImageSkia image_; bool has_raw_image_; @@ -68,6 +72,9 @@ class UserImage { bool has_animated_image_; RawImage animated_image_; GURL url_; + + // If image was loaded from the local file, file path is stored here. + std::string file_path_; bool is_safe_format_; }; diff --git a/chrome/browser/chromeos/login/user_image_loader.cc b/chrome/browser/chromeos/login/user_image_loader.cc index bbb7c6b..3087fd7 100644 --- a/chrome/browser/chromeos/login/user_image_loader.cc +++ b/chrome/browser/chromeos/login/user_image_loader.cc @@ -20,9 +20,11 @@ namespace chromeos { -UserImageLoader::ImageInfo::ImageInfo(int size, +UserImageLoader::ImageInfo::ImageInfo(const std::string& file_path, + int pixels_per_side, const LoadedCallback& loaded_cb) - : size(size), + : file_path(file_path), + pixels_per_side(pixels_per_side), loaded_cb(loaded_cb) { } @@ -41,33 +43,32 @@ UserImageLoader::~UserImageLoader() { } void UserImageLoader::Start(const std::string& filepath, - int size, + int pixels_per_side, const LoadedCallback& loaded_cb) { background_task_runner_->PostTask( FROM_HERE, base::Bind(&UserImageLoader::ReadAndDecodeImage, this, - filepath, - ImageInfo(size, loaded_cb))); + ImageInfo(filepath, pixels_per_side, loaded_cb))); } void UserImageLoader::Start(scoped_ptr<std::string> data, - int size, + int pixels_per_side, const LoadedCallback& loaded_cb) { - background_task_runner_->PostTask(FROM_HERE, - base::Bind(&UserImageLoader::DecodeImage, - this, - base::Passed(&data), - ImageInfo(size, loaded_cb))); + background_task_runner_->PostTask( + FROM_HERE, + base::Bind(&UserImageLoader::DecodeImage, + this, + base::Passed(&data), + ImageInfo(std::string(), pixels_per_side, loaded_cb))); } -void UserImageLoader::ReadAndDecodeImage(const std::string& filepath, - const ImageInfo& image_info) { +void UserImageLoader::ReadAndDecodeImage(const ImageInfo& image_info) { DCHECK(background_task_runner_->RunsTasksOnCurrentThread()); scoped_ptr<std::string> data(new std::string); const bool success = - base::ReadFileToString(base::FilePath(filepath), data.get()); + base::ReadFileToString(base::FilePath(image_info.file_path), data.get()); DCHECK(success); DecodeImage(data.Pass(), image_info); @@ -92,7 +93,8 @@ void UserImageLoader::OnImageDecoded(const ImageDecoder* decoder, NOTREACHED(); return; } - const int target_size = it->second.size; + const std::string file_path = it->second.file_path; + const int target_size = it->second.pixels_per_side; const LoadedCallback loaded_cb = it->second.loaded_cb; image_info_map_.erase(it); @@ -100,12 +102,13 @@ void UserImageLoader::OnImageDecoded(const ImageDecoder* decoder, if (target_size > 0) { // Auto crop the image, taking the largest square in the center. - int size = std::min(decoded_image.width(), decoded_image.height()); - int x = (decoded_image.width() - size) / 2; - int y = (decoded_image.height() - size) / 2; - SkBitmap cropped_image = - SkBitmapOperations::CreateTiledBitmap(decoded_image, x, y, size, size); - if (size > target_size) { + int pixels_per_side = + std::min(decoded_image.width(), decoded_image.height()); + int x = (decoded_image.width() - pixels_per_side) / 2; + int y = (decoded_image.height() - pixels_per_side) / 2; + SkBitmap cropped_image = SkBitmapOperations::CreateTiledBitmap( + decoded_image, x, y, pixels_per_side, pixels_per_side); + if (pixels_per_side > target_size) { // Also downsize the image to save space and memory. final_image = skia::ImageOperations::Resize(cropped_image, @@ -123,6 +126,7 @@ void UserImageLoader::OnImageDecoded(const ImageDecoder* decoder, gfx::ImageSkia::CreateFrom1xBitmap(final_image); final_image_skia.MakeThreadSafe(); UserImage user_image(final_image_skia, decoder->get_image_data()); + user_image.set_file_path(file_path); if (image_codec_ == ImageDecoder::ROBUST_JPEG_CODEC) user_image.MarkAsSafe(); foreground_task_runner_->PostTask(FROM_HERE, diff --git a/chrome/browser/chromeos/login/user_image_loader.h b/chrome/browser/chromeos/login/user_image_loader.h index 2b16726..af43f58 100644 --- a/chrome/browser/chromeos/login/user_image_loader.h +++ b/chrome/browser/chromeos/login/user_image_loader.h @@ -42,10 +42,10 @@ class UserImageLoader : public base::RefCountedThreadSafe<UserImageLoader>, // image from |filepath| on disk, the second processes |data| read into memory // already. void Start(const std::string& filepath, - int size, + int pixels_per_side, const LoadedCallback& loaded_cb); void Start(scoped_ptr<std::string> data, - int size, + int pixels_per_side, const LoadedCallback& loaded_cb); private: @@ -53,10 +53,13 @@ class UserImageLoader : public base::RefCountedThreadSafe<UserImageLoader>, // Contains attributes we need to know about each image we decode. struct ImageInfo { - ImageInfo(int size, const LoadedCallback& loaded_cb); + ImageInfo(const std::string& file_path, + int pixels_per_side, + const LoadedCallback& loaded_cb); ~ImageInfo(); - const int size; + const std::string file_path; + const int pixels_per_side; const LoadedCallback loaded_cb; }; @@ -64,10 +67,9 @@ class UserImageLoader : public base::RefCountedThreadSafe<UserImageLoader>, virtual ~UserImageLoader(); - // Reads the image from |filepath| and starts the decoding process. This - // method may only be invoked via the |background_task_runner_|. - void ReadAndDecodeImage(const std::string& filepath, - const ImageInfo& image_info); + // Reads the image from |image_info.file_path| and starts the decoding + // process. This method may only be invoked via the |background_task_runner_|. + void ReadAndDecodeImage(const ImageInfo& image_info); // Decodes the image |data|. This method may only be invoked via the // |background_task_runner_|. diff --git a/chrome/browser/chromeos/login/wallpaper_manager.cc b/chrome/browser/chromeos/login/wallpaper_manager.cc index 751bcc3..ae98e2f 100644 --- a/chrome/browser/chromeos/login/wallpaper_manager.cc +++ b/chrome/browser/chromeos/login/wallpaper_manager.cc @@ -29,6 +29,7 @@ #include "base/values.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chrome_notification_types.h" +#include "chrome/browser/chromeos/customization_document.h" #include "chrome/browser/chromeos/extensions/wallpaper_manager_util.h" #include "chrome/browser/chromeos/extensions/wallpaper_private_api.h" #include "chrome/browser/chromeos/login/login_display_host_impl.h" @@ -123,6 +124,30 @@ bool MoveCustomWallpaperDirectory(const char* sub_dir, return false; } +// These global default values are used to set customized default +// wallpaper path in WallpaperManager::InitializeWallpaper(). +base::FilePath GetCustomizedWallpaperDefaultRescaledFileName( + const std::string& suffix) { + const base::FilePath default_downloaded_file_name = + ServicesCustomizationDocument::GetCustomizedWallpaperDownloadedFileName(); + const base::FilePath default_cache_dir = + ServicesCustomizationDocument::GetCustomizedWallpaperCacheDir(); + if (default_downloaded_file_name.empty() || default_cache_dir.empty()) + return base::FilePath(); + return default_cache_dir.Append( + default_downloaded_file_name.BaseName().value() + suffix); +} + +// Whether DesktopBackgroundController should start with customized default +// wallpaper in WallpaperManager::InitializeWallpaper() or not. +bool ShouldUseCustomizedDefaultWallpaper() { + PrefService* pref_service = g_browser_process->local_state(); + + return !(pref_service->FindPreference( + prefs::kCustomizationDefaultWallpaperURL) + ->IsDefaultValue()); +} + } // namespace const char kWallpaperSequenceTokenName[] = "wallpaper-sequence"; @@ -144,6 +169,77 @@ const int kWallpaperThumbnailHeight = 68; static WallpaperManager* g_wallpaper_manager = NULL; +class WallpaperManager::CustomizedWallpaperRescaledFiles { + public: + CustomizedWallpaperRescaledFiles(const base::FilePath& path_downloaded, + const base::FilePath& path_rescaled_small, + const base::FilePath& path_rescaled_large); + + bool AllSizesExist() const; + + // Closure will hold unretained pointer to this object. So caller must + // make sure that the closure will be destoyed before this object. + // Closure must be called on BlockingPool. + base::Closure CreateCheckerClosure(); + + const base::FilePath& path_downloaded() const { return path_downloaded_; } + const base::FilePath& path_rescaled_small() const { + return path_rescaled_small_; + } + const base::FilePath& path_rescaled_large() const { + return path_rescaled_large_; + } + + const bool downloaded_exists() const { return downloaded_exists_; } + const bool rescaled_small_exists() const { return rescaled_small_exists_; } + const bool rescaled_large_exists() const { return rescaled_large_exists_; } + + private: + // Must be called on BlockingPool. + void CheckCustomizedWallpaperFilesExist(); + + const base::FilePath path_downloaded_; + const base::FilePath path_rescaled_small_; + const base::FilePath path_rescaled_large_; + + bool downloaded_exists_; + bool rescaled_small_exists_; + bool rescaled_large_exists_; + + DISALLOW_COPY_AND_ASSIGN(CustomizedWallpaperRescaledFiles); +}; + +WallpaperManager::CustomizedWallpaperRescaledFiles:: + CustomizedWallpaperRescaledFiles(const base::FilePath& path_downloaded, + const base::FilePath& path_rescaled_small, + const base::FilePath& path_rescaled_large) + : path_downloaded_(path_downloaded), + path_rescaled_small_(path_rescaled_small), + path_rescaled_large_(path_rescaled_large), + downloaded_exists_(false), + rescaled_small_exists_(false), + rescaled_large_exists_(false) { +} + +base::Closure +WallpaperManager::CustomizedWallpaperRescaledFiles::CreateCheckerClosure() { + return base::Bind(&WallpaperManager::CustomizedWallpaperRescaledFiles:: + CheckCustomizedWallpaperFilesExist, + base::Unretained(this)); +} + +void WallpaperManager::CustomizedWallpaperRescaledFiles:: + CheckCustomizedWallpaperFilesExist() { + DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread()); + downloaded_exists_ = base::PathExists(path_downloaded_); + rescaled_small_exists_ = base::PathExists(path_rescaled_small_); + rescaled_large_exists_ = base::PathExists(path_rescaled_large_); +} + +bool WallpaperManager::CustomizedWallpaperRescaledFiles::AllSizesExist() const { + return rescaled_small_exists_ && rescaled_large_exists_; +} + // This object is passed between several threads while wallpaper is being // loaded. It will notify callback when last reference to it is removed // (thus indicating that the last load action has finished). @@ -450,6 +546,15 @@ void WallpaperManager::InitializeWallpaper() { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); UserManager* user_manager = UserManager::Get(); + // Apply device customization. + if (ShouldUseCustomizedDefaultWallpaper()) { + SetDefaultWallpaperPath( + GetCustomizedWallpaperDefaultRescaledFileName(kSmallWallpaperSuffix), + scoped_ptr<gfx::ImageSkia>().Pass(), + GetCustomizedWallpaperDefaultRescaledFileName(kLargeWallpaperSuffix), + scoped_ptr<gfx::ImageSkia>().Pass()); + } + CommandLine* command_line = GetCommandLine(); if (command_line->HasSwitch(chromeos::switches::kGuestSession)) { // Guest wallpaper should be initialized when guest login. @@ -803,7 +908,7 @@ void WallpaperManager::DoSetDefaultWallpaper( : ash::WALLPAPER_LAYOUT_CENTER_CROPPED; DCHECK(file); if (!default_wallpaper_image_.get() || - default_wallpaper_image_->url().spec() != file->value()) { + default_wallpaper_image_->file_path() != file->value()) { default_wallpaper_image_.reset(); if (!file->empty()) { loaded_wallpapers_++; @@ -985,10 +1090,11 @@ void WallpaperManager::EnableSurpriseMe() { Profile* profile = ProfileManager::GetActiveUserProfile(); DCHECK(profile); DCHECK(extensions::EventRouter::Get(profile)); + + using namespace extensions::api::wallpaper_private; scoped_ptr<extensions::Event> event( - new extensions::Event( - extensions::api::wallpaper_private::OnRequestEnableSurpriseMe::kEventName, - extensions::api::wallpaper_private::OnRequestEnableSurpriseMe::Create())); + new extensions::Event(OnRequestEnableSurpriseMe::kEventName, + OnRequestEnableSurpriseMe::Create())); extensions::EventRouter::Get(profile)->DispatchEventToExtension( extension_misc::kWallpaperManagerId, event.Pass()); @@ -1539,6 +1645,129 @@ base::TimeDelta WallpaperManager::GetWallpaperLoadDelay() const { return delay; } +void WallpaperManager::SetCustomizedDefaultWallpaperAfterCheck( + const GURL& wallpaper_url, + const base::FilePath& downloaded_file, + scoped_ptr<CustomizedWallpaperRescaledFiles> rescaled_files) { + PrefService* pref_service = g_browser_process->local_state(); + + std::string current_url = + pref_service->GetString(prefs::kCustomizationDefaultWallpaperURL); + if (current_url != wallpaper_url.spec() || !rescaled_files->AllSizesExist()) { + DCHECK(rescaled_files->downloaded_exists()); + + // Either resized images do not exist or cached version is incorrect. + // Need to start resize again. + wallpaper_loader_->Start( + downloaded_file.value(), + 0, // Do not crop. + base::Bind(&WallpaperManager::OnCustomizedDefaultWallpaperDecoded, + weak_factory_.GetWeakPtr(), + wallpaper_url, + base::Passed(rescaled_files.Pass()))); + } else { + SetDefaultWallpaperPath(rescaled_files->path_rescaled_small(), + scoped_ptr<gfx::ImageSkia>().Pass(), + rescaled_files->path_rescaled_large(), + scoped_ptr<gfx::ImageSkia>().Pass()); + } +} + +void WallpaperManager::OnCustomizedDefaultWallpaperDecoded( + const GURL& wallpaper_url, + scoped_ptr<CustomizedWallpaperRescaledFiles> rescaled_files, + const UserImage& wallpaper) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + // If decoded wallpaper is empty, we have probably failed to decode the file. + if (wallpaper.image().isNull()) { + LOG(WARNING) << "Failed to decode customized wallpaper."; + return; + } + + wallpaper.image().EnsureRepsForSupportedScales(); + scoped_ptr<gfx::ImageSkia> deep_copy(wallpaper.image().DeepCopy()); + + scoped_ptr<bool> success(new bool(false)); + scoped_ptr<gfx::ImageSkia> small_wallpaper_image(new gfx::ImageSkia); + scoped_ptr<gfx::ImageSkia> large_wallpaper_image(new gfx::ImageSkia); + + // TODO(bshe): This may break if RawImage becomes RefCountedMemory. + base::Closure resize_closure = + base::Bind(&WallpaperManager::ResizeCustomizedDefaultWallpaper, + base::Unretained(this), + base::Passed(&deep_copy), + wallpaper.raw_image(), + base::Unretained(rescaled_files.get()), + base::Unretained(success.get()), + base::Unretained(small_wallpaper_image.get()), + base::Unretained(large_wallpaper_image.get())); + base::Closure on_resized_closure = + base::Bind(&WallpaperManager::OnCustomizedDefaultWallpaperResized, + weak_factory_.GetWeakPtr(), + wallpaper_url, + base::Passed(rescaled_files.Pass()), + base::Passed(success.Pass()), + base::Passed(small_wallpaper_image.Pass()), + base::Passed(large_wallpaper_image.Pass())); + + if (!task_runner_->PostTaskAndReply( + FROM_HERE, resize_closure, on_resized_closure)) { + LOG(WARNING) << "Failed to start Customized Wallpaper resize."; + } +} + +void WallpaperManager::ResizeCustomizedDefaultWallpaper( + scoped_ptr<gfx::ImageSkia> image, + const UserImage::RawImage& raw_image, + const CustomizedWallpaperRescaledFiles* rescaled_files, + bool* success, + gfx::ImageSkia* small_wallpaper_image, + gfx::ImageSkia* large_wallpaper_image) { + DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread( + sequence_token_)); + UserImage wallpaper(*image.get(), raw_image); + + *success = true; + + *success &= ResizeAndSaveWallpaper(wallpaper, + rescaled_files->path_rescaled_small(), + ash::WALLPAPER_LAYOUT_STRETCH, + kSmallWallpaperMaxWidth, + kSmallWallpaperMaxHeight, + small_wallpaper_image); + + *success &= ResizeAndSaveWallpaper(wallpaper, + rescaled_files->path_rescaled_large(), + ash::WALLPAPER_LAYOUT_STRETCH, + kLargeWallpaperMaxWidth, + kLargeWallpaperMaxHeight, + large_wallpaper_image); +} + +void WallpaperManager::OnCustomizedDefaultWallpaperResized( + const GURL& wallpaper_url, + scoped_ptr<CustomizedWallpaperRescaledFiles> rescaled_files, + scoped_ptr<bool> success, + scoped_ptr<gfx::ImageSkia> small_wallpaper_image, + scoped_ptr<gfx::ImageSkia> large_wallpaper_image) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK(rescaled_files); + DCHECK(success.get()); + if (!*success) { + LOG(WARNING) << "Failed to save resized customized default wallpaper"; + return; + } + PrefService* pref_service = g_browser_process->local_state(); + pref_service->SetString(prefs::kCustomizationDefaultWallpaperURL, + wallpaper_url.spec()); + SetDefaultWallpaperPath(rescaled_files->path_rescaled_small(), + small_wallpaper_image.Pass(), + rescaled_files->path_rescaled_large(), + large_wallpaper_image.Pass()); + VLOG(1) << "Customized default wallpaper applied."; +} + WallpaperManager::PendingWallpaper* WallpaperManager::GetPendingWallpaper( const std::string& user_id, bool delayed) { @@ -1552,6 +1781,41 @@ WallpaperManager::PendingWallpaper* WallpaperManager::GetPendingWallpaper( return pending_inactive_; } +void WallpaperManager::SetCustomizedDefaultWallpaper( + const GURL& wallpaper_url, + const base::FilePath& downloaded_file, + const base::FilePath& resized_directory) { + // Should fail if this ever happens in tests. + DCHECK(wallpaper_url.is_valid()); + if (!wallpaper_url.is_valid()) { + if (!wallpaper_url.is_empty()) { + LOG(WARNING) << "Invalid Customized Wallpaper URL '" + << wallpaper_url.spec() << "'"; + } + return; + } + std::string downloaded_file_name = downloaded_file.BaseName().value(); + scoped_ptr<CustomizedWallpaperRescaledFiles> rescaled_files( + new CustomizedWallpaperRescaledFiles( + downloaded_file, + resized_directory.Append(downloaded_file_name + + kSmallWallpaperSuffix), + resized_directory.Append(downloaded_file_name + + kLargeWallpaperSuffix))); + + base::Closure check_file_exists = rescaled_files->CreateCheckerClosure(); + base::Closure on_checked_closure = + base::Bind(&WallpaperManager::SetCustomizedDefaultWallpaperAfterCheck, + weak_factory_.GetWeakPtr(), + wallpaper_url, + downloaded_file, + base::Passed(rescaled_files.Pass())); + if (!BrowserThread::PostBlockingPoolTaskAndReply( + FROM_HERE, check_file_exists, on_checked_closure)) { + LOG(WARNING) << "Failed to start check CheckCustomizedWallpaperFilesExist."; + } +} + void WallpaperManager::SetDefaultWallpaperPathsFromCommandLine( base::CommandLine* command_line) { default_small_wallpaper_file_ = command_line->GetSwitchValuePath( @@ -1571,8 +1835,7 @@ void WallpaperManager::OnDefaultWallpaperDecoded( scoped_ptr<chromeos::UserImage>* result_out, MovableOnDestroyCallbackHolder on_finish, const UserImage& wallpaper) { - result_out->reset(new UserImage(wallpaper.image())); - (*result_out)->set_url(GURL(path.value())); + result_out->reset(new UserImage(wallpaper)); ash::Shell::GetInstance()->desktop_background_controller()->SetWallpaperImage( wallpaper.image(), layout); } @@ -1599,4 +1862,49 @@ const char* WallpaperManager::GetCustomWallpaperSubdirForCurrentResolution() { : kLargeWallpaperSubDir; } +void WallpaperManager::SetDefaultWallpaperPath( + const base::FilePath& default_small_wallpaper_file, + scoped_ptr<gfx::ImageSkia> small_wallpaper_image, + const base::FilePath& default_large_wallpaper_file, + scoped_ptr<gfx::ImageSkia> large_wallpaper_image) { + default_small_wallpaper_file_ = default_small_wallpaper_file; + default_large_wallpaper_file_ = default_large_wallpaper_file; + + ash::DesktopBackgroundController* dbc = + ash::Shell::GetInstance()->desktop_background_controller(); + + // |need_update_screen| is true if the previous default wallpaper is visible + // now, so we need to update wallpaper on the screen. + // + // Layout is ignored here, so ash::WALLPAPER_LAYOUT_CENTER is used + // as a placeholder only. + const bool need_update_screen = + default_wallpaper_image_.get() && + dbc->WallpaperIsAlreadyLoaded( + &(default_wallpaper_image_->image()), + ash::DesktopBackgroundController::kInvalidResourceID, + false /* compare_layouts */, + ash::WALLPAPER_LAYOUT_CENTER); + + default_wallpaper_image_.reset(); + if (GetAppropriateResolution() == WALLPAPER_RESOLUTION_SMALL) { + if (small_wallpaper_image) { + default_wallpaper_image_.reset(new UserImage(*small_wallpaper_image)); + default_wallpaper_image_->set_file_path( + default_small_wallpaper_file.value()); + } + } else { + if (large_wallpaper_image) { + default_wallpaper_image_.reset(new UserImage(*large_wallpaper_image)); + default_wallpaper_image_->set_file_path( + default_large_wallpaper_file.value()); + } + } + + if (need_update_screen) { + DoSetDefaultWallpaper(std::string(), + MovableOnDestroyCallbackHolder().Pass()); + } +} + } // namespace chromeos diff --git a/chrome/browser/chromeos/login/wallpaper_manager.h b/chrome/browser/chromeos/login/wallpaper_manager.h index cb3c95a..1a76f78 100644 --- a/chrome/browser/chromeos/login/wallpaper_manager.h +++ b/chrome/browser/chromeos/login/wallpaper_manager.h @@ -112,6 +112,10 @@ class WallpaperManager: public content::NotificationObserver { DISALLOW_COPY_AND_ASSIGN(TestApi); }; + // This should be public to allow access from functions in anonymous + // namespace. + class CustomizedWallpaperRescaledFiles; + class Observer { public: virtual ~Observer() {} @@ -266,6 +270,17 @@ class WallpaperManager: public content::NotificationObserver { const UserImage& wallpaper, bool update_wallpaper); + // Use given files as new default wallpaper. + // Reloads current wallpaper, if old default was loaded. + // Current value of default_wallpaper_image_ is destroyed. + // Sets default_wallpaper_image_ either to |small_wallpaper_image| or + // |large_wallpaper_image| depending on GetAppropriateResolution(). + void SetDefaultWallpaperPath( + const base::FilePath& customized_default_wallpaper_file_small, + scoped_ptr<gfx::ImageSkia> small_wallpaper_image, + const base::FilePath& customized_default_wallpaper_file_large, + scoped_ptr<gfx::ImageSkia> large_wallpaper_image); + // Sets wallpaper to default wallpaper (asynchronously with zero delay). void SetDefaultWallpaperNow(const std::string& user_id); @@ -331,6 +346,13 @@ class WallpaperManager: public content::NotificationObserver { // Enable surprise me wallpaper mode. void EnableSurpriseMe(); + // This is called from CustomizationDocument. + // |resized_directory| is the directory where resized versions are stored and + // must be writable. + void SetCustomizedDefaultWallpaper(const GURL& wallpaper_url, + const base::FilePath& downloaded_file, + const base::FilePath& resized_directory); + private: friend class TestApi; friend class WallpaperManagerBrowserTest; @@ -493,6 +515,36 @@ class WallpaperManager: public content::NotificationObserver { // in zero delay. base::TimeDelta GetWallpaperLoadDelay() const; + // This is called after we check that supplied default wallpaper files exist. + void SetCustomizedDefaultWallpaperAfterCheck( + const GURL& wallpaper_url, + const base::FilePath& downloaded_file, + scoped_ptr<CustomizedWallpaperRescaledFiles> rescaled_files); + + // Starts rescaling of customized wallpaper. + void OnCustomizedDefaultWallpaperDecoded( + const GURL& wallpaper_url, + scoped_ptr<CustomizedWallpaperRescaledFiles> rescaled_files, + const UserImage& user_image); + + // Resize and save customized default wallpaper. + void ResizeCustomizedDefaultWallpaper( + scoped_ptr<gfx::ImageSkia> image, + const UserImage::RawImage& raw_image, + const CustomizedWallpaperRescaledFiles* rescaled_files, + bool* success, + gfx::ImageSkia* small_wallpaper_image, + gfx::ImageSkia* large_wallpaper_image); + + // Check the result of ResizeCustomizedDefaultWallpaper and finally + // apply Customized Default Wallpaper. + void OnCustomizedDefaultWallpaperResized( + const GURL& wallpaper_url, + scoped_ptr<CustomizedWallpaperRescaledFiles> rescaled_files, + scoped_ptr<bool> success, + scoped_ptr<gfx::ImageSkia> small_wallpaper_image, + scoped_ptr<gfx::ImageSkia> large_wallpaper_image); + // Init |*default_*_wallpaper_file_| from given command line and // clear |default_wallpaper_image_|. void SetDefaultWallpaperPathsFromCommandLine(base::CommandLine* command_line); diff --git a/chrome/browser/chromeos/login/wizard_controller.cc b/chrome/browser/chromeos/login/wizard_controller.cc index 4275d6d..e3113bc 100644 --- a/chrome/browser/chromeos/login/wizard_controller.cc +++ b/chrome/browser/chromeos/login/wizard_controller.cc @@ -679,6 +679,10 @@ void WizardController::PerformPostEulaActions() { base::Bind(&WizardController::StartTimezoneResolve, weak_factory_.GetWeakPtr()), base::TimeDelta::FromMilliseconds(kDefaultNetworkRetryDelayMS)); + DelayNetworkCall( + ServicesCustomizationDocument::GetInstance() + ->EnsureCustomizationAppliedClosure(), + base::TimeDelta::FromMilliseconds(kDefaultNetworkRetryDelayMS)); // Now that EULA has been accepted (for official builds), enable portal check. // ChromiumOS builds would go though this code path too. diff --git a/chrome/browser/extensions/external_provider_impl_chromeos_unittest.cc b/chrome/browser/extensions/external_provider_impl_chromeos_unittest.cc index 74117b3..f2b97ca 100644 --- a/chrome/browser/extensions/external_provider_impl_chromeos_unittest.cc +++ b/chrome/browser/extensions/external_provider_impl_chromeos_unittest.cc @@ -6,11 +6,14 @@ #include "base/command_line.h" #include "base/memory/scoped_ptr.h" +#include "base/prefs/testing_pref_service.h" #include "base/test/scoped_path_override.h" #include "chrome/browser/chrome_notification_types.h" +#include "chrome/browser/chromeos/customization_document.h" #include "chrome/browser/extensions/extension_service_unittest.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" +#include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" #include "chromeos/system/mock_statistics_provider.h" #include "chromeos/system/statistics_provider.h" @@ -52,6 +55,10 @@ class ExternalProviderImplChromeOSTest : public ExtensionServiceTestBase { virtual void SetUp() OVERRIDE { ExtensionServiceTestBase::SetUp(); + TestingBrowserProcess::GetGlobal()->SetLocalState(&local_state_); + chromeos::ServicesCustomizationDocument::RegisterPrefs( + local_state_.registry()); + external_externsions_overrides_.reset( new base::ScopedPathOverride(chrome::DIR_EXTERNAL_EXTENSIONS, data_dir_.Append("external"))); @@ -64,9 +71,11 @@ class ExternalProviderImplChromeOSTest : public ExtensionServiceTestBase { virtual void TearDown() OVERRIDE { chromeos::system::StatisticsProvider::SetTestProvider(NULL); + TestingBrowserProcess::GetGlobal()->SetLocalState(NULL); } private: + TestingPrefServiceSimple local_state_; scoped_ptr<base::ScopedPathOverride> external_externsions_overrides_; chromeos::system::MockStatisticsProvider mock_statistics_provider_; diff --git a/chrome/browser/extensions/external_provider_impl_unittest.cc b/chrome/browser/extensions/external_provider_impl_unittest.cc index 3b82b78..27e8c55 100644 --- a/chrome/browser/extensions/external_provider_impl_unittest.cc +++ b/chrome/browser/extensions/external_provider_impl_unittest.cc @@ -9,6 +9,7 @@ #include "base/files/file_path.h" #include "base/memory/scoped_ptr.h" #include "base/path_service.h" +#include "base/prefs/testing_pref_service.h" #include "base/strings/stringprintf.h" #include "base/test/scoped_path_override.h" #include "chrome/browser/chrome_notification_types.h" @@ -16,6 +17,7 @@ #include "chrome/browser/extensions/updater/extension_cache_fake.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" +#include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" #include "content/public/browser/notification_service.h" #include "content/public/test/test_utils.h" @@ -25,6 +27,7 @@ #include "testing/gmock/include/gmock/gmock.h" #if defined(OS_CHROMEOS) +#include "chrome/browser/chromeos/customization_document.h" #include "chromeos/system/mock_statistics_provider.h" #include "chromeos/system/statistics_provider.h" #endif @@ -65,6 +68,13 @@ class ExternalProviderImplTest : public ExtensionServiceTestBase { virtual void SetUp() OVERRIDE { ExtensionServiceTestBase::SetUp(); test_server_.reset(new EmbeddedTestServer()); + +#if defined(OS_CHROMEOS) + TestingBrowserProcess::GetGlobal()->SetLocalState(&local_state_); + chromeos::ServicesCustomizationDocument::RegisterPrefs( + local_state_.registry()); +#endif + ASSERT_TRUE(test_server_->InitializeAndWaitUntilReady()); test_server_->RegisterRequestHandler( base::Bind(&ExternalProviderImplTest::HandleRequest, @@ -86,6 +96,7 @@ class ExternalProviderImplTest : public ExtensionServiceTestBase { virtual void TearDown() OVERRIDE { #if defined(OS_CHROMEOS) chromeos::system::StatisticsProvider::SetTestProvider(NULL); + TestingBrowserProcess::GetGlobal()->SetLocalState(NULL); #endif } @@ -128,6 +139,7 @@ class ExternalProviderImplTest : public ExtensionServiceTestBase { scoped_ptr<ExtensionCacheFake> test_extension_cache_; #if defined(OS_CHROMEOS) chromeos::system::MockStatisticsProvider mock_statistics_provider_; + TestingPrefServiceSimple local_state_; #endif DISALLOW_COPY_AND_ASSIGN(ExternalProviderImplTest); diff --git a/chrome/chrome_browser_chromeos.gypi b/chrome/chrome_browser_chromeos.gypi index a77e042..a9d6a8a 100644 --- a/chrome/chrome_browser_chromeos.gypi +++ b/chrome/chrome_browser_chromeos.gypi @@ -181,6 +181,8 @@ 'browser/chromeos/chrome_browser_main_chromeos.h', 'browser/chromeos/customization_document.cc', 'browser/chromeos/customization_document.h', + 'browser/chromeos/customization_wallpaper_downloader.cc', + 'browser/chromeos/customization_wallpaper_downloader.h', 'browser/chromeos/display/display_configuration_observer.cc', 'browser/chromeos/display/display_configuration_observer.h', 'browser/chromeos/display/display_preferences.cc', diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index 5518744..45f64b4 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc @@ -2077,6 +2077,12 @@ const char kUsedPolicyCertificates[] = "policy.used_policy_certificates"; // after recovery. const char kServerBackedDeviceState[] = "server_backed_device_state"; +// Customized wallpaper URL, which is already downloaded and scaled. +// The URL from this preference must never be fetched. It is compared to the +// URL from customization document to check if wallpaper URL has changed +// since wallpaper was cached. +const char kCustomizationDefaultWallpaperURL[] = + "customization.default_wallpaper_url"; #endif // Whether there is a Flash version installed that supports clearing LSO data. diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index a560c0e..bc4ff73 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h @@ -717,6 +717,7 @@ extern const char kOobeComplete[]; extern const char kDeviceRegistered[]; extern const char kUsedPolicyCertificates[]; extern const char kServerBackedDeviceState[]; +extern const char kCustomizationDefaultWallpaperURL[]; #endif extern const char kClearPluginLSODataEnabled[]; |