diff options
Diffstat (limited to 'chromium/components/wallpaper')
8 files changed, 220 insertions, 44 deletions
diff --git a/chromium/components/wallpaper/OWNERS b/chromium/components/wallpaper/OWNERS index 7ab58077e17..a9af8c98de7 100644 --- a/chromium/components/wallpaper/OWNERS +++ b/chromium/components/wallpaper/OWNERS @@ -1,2 +1,4 @@ bshe@chromium.org xdai@chromium.org + +# COMPONENT: UI>Shell>Wallpaper diff --git a/chromium/components/wallpaper/wallpaper_color_calculator.cc b/chromium/components/wallpaper/wallpaper_color_calculator.cc index 0096d5d1916..499fdd544da 100644 --- a/chromium/components/wallpaper/wallpaper_color_calculator.cc +++ b/chromium/components/wallpaper/wallpaper_color_calculator.cc @@ -11,9 +11,44 @@ #include "base/metrics/histogram_macros.h" #include "base/task_runner.h" #include "base/task_runner_util.h" +#include "components/wallpaper/wallpaper_color_calculator_observer.h" namespace wallpaper { +namespace { + +// The largest image size, in pixels, to synchronously calculate the prominent +// color. This is a simple heuristic optimization because extraction on images +// smaller than this should run very quickly, and offloading the task to another +// thread would actually take longer. +const int kMaxPixelsForSynchronousCalculation = 100; + +// Wrapper for color_utils::CalculateProminentColorOfBitmap() that records +// wallpaper specific metrics. +// +// NOTE: |image| is intentionally a copy to ensure it exists for the duration of +// the calculation. +SkColor CalculateWallpaperColor(const gfx::ImageSkia image, + color_utils::LumaRange luma, + color_utils::SaturationRange saturation) { + base::TimeTicks start_time = base::TimeTicks::Now(); + const SkColor prominent_color = color_utils::CalculateProminentColorOfBitmap( + *image.bitmap(), luma, saturation); + + UMA_HISTOGRAM_TIMES("Ash.Wallpaper.ColorExtraction.Durations", + base::TimeTicks::Now() - start_time); + UMA_HISTOGRAM_BOOLEAN("Ash.Wallpaper.ColorExtractionResult", + prominent_color != SK_ColorTRANSPARENT); + + return prominent_color; +} + +bool ShouldCalculateSync(const gfx::ImageSkia& image) { + return image.width() * image.height() <= kMaxPixelsForSynchronousCalculation; +} + +} // namespace + WallpaperColorCalculator::WallpaperColorCalculator( const gfx::ImageSkia& image, color_utils::LumaRange luma, @@ -38,15 +73,19 @@ void WallpaperColorCalculator::RemoveObserver( } bool WallpaperColorCalculator::StartCalculation() { - start_calculation_time_ = base::Time::Now(); + if (ShouldCalculateSync(image_)) { + const SkColor prominent_color = + CalculateWallpaperColor(image_, luma_, saturation_); + NotifyCalculationComplete(prominent_color); + return true; + } image_.MakeThreadSafe(); if (base::PostTaskAndReplyWithResult( task_runner_.get(), FROM_HERE, - base::Bind(&color_utils::CalculateProminentColorOfBitmap, - *image_.bitmap(), luma_, saturation_), - base::Bind(&WallpaperColorCalculator::NotifyCalculationComplete, - weak_ptr_factory_.GetWeakPtr()))) { + base::Bind(&CalculateWallpaperColor, image_, luma_, saturation_), + base::Bind(&WallpaperColorCalculator::OnAsyncCalculationComplete, + weak_ptr_factory_.GetWeakPtr(), base::TimeTicks::Now()))) { return true; } @@ -62,11 +101,16 @@ void WallpaperColorCalculator::SetTaskRunnerForTest( task_runner_ = task_runner; } -void WallpaperColorCalculator::NotifyCalculationComplete( +void WallpaperColorCalculator::OnAsyncCalculationComplete( + base::TimeTicks async_start_time, SkColor prominent_color) { - UMA_HISTOGRAM_MEDIUM_TIMES("Ash.Wallpaper.TimeSpentExtractingColors", - base::Time::Now() - start_calculation_time_); + UMA_HISTOGRAM_TIMES("Ash.Wallpaper.ColorExtraction.UserDelay", + base::TimeTicks::Now() - async_start_time); + NotifyCalculationComplete(prominent_color); +} +void WallpaperColorCalculator::NotifyCalculationComplete( + SkColor prominent_color) { prominent_color_ = prominent_color; for (auto& observer : observers_) observer.OnColorCalculationComplete(); diff --git a/chromium/components/wallpaper/wallpaper_color_calculator.h b/chromium/components/wallpaper/wallpaper_color_calculator.h index efad64bec17..c59c12e7139 100644 --- a/chromium/components/wallpaper/wallpaper_color_calculator.h +++ b/chromium/components/wallpaper/wallpaper_color_calculator.h @@ -10,7 +10,6 @@ #include "base/memory/weak_ptr.h" #include "base/observer_list.h" #include "base/time/time.h" -#include "components/wallpaper/wallpaper_color_calculator_observer.h" #include "components/wallpaper/wallpaper_export.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/gfx/color_analysis.h" @@ -23,7 +22,7 @@ class TaskRunner; namespace wallpaper { class WallpaperColorCalculatorObserver; -// Asynchronously calculates colors based on a wallpaper image. +// Calculates colors based on a wallpaper image. class WALLPAPER_EXPORT WallpaperColorCalculator { public: // |image|, |luma| and |saturation| are the input parameters to the color @@ -39,7 +38,8 @@ class WALLPAPER_EXPORT WallpaperColorCalculator { void RemoveObserver(WallpaperColorCalculatorObserver* observer); // Initiates the calculation and returns false if the calculation fails to be - // initiated. Callers should be aware that this will make |image_| read-only. + // initiated. Observers may be notified synchronously or asynchronously. + // Callers should be aware that this will make |image_| read-only. bool StartCalculation() WARN_UNUSED_RESULT; SkColor prominent_color() const { return prominent_color_; } @@ -52,6 +52,11 @@ class WALLPAPER_EXPORT WallpaperColorCalculator { void SetTaskRunnerForTest(scoped_refptr<base::TaskRunner> task_runner); private: + // Handles asynchronous calculation results. |async_start_time| is used to + // record duration metrics. + void OnAsyncCalculationComplete(base::TimeTicks async_start_time, + SkColor prominent_color); + // Notifies observers that a color calulation has completed. Called on the // same thread that constructed |this|. void NotifyCalculationComplete(SkColor prominent_color); @@ -71,10 +76,6 @@ class WALLPAPER_EXPORT WallpaperColorCalculator { // The task runner to run the calculation on. scoped_refptr<base::TaskRunner> task_runner_; - // The time that StartCalculation() was last called. Used for recording - // timing metrics. - base::Time start_calculation_time_; - base::ObserverList<WallpaperColorCalculatorObserver> observers_; base::WeakPtrFactory<WallpaperColorCalculator> weak_ptr_factory_; diff --git a/chromium/components/wallpaper/wallpaper_color_calculator_unittest.cc b/chromium/components/wallpaper/wallpaper_color_calculator_unittest.cc index 398d0fa95cb..938ec5ee85f 100644 --- a/chromium/components/wallpaper/wallpaper_color_calculator_unittest.cc +++ b/chromium/components/wallpaper/wallpaper_color_calculator_unittest.cc @@ -8,6 +8,7 @@ #include "base/macros.h" #include "base/memory/ptr_util.h" +#include "base/test/histogram_tester.h" #include "base/test/null_task_runner.h" #include "base/test/test_mock_time_task_runner.h" #include "base/threading/thread_task_runner_handle.h" @@ -27,6 +28,18 @@ namespace { const SkColor kDefaultColor = SK_ColorTRANSPARENT; +const SkColor kGray = SkColorSetRGB(10, 10, 10); + +const SkColor kVibrantGreen = SkColorSetRGB(25, 200, 25); + +// Image size that causes the WallpaperColorCalculator to synchronously extract +// the prominent color. +constexpr gfx::Size kSyncImageSize = gfx::Size(5, 5); + +// Image size that causes the WallpaperColorCalculator to asynchronously extract +// the prominent color. +constexpr gfx::Size kAsyncImageSize = gfx::Size(50, 50); + class TestWallpaperColorCalculatorObserver : public WallpaperColorCalculatorObserver { public: @@ -45,6 +58,24 @@ class TestWallpaperColorCalculatorObserver DISALLOW_COPY_AND_ASSIGN(TestWallpaperColorCalculatorObserver); }; +// Returns an image that will yield a color when processing it with +// color_utils::CalculateProminentColorOfBitmap() using the LumaRange::NORMAL +// and SaturationRange::VIBRANT values. +gfx::ImageSkia CreateColorProducingImage(const gfx::Size& size) { + gfx::Canvas canvas(size, 1.0f, true); + canvas.DrawColor(kGray); + canvas.FillRect(gfx::Rect(0, 1, size.height(), 1), kVibrantGreen); + return gfx::ImageSkia::CreateFrom1xBitmap(canvas.GetBitmap()); +} + +// Returns an image that will not yield a color when processing it with +// color_utils::CalculateProminentColorOfBitmap(). +gfx::ImageSkia CreateNonColorProducingImage(const gfx::Size& size) { + gfx::Canvas canvas(size, 1.0f, true); + canvas.DrawColor(kGray); + return gfx::ImageSkia::CreateFrom1xBitmap(canvas.GetBitmap()); +} + } // namespace class WallPaperColorCalculatorTest : public testing::Test { @@ -53,19 +84,26 @@ class WallPaperColorCalculatorTest : public testing::Test { ~WallPaperColorCalculatorTest() override; protected: + // Installs the given |task_runner| globally and on the |calculator_| instance + // if it exists. void InstallTaskRunner( scoped_refptr<base::SingleThreadTaskRunner> task_runner); - gfx::ImageSkia image_; + // Creates a new |calculator_| for the given |image| and installs the current + // |task_runner_|. + void CreateCalculator(const gfx::ImageSkia& image); std::unique_ptr<WallpaperColorCalculator> calculator_; + // Required for asynchronous calculations. scoped_refptr<base::TestMockTimeTaskRunner> task_runner_; TestWallpaperColorCalculatorObserver observer_; + base::HistogramTester histograms_; + private: - // Required by PostTaskAndReplyImpl. + // Required for asynchronous calculations, e.g. by PostTaskAndReplyImpl. std::unique_ptr<base::ThreadTaskRunnerHandle> task_runner_handle_; DISALLOW_COPY_AND_ASSIGN(WallPaperColorCalculatorTest); @@ -73,22 +111,7 @@ class WallPaperColorCalculatorTest : public testing::Test { WallPaperColorCalculatorTest::WallPaperColorCalculatorTest() : task_runner_(new base::TestMockTimeTaskRunner()) { - // Creates an |image_| that will yield a non-default prominent color. - const gfx::Size kImageSize(300, 200); - const SkColor kGray = SkColorSetRGB(10, 10, 10); - const SkColor kVibrantGreen = SkColorSetRGB(25, 200, 25); - - gfx::Canvas canvas(kImageSize, 1.0f, true); - canvas.FillRect(gfx::Rect(kImageSize), kGray); - canvas.FillRect(gfx::Rect(0, 1, 300, 1), kVibrantGreen); - - image_ = gfx::ImageSkia::CreateFrom1xBitmap(canvas.ToBitmap()); - - calculator_ = base::MakeUnique<WallpaperColorCalculator>( - image_, color_utils::LumaRange::NORMAL, - color_utils::SaturationRange::VIBRANT, nullptr); - calculator_->AddObserver(&observer_); - + CreateCalculator(CreateColorProducingImage(kAsyncImageSize)); InstallTaskRunner(task_runner_); } @@ -99,20 +122,55 @@ void WallPaperColorCalculatorTest::InstallTaskRunner( task_runner_handle_.reset(); task_runner_handle_ = base::MakeUnique<base::ThreadTaskRunnerHandle>(task_runner); - calculator_->SetTaskRunnerForTest(task_runner); + if (calculator_) + calculator_->SetTaskRunnerForTest(task_runner); } -TEST_F(WallPaperColorCalculatorTest, - StartCalculationReturnsFalseWhenPostingTaskFails) { +void WallPaperColorCalculatorTest::CreateCalculator( + const gfx::ImageSkia& image) { + calculator_ = base::MakeUnique<WallpaperColorCalculator>( + image, color_utils::LumaRange::NORMAL, + color_utils::SaturationRange::VIBRANT, task_runner_); + calculator_->AddObserver(&observer_); +} + +// Used to group the asynchronous calculation tests. +typedef WallPaperColorCalculatorTest WallPaperColorCalculatorAsyncTest; + +TEST_F(WallPaperColorCalculatorAsyncTest, MetricsForSuccessfulExtraction) { + histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtractionResult", 0); + histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtraction.Durations", 0); + histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtraction.UserDelay", 0); + + EXPECT_TRUE(calculator_->StartCalculation()); + task_runner_->RunUntilIdle(); + + histograms_.ExpectUniqueSample("Ash.Wallpaper.ColorExtractionResult", true, + 1); + histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtraction.Durations", 1); + histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtraction.UserDelay", 1); +} + +TEST_F(WallPaperColorCalculatorAsyncTest, MetricsWhenPostingTaskFails) { scoped_refptr<base::NullTaskRunner> task_runner = new base::NullTaskRunner(); InstallTaskRunner(task_runner); - calculator_->set_prominent_color_for_test(SK_ColorBLACK); + + histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtractionResult", 0); + histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtraction.Durations", 0); + histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtraction.UserDelay", 0); EXPECT_FALSE(calculator_->StartCalculation()); + task_runner_->RunUntilIdle(); + + histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtractionResult", 0); + histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtraction.Durations", 0); + histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtraction.UserDelay", 0); + EXPECT_EQ(kDefaultColor, calculator_->prominent_color()); } -TEST_F(WallPaperColorCalculatorTest, ObserverNotifiedOnSuccessfulCalculation) { +TEST_F(WallPaperColorCalculatorAsyncTest, + ObserverNotifiedOnSuccessfulCalculation) { EXPECT_FALSE(observer_.WasNotified()); EXPECT_TRUE(calculator_->StartCalculation()); @@ -122,7 +180,7 @@ TEST_F(WallPaperColorCalculatorTest, ObserverNotifiedOnSuccessfulCalculation) { EXPECT_TRUE(observer_.WasNotified()); } -TEST_F(WallPaperColorCalculatorTest, ColorUpdatedOnSuccessfulCalculation) { +TEST_F(WallPaperColorCalculatorAsyncTest, ColorUpdatedOnSuccessfulCalculation) { calculator_->set_prominent_color_for_test(kDefaultColor); EXPECT_TRUE(calculator_->StartCalculation()); @@ -132,7 +190,7 @@ TEST_F(WallPaperColorCalculatorTest, ColorUpdatedOnSuccessfulCalculation) { EXPECT_NE(kDefaultColor, calculator_->prominent_color()); } -TEST_F(WallPaperColorCalculatorTest, +TEST_F(WallPaperColorCalculatorAsyncTest, NoCrashWhenCalculatorDestroyedBeforeTaskProcessing) { EXPECT_TRUE(calculator_->StartCalculation()); calculator_.reset(); @@ -144,4 +202,38 @@ TEST_F(WallPaperColorCalculatorTest, EXPECT_FALSE(task_runner_->HasPendingTask()); } +// Used to group the synchronous calculation tests. +typedef WallPaperColorCalculatorTest WallPaperColorCalculatorSyncTest; + +TEST_F(WallPaperColorCalculatorSyncTest, MetricsForSuccessfulExtraction) { + CreateCalculator(CreateColorProducingImage(kSyncImageSize)); + calculator_->SetTaskRunnerForTest(nullptr); + + histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtractionResult", 0); + histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtraction.Durations", 0); + histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtraction.UserDelay", 0); + + EXPECT_TRUE(calculator_->StartCalculation()); + + histograms_.ExpectUniqueSample("Ash.Wallpaper.ColorExtractionResult", true, + 1); + histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtraction.Durations", 1); + histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtraction.UserDelay", 0); +} + +TEST_F(WallPaperColorCalculatorSyncTest, MetricsForFailedExctraction) { + CreateCalculator(CreateNonColorProducingImage(kSyncImageSize)); + + histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtractionResult", 0); + histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtraction.Durations", 0); + histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtraction.UserDelay", 0); + + EXPECT_TRUE(calculator_->StartCalculation()); + + histograms_.ExpectUniqueSample("Ash.Wallpaper.ColorExtractionResult", false, + 1); + histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtraction.Durations", 1); + histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtraction.UserDelay", 0); +} + } // namespace wallpaper diff --git a/chromium/components/wallpaper/wallpaper_manager_base.cc b/chromium/components/wallpaper/wallpaper_manager_base.cc index f81a395cbc5..188580d6e89 100644 --- a/chromium/components/wallpaper/wallpaper_manager_base.cc +++ b/chromium/components/wallpaper/wallpaper_manager_base.cc @@ -372,6 +372,22 @@ bool WallpaperManagerBase::GetLoggedInUserWallpaperInfo(WallpaperInfo* info) { user_manager::UserManager::Get()->GetActiveUser()->GetAccountId(), info); } +void WallpaperManagerBase::SetDefaultWallpaper(const AccountId& account_id, + bool update_wallpaper) { + RemoveUserWallpaperInfo(account_id); + + const wallpaper::WallpaperInfo info = { + std::string(), wallpaper::WALLPAPER_LAYOUT_CENTER, + user_manager::User::DEFAULT, base::Time::Now().LocalMidnight()}; + const bool is_persistent = + !user_manager::UserManager::Get()->IsUserNonCryptohomeDataEphemeral( + account_id); + SetUserWallpaperInfo(account_id, info, is_persistent); + + if (update_wallpaper) + SetDefaultWallpaperNow(account_id); +} + // static bool WallpaperManagerBase::ResizeImage( const gfx::ImageSkia& image, diff --git a/chromium/components/wallpaper/wallpaper_manager_base.h b/chromium/components/wallpaper/wallpaper_manager_base.h index 3c31f52bf5a..88601cc801e 100644 --- a/chromium/components/wallpaper/wallpaper_manager_base.h +++ b/chromium/components/wallpaper/wallpaper_manager_base.h @@ -276,6 +276,11 @@ class WALLPAPER_EXPORT WallpaperManagerBase { const gfx::ImageSkia& image, bool update_wallpaper) = 0; + // Updates wallpaper info for |account_id| to default. If |update_wallpaper| + // is false, don't change wallpaper but only update cache. + virtual void SetDefaultWallpaper(const AccountId& account_id, + 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. diff --git a/chromium/components/wallpaper/wallpaper_resizer.cc b/chromium/components/wallpaper/wallpaper_resizer.cc index 545a9cc4d00..0bfa3d4648c 100644 --- a/chromium/components/wallpaper/wallpaper_resizer.cc +++ b/chromium/components/wallpaper/wallpaper_resizer.cc @@ -9,6 +9,7 @@ #include "base/bind.h" #include "base/location.h" #include "base/logging.h" +#include "base/metrics/histogram_macros.h" #include "base/task_runner.h" #include "components/wallpaper/wallpaper_resizer_observer.h" #include "third_party/skia/include/core/SkImage.h" @@ -23,14 +24,19 @@ int RoundPositive(double x) { return static_cast<int>(floor(x + 0.5)); } -// Resizes |orig_bitmap| to |target_size| using |layout| and stores the +// Resizes |image| to |target_size| using |layout| and stores the // resulting bitmap at |resized_bitmap_out|. -void Resize(SkBitmap orig_bitmap, +// +// NOTE: |image| is intentionally a copy to ensure it exists for the duration of +// the function. +void Resize(const gfx::ImageSkia image, const gfx::Size& target_size, WallpaperLayout layout, SkBitmap* resized_bitmap_out, base::TaskRunner* task_runner) { DCHECK(task_runner->RunsTasksOnCurrentThread()); + + SkBitmap orig_bitmap = *image.bitmap(); SkBitmap new_bitmap = orig_bitmap; const int orig_width = orig_bitmap.width(); @@ -121,11 +127,13 @@ WallpaperResizer::~WallpaperResizer() { } void WallpaperResizer::StartResize() { + start_calculation_time_ = base::TimeTicks::Now(); + SkBitmap* resized_bitmap = new SkBitmap; if (!task_runner_->PostTaskAndReply( FROM_HERE, - base::Bind(&Resize, *image_.bitmap(), target_size_, layout_, - resized_bitmap, base::RetainedRef(task_runner_)), + base::Bind(&Resize, image_, target_size_, layout_, resized_bitmap, + base::RetainedRef(task_runner_)), base::Bind(&WallpaperResizer::OnResizeFinished, weak_ptr_factory_.GetWeakPtr(), base::Owned(resized_bitmap)))) { @@ -144,6 +152,9 @@ void WallpaperResizer::RemoveObserver(WallpaperResizerObserver* observer) { void WallpaperResizer::OnResizeFinished(SkBitmap* resized_bitmap) { image_ = gfx::ImageSkia::CreateFrom1xBitmap(*resized_bitmap); + UMA_HISTOGRAM_TIMES("Ash.Wallpaper.TimeSpentResizing", + base::TimeTicks::Now() - start_calculation_time_); + for (auto& observer : observers_) observer.OnWallpaperResized(); } diff --git a/chromium/components/wallpaper/wallpaper_resizer.h b/chromium/components/wallpaper/wallpaper_resizer.h index 836470d58af..ee96fc403ad 100644 --- a/chromium/components/wallpaper/wallpaper_resizer.h +++ b/chromium/components/wallpaper/wallpaper_resizer.h @@ -11,6 +11,7 @@ #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/observer_list.h" +#include "base/time/time.h" #include "components/wallpaper/wallpaper_layout.h" #include "components/wallpaper/wallpaper_resizer_observer.h" #include "skia/ext/image_operations.h" @@ -73,6 +74,10 @@ class WALLPAPER_EXPORT WallpaperResizer { WallpaperLayout layout_; + // The time that StartResize() was last called. Used for recording timing + // metrics. + base::TimeTicks start_calculation_time_; + scoped_refptr<base::TaskRunner> task_runner_; base::WeakPtrFactory<WallpaperResizer> weak_ptr_factory_; |