summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoralemate@chromium.org <alemate@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-23 14:17:57 +0000
committeralemate@chromium.org <alemate@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-23 14:17:57 +0000
commit94365820697621536ee32326ac4e77f720337a26 (patch)
tree9e80f1be42c03f0fc20729e378a993d275237cb0
parent9b9ed013945b7f2cdefc595a4c0384ada51f8d56 (diff)
downloadchromium_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
-rw-r--r--ash/desktop_background/desktop_background_controller.cc12
-rw-r--r--ash/desktop_background/desktop_background_controller.h18
-rw-r--r--ash/desktop_background/wallpaper_resizer.cc4
-rw-r--r--ash/desktop_background/wallpaper_resizer.h2
-rw-r--r--chrome/browser/chromeos/customization_document.cc305
-rw-r--r--chrome/browser/chromeos/customization_document.h67
-rw-r--r--chrome/browser/chromeos/customization_document_unittest.cc18
-rw-r--r--chrome/browser/chromeos/customization_wallpaper_downloader.cc194
-rw-r--r--chrome/browser/chromeos/customization_wallpaper_downloader.h102
-rw-r--r--chrome/browser/chromeos/login/login_display_host_impl.cc8
-rw-r--r--chrome/browser/chromeos/login/user_image.h7
-rw-r--r--chrome/browser/chromeos/login/user_image_loader.cc46
-rw-r--r--chrome/browser/chromeos/login/user_image_loader.h18
-rw-r--r--chrome/browser/chromeos/login/wallpaper_manager.cc320
-rw-r--r--chrome/browser/chromeos/login/wallpaper_manager.h52
-rw-r--r--chrome/browser/chromeos/login/wizard_controller.cc4
-rw-r--r--chrome/browser/extensions/external_provider_impl_chromeos_unittest.cc9
-rw-r--r--chrome/browser/extensions/external_provider_impl_unittest.cc12
-rw-r--r--chrome/chrome_browser_chromeos.gypi2
-rw-r--r--chrome/common/pref_names.cc6
-rw-r--r--chrome/common/pref_names.h1
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[];