1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager_test_utils.h"
6
7#include "ash/ash_switches.h"
8#include "base/command_line.h"
9#include "base/files/file_path.h"
10#include "base/files/file_util.h"
11#include "base/files/scoped_temp_dir.h"
12#include "base/logging.h"
13#include "base/run_loop.h"
14#include "base/time/time.h"
15#include "chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.h"
16#include "testing/gtest/include/gtest/gtest.h"
17#include "ui/gfx/codec/jpeg_codec.h"
18#include "ui/gfx/point.h"
19#include "ui/gfx/rect.h"
20
21namespace chromeos {
22
23namespace {
24
25class TestWallpaperObserverPendingListEmpty
26    : public WallpaperManager::Observer {
27 public:
28  explicit TestWallpaperObserverPendingListEmpty(
29      WallpaperManager* wallpaper_manager)
30      : empty_(false), wallpaper_manager_(wallpaper_manager) {
31    DCHECK(wallpaper_manager_);
32    wallpaper_manager_->AddObserver(this);
33  }
34
35  virtual ~TestWallpaperObserverPendingListEmpty() {
36    wallpaper_manager_->RemoveObserver(this);
37  }
38
39  virtual void OnWallpaperAnimationFinished(
40      const std::string& user_id) OVERRIDE {}
41
42  virtual void OnPendingListEmptyForTesting() OVERRIDE {
43    empty_ = true;
44    base::MessageLoop::current()->Quit();
45  }
46
47  void WaitForPendingListEmpty() {
48    if (wallpaper_manager_->GetPendingListSizeForTesting() == 0) {
49      empty_ = true;
50      return;
51    }
52    while (!empty_)
53      base::RunLoop().Run();
54  }
55
56 private:
57  bool empty_;
58  WallpaperManager* wallpaper_manager_;
59
60  DISALLOW_COPY_AND_ASSIGN(TestWallpaperObserverPendingListEmpty);
61};
62
63}  // namespace
64
65namespace wallpaper_manager_test_utils {
66
67const SkColor kLargeDefaultWallpaperColor = SK_ColorRED;
68const SkColor kSmallDefaultWallpaperColor = SK_ColorGREEN;
69const SkColor kLargeGuestWallpaperColor = SK_ColorBLUE;
70const SkColor kSmallGuestWallpaperColor = SK_ColorYELLOW;
71
72const SkColor kCustomWallpaperColor = SK_ColorMAGENTA;
73
74const int kWallpaperSize = 2;
75
76bool CreateJPEGImage(int width,
77                     int height,
78                     SkColor color,
79                     std::vector<unsigned char>* output) {
80  SkBitmap bitmap;
81  bitmap.allocN32Pixels(width, height);
82  bitmap.eraseColor(color);
83
84  const int kQuality = 80;
85  if (!gfx::JPEGCodec::Encode(
86          static_cast<const unsigned char*>(bitmap.getPixels()),
87          gfx::JPEGCodec::FORMAT_SkBitmap,
88          width,
89          height,
90          bitmap.rowBytes(),
91          kQuality,
92          output)) {
93    LOG(ERROR) << "Unable to encode " << width << "x" << height << " bitmap";
94    return false;
95  }
96  return true;
97}
98
99gfx::ImageSkia CreateTestImage(int width, int height, SkColor color) {
100  SkBitmap bitmap;
101  bitmap.allocN32Pixels(width, height);
102  bitmap.eraseColor(color);
103  return gfx::ImageSkia::CreateFrom1xBitmap(bitmap);
104}
105
106bool WriteJPEGFile(const base::FilePath& path,
107                   int width,
108                   int height,
109                   SkColor color) {
110  std::vector<unsigned char> output;
111  if (!CreateJPEGImage(width, height, color, &output))
112    return false;
113
114  size_t bytes_written = base::WriteFile(
115      path, reinterpret_cast<const char*>(&output[0]), output.size());
116  if (bytes_written != output.size()) {
117    LOG(ERROR) << "Wrote " << bytes_written << " byte(s) instead of "
118               << output.size() << " to " << path.value();
119    return false;
120  }
121  return true;
122}
123
124bool ImageIsNearColor(gfx::ImageSkia image, SkColor expected_color) {
125  if (image.size().IsEmpty()) {
126    LOG(ERROR) << "Image is empty";
127    return false;
128  }
129
130  const SkBitmap* bitmap = image.bitmap();
131  if (!bitmap) {
132    LOG(ERROR) << "Unable to get bitmap from image";
133    return false;
134  }
135
136  bitmap->lockPixels();
137  gfx::Point center = gfx::Rect(image.size()).CenterPoint();
138  SkColor image_color = bitmap->getColor(center.x(), center.y());
139  bitmap->unlockPixels();
140
141  const int kDiff = 3;
142  if (std::abs(static_cast<int>(SkColorGetA(image_color)) -
143               static_cast<int>(SkColorGetA(expected_color))) > kDiff ||
144      std::abs(static_cast<int>(SkColorGetR(image_color)) -
145               static_cast<int>(SkColorGetR(expected_color))) > kDiff ||
146      std::abs(static_cast<int>(SkColorGetG(image_color)) -
147               static_cast<int>(SkColorGetG(expected_color))) > kDiff ||
148      std::abs(static_cast<int>(SkColorGetB(image_color)) -
149               static_cast<int>(SkColorGetB(expected_color))) > kDiff) {
150    LOG(ERROR) << "Expected color near 0x" << std::hex << expected_color
151               << " but got 0x" << image_color;
152    return false;
153  }
154
155  return true;
156}
157
158void WaitAsyncWallpaperLoadFinished() {
159  TestWallpaperObserverPendingListEmpty observer(WallpaperManager::Get());
160  observer.WaitForPendingListEmpty();
161}
162
163void CreateCmdlineWallpapers(const base::ScopedTempDir& dir,
164                             scoped_ptr<base::CommandLine>* command_line) {
165  std::vector<std::string> options;
166  options.push_back(std::string("WM_Test_cmdline"));
167  const base::FilePath small_file =
168      dir.path().Append(FILE_PATH_LITERAL("small.jpg"));
169  options.push_back(std::string("--") +
170                    ash::switches::kAshDefaultWallpaperSmall + "=" +
171                    small_file.value());
172  const base::FilePath large_file =
173      dir.path().Append(FILE_PATH_LITERAL("large.jpg"));
174  options.push_back(std::string("--") +
175                    ash::switches::kAshDefaultWallpaperLarge + "=" +
176                    large_file.value());
177
178  const base::FilePath guest_small_file =
179      dir.path().Append(FILE_PATH_LITERAL("guest_small.jpg"));
180  options.push_back(std::string("--") + ash::switches::kAshGuestWallpaperSmall +
181                    "=" + guest_small_file.value());
182  const base::FilePath guest_large_file =
183      dir.path().Append(FILE_PATH_LITERAL("guest_large.jpg"));
184  options.push_back(std::string("--") + ash::switches::kAshGuestWallpaperLarge +
185                    "=" + guest_large_file.value());
186
187  ASSERT_TRUE(WriteJPEGFile(
188      small_file, kWallpaperSize, kWallpaperSize, kSmallDefaultWallpaperColor));
189  ASSERT_TRUE(WriteJPEGFile(
190      large_file, kWallpaperSize, kWallpaperSize, kLargeDefaultWallpaperColor));
191
192  ASSERT_TRUE(WriteJPEGFile(guest_small_file,
193                            kWallpaperSize,
194                            kWallpaperSize,
195                            kSmallGuestWallpaperColor));
196  ASSERT_TRUE(WriteJPEGFile(guest_large_file,
197                            kWallpaperSize,
198                            kWallpaperSize,
199                            kLargeGuestWallpaperColor));
200
201  command_line->reset(new base::CommandLine(options));
202  WallpaperManager::Get()->SetCommandLineForTesting(command_line->get());
203}
204
205}  // namespace wallpaper_manager_test_utils
206
207}  // namespace chromeos
208