blob: f9008968f396ed77ba5e09d413e37e69bbf5de89 [file] [log] [blame]
// 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 <vector>
#include "ash/desktop_background/desktop_background_controller.h"
#include "ash/shell.h"
#include "base/command_line.h"
#include "base/files/scoped_temp_dir.h"
#include "base/run_loop.h"
#include "base/time/time.h"
#include "chrome/browser/chromeos/customization_document.h"
#include "chrome/browser/chromeos/customization_wallpaper_downloader.h"
#include "chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.h"
#include "chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager_test_utils.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chromeos/chromeos_switches.h"
#include "components/google/core/browser/google_url_tracker.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_status_code.h"
#include "net/url_request/test_url_fetcher_factory.h"
#include "net/url_request/url_fetcher_impl.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace chromeos {
namespace {
const char kOEMWallpaperURL[] = "http://somedomain.com/image.png";
const char kServicesManifest[] =
"{"
" \"version\": \"1.0\","
" \"default_wallpaper\": \"http://somedomain.com/image.png\",\n"
" \"default_apps\": [\n"
" \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\n"
" \"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\"\n"
" ],\n"
" \"localized_content\": {\n"
" \"en-US\": {\n"
" \"default_apps_folder_name\": \"EN-US OEM Name\"\n"
" },\n"
" \"en\": {\n"
" \"default_apps_folder_name\": \"EN OEM Name\"\n"
" },\n"
" \"default\": {\n"
" \"default_apps_folder_name\": \"Default OEM Name\"\n"
" }\n"
" }\n"
"}";
// Expected minimal wallpaper download retry interval in milliseconds.
const int kDownloadRetryIntervalMS = 100;
class TestWallpaperObserver : public WallpaperManager::Observer {
public:
explicit TestWallpaperObserver(WallpaperManager* wallpaper_manager)
: finished_(false),
wallpaper_manager_(wallpaper_manager) {
DCHECK(wallpaper_manager_);
wallpaper_manager_->AddObserver(this);
}
virtual ~TestWallpaperObserver() {
wallpaper_manager_->RemoveObserver(this);
}
virtual void OnWallpaperAnimationFinished(const std::string&) OVERRIDE {
finished_ = true;
base::MessageLoop::current()->Quit();
}
void WaitForWallpaperAnimationFinished() {
while (!finished_)
base::RunLoop().Run();
}
private:
bool finished_;
WallpaperManager* wallpaper_manager_;
DISALLOW_COPY_AND_ASSIGN(TestWallpaperObserver);
};
} // namespace
// This is helper class for net::FakeURLFetcherFactory.
class TestWallpaperImageURLFetcherCallback {
public:
TestWallpaperImageURLFetcherCallback(
const GURL& url,
const size_t require_retries,
const std::vector<unsigned char>& jpeg_data_raw)
: url_(url),
require_retries_(require_retries),
factory_(NULL) {
jpeg_data_.resize(jpeg_data_raw.size());
std::copy(jpeg_data_raw.begin(), jpeg_data_raw.end(), jpeg_data_.begin());
}
scoped_ptr<net::FakeURLFetcher> CreateURLFetcher(
const GURL& url,
net::URLFetcherDelegate* delegate,
const std::string& response_data,
net::HttpStatusCode response_code,
net::URLRequestStatus::Status status) {
chromeos::ServicesCustomizationDocument* customization =
chromeos::ServicesCustomizationDocument::GetInstance();
customization->wallpaper_downloader_for_testing()
->set_retry_delay_for_testing(
base::TimeDelta::FromMilliseconds(kDownloadRetryIntervalMS));
attempts_.push_back(base::TimeTicks::Now());
if (attempts_.size() > 1) {
const int retry = num_attempts() - 1;
const base::TimeDelta current_delay =
customization->wallpaper_downloader_for_testing()
->retry_current_delay_for_testing();
const double base_interval = base::TimeDelta::FromMilliseconds(
kDownloadRetryIntervalMS).InSecondsF();
EXPECT_GE(current_delay,
base::TimeDelta::FromSecondsD(base_interval * retry * retry))
<< "Retry too fast. Actual interval " << current_delay.InSecondsF()
<< " seconds, but expected at least " << base_interval
<< " * (retry=" << retry
<< " * retry)= " << base_interval * retry * retry << " seconds.";
}
if (attempts_.size() > require_retries_) {
response_code = net::HTTP_OK;
status = net::URLRequestStatus::SUCCESS;
factory_->SetFakeResponse(url, response_data, response_code, status);
}
scoped_ptr<net::FakeURLFetcher> fetcher(new net::FakeURLFetcher(
url, delegate, response_data, response_code, status));
scoped_refptr<net::HttpResponseHeaders> download_headers =
new net::HttpResponseHeaders(std::string());
download_headers->AddHeader("Content-Type: image/jpeg");
fetcher->set_response_headers(download_headers);
return fetcher.Pass();
}
void Initialize(net::FakeURLFetcherFactory* factory) {
factory_ = factory;
factory_->SetFakeResponse(url_,
jpeg_data_,
net::HTTP_INTERNAL_SERVER_ERROR,
net::URLRequestStatus::FAILED);
}
size_t num_attempts() const { return attempts_.size(); }
private:
const GURL url_;
// Respond with OK on required retry attempt.
const size_t require_retries_;
net::FakeURLFetcherFactory* factory_;
std::vector<base::TimeTicks> attempts_;
std::string jpeg_data_;
DISALLOW_COPY_AND_ASSIGN(TestWallpaperImageURLFetcherCallback);
};
// This implements fake remote source for wallpaper image.
// JPEG image is created here and served to CustomizationWallpaperDownloader
// via net::FakeURLFetcher.
class WallpaperImageFetcherFactory {
public:
WallpaperImageFetcherFactory(const GURL& url,
int width,
int height,
SkColor color,
const size_t require_retries) {
// ASSERT_TRUE() cannot be directly used in constructor.
Initialize(url, width, height, color, require_retries);
}
~WallpaperImageFetcherFactory() {
fetcher_factory_.reset();
net::URLFetcherImpl::set_factory(fallback_fetcher_factory_.get());
fallback_fetcher_factory_.reset();
}
size_t num_attempts() const { return url_callback_->num_attempts(); }
private:
void Initialize(const GURL& url,
int width,
int height,
SkColor color,
const size_t require_retries) {
std::vector<unsigned char> oem_wallpaper_;
ASSERT_TRUE(wallpaper_manager_test_utils::CreateJPEGImage(
width, height, color, &oem_wallpaper_));
url_callback_.reset(new TestWallpaperImageURLFetcherCallback(
url, require_retries, oem_wallpaper_));
fallback_fetcher_factory_.reset(new net::TestURLFetcherFactory);
net::URLFetcherImpl::set_factory(NULL);
fetcher_factory_.reset(new net::FakeURLFetcherFactory(
fallback_fetcher_factory_.get(),
base::Bind(&TestWallpaperImageURLFetcherCallback::CreateURLFetcher,
base::Unretained(url_callback_.get()))));
url_callback_->Initialize(fetcher_factory_.get());
}
scoped_ptr<TestWallpaperImageURLFetcherCallback> url_callback_;
// Use a test factory as a fallback so we don't have to deal with other
// requests.
scoped_ptr<net::TestURLFetcherFactory> fallback_fetcher_factory_;
scoped_ptr<net::FakeURLFetcherFactory> fetcher_factory_;
DISALLOW_COPY_AND_ASSIGN(WallpaperImageFetcherFactory);
};
class CustomizationWallpaperDownloaderBrowserTest
: public InProcessBrowserTest {
public:
CustomizationWallpaperDownloaderBrowserTest()
: controller_(NULL),
local_state_(NULL) {
}
virtual ~CustomizationWallpaperDownloaderBrowserTest() {}
virtual void SetUpOnMainThread() OVERRIDE {
controller_ = ash::Shell::GetInstance()->desktop_background_controller();
local_state_ = g_browser_process->local_state();
}
virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
command_line->AppendSwitch(chromeos::switches::kLoginManager);
command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile, "user");
}
virtual void TearDownOnMainThread() OVERRIDE { controller_ = NULL; }
protected:
void CreateCmdlineWallpapers() {
cmdline_wallpaper_dir_.reset(new base::ScopedTempDir);
ASSERT_TRUE(cmdline_wallpaper_dir_->CreateUniqueTempDir());
wallpaper_manager_test_utils::CreateCmdlineWallpapers(
*cmdline_wallpaper_dir_, &wallpaper_manager_command_line_);
}
ash::DesktopBackgroundController* controller_;
PrefService* local_state_;
scoped_ptr<base::CommandLine> wallpaper_manager_command_line_;
// Directory created by CreateCmdlineWallpapersAndSetFlags() to store default
// wallpaper images.
scoped_ptr<base::ScopedTempDir> cmdline_wallpaper_dir_;
private:
DISALLOW_COPY_AND_ASSIGN(CustomizationWallpaperDownloaderBrowserTest);
};
IN_PROC_BROWSER_TEST_F(CustomizationWallpaperDownloaderBrowserTest,
OEMWallpaperIsPresent) {
CreateCmdlineWallpapers();
WallpaperManager::Get()->SetDefaultWallpaperNow(std::string());
wallpaper_manager_test_utils::WaitAsyncWallpaperLoadFinished();
EXPECT_TRUE(wallpaper_manager_test_utils::ImageIsNearColor(
controller_->GetWallpaper(),
wallpaper_manager_test_utils::kSmallDefaultWallpaperColor));
WallpaperImageFetcherFactory url_factory(
GURL(kOEMWallpaperURL),
wallpaper_manager_test_utils::kWallpaperSize,
wallpaper_manager_test_utils::kWallpaperSize,
wallpaper_manager_test_utils::kCustomWallpaperColor,
0 /* require_retries */);
TestWallpaperObserver observer(WallpaperManager::Get());
chromeos::ServicesCustomizationDocument* customization =
chromeos::ServicesCustomizationDocument::GetInstance();
EXPECT_TRUE(
customization->LoadManifestFromString(std::string(kServicesManifest)));
observer.WaitForWallpaperAnimationFinished();
EXPECT_TRUE(wallpaper_manager_test_utils::ImageIsNearColor(
controller_->GetWallpaper(),
wallpaper_manager_test_utils::kCustomWallpaperColor));
EXPECT_EQ(1U, url_factory.num_attempts());
}
IN_PROC_BROWSER_TEST_F(CustomizationWallpaperDownloaderBrowserTest,
OEMWallpaperRetryFetch) {
CreateCmdlineWallpapers();
WallpaperManager::Get()->SetDefaultWallpaperNow(std::string());
wallpaper_manager_test_utils::WaitAsyncWallpaperLoadFinished();
EXPECT_TRUE(wallpaper_manager_test_utils::ImageIsNearColor(
controller_->GetWallpaper(),
wallpaper_manager_test_utils::kSmallDefaultWallpaperColor));
WallpaperImageFetcherFactory url_factory(
GURL(kOEMWallpaperURL),
wallpaper_manager_test_utils::kWallpaperSize,
wallpaper_manager_test_utils::kWallpaperSize,
wallpaper_manager_test_utils::kCustomWallpaperColor,
1 /* require_retries */);
TestWallpaperObserver observer(WallpaperManager::Get());
chromeos::ServicesCustomizationDocument* customization =
chromeos::ServicesCustomizationDocument::GetInstance();
EXPECT_TRUE(
customization->LoadManifestFromString(std::string(kServicesManifest)));
observer.WaitForWallpaperAnimationFinished();
EXPECT_TRUE(wallpaper_manager_test_utils::ImageIsNearColor(
controller_->GetWallpaper(),
wallpaper_manager_test_utils::kCustomWallpaperColor));
EXPECT_EQ(2U, url_factory.num_attempts());
}
} // namespace chromeos