blob: 6a18350c354ff750a83d909cbabf0fe46fa57b0b [file] [log] [blame]
// Copyright (c) 2013 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/extensions/wallpaper_private_api.h"
#include <map>
#include <memory>
#include <set>
#include <string>
#include <utility>
#include <vector>
#include "ash/wallpaper/wallpaper_controller.h"
#include "base/command_line.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_util.h"
#include "base/macros.h"
#include "base/memory/ref_counted_memory.h"
#include "base/metrics/histogram_macros.h"
#include "base/path_service.h"
#include "base/sequenced_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/task_runner_util.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/extensions/backdrop_wallpaper_handlers/backdrop_wallpaper_handlers.h"
#include "chrome/browser/chromeos/file_manager/path_util.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/sync/profile_sync_service_factory.h"
#include "chrome/browser/ui/ash/ash_util.h"
#include "chrome/browser/ui/ash/wallpaper_controller_client.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/grit/generated_resources.h"
#include "chromeos/chromeos_switches.h"
#include "components/browser_sync/profile_sync_service.h"
#include "components/strings/grit/components_strings.h"
#include "components/user_manager/user.h"
#include "components/user_manager/user_manager.h"
#include "content/public/browser/browser_thread.h"
#include "extensions/browser/event_router.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/webui/web_ui_util.h"
#include "ui/display/screen.h"
#include "ui/strings/grit/app_locale_settings.h"
#include "url/gurl.h"
using base::Value;
using content::BrowserThread;
namespace wallpaper_base = extensions::api::wallpaper;
namespace wallpaper_private = extensions::api::wallpaper_private;
namespace set_wallpaper_if_exists = wallpaper_private::SetWallpaperIfExists;
namespace set_wallpaper = wallpaper_private::SetWallpaper;
namespace set_custom_wallpaper = wallpaper_private::SetCustomWallpaper;
namespace set_custom_wallpaper_layout =
wallpaper_private::SetCustomWallpaperLayout;
namespace get_thumbnail = wallpaper_private::GetThumbnail;
namespace save_thumbnail = wallpaper_private::SaveThumbnail;
namespace get_offline_wallpaper_list =
wallpaper_private::GetOfflineWallpaperList;
namespace record_wallpaper_uma = wallpaper_private::RecordWallpaperUMA;
namespace get_collections_info = wallpaper_private::GetCollectionsInfo;
namespace get_images_info = wallpaper_private::GetImagesInfo;
namespace get_local_image_paths = wallpaper_private::GetLocalImagePaths;
namespace get_local_image_data = wallpaper_private::GetLocalImageData;
namespace {
// The time in seconds and retry limit to re-check the profile sync service
// status. Only after the profile sync service has been configured, we can get
// the correct value of the user sync preference of "syncThemes".
constexpr int kRetryDelay = 10;
constexpr int kRetryLimit = 3;
constexpr char kPngFilePattern[] = "*.[pP][nN][gG]";
constexpr char kJpgFilePattern[] = "*.[jJ][pP][gG]";
constexpr char kJpegFilePattern[] = "*.[jJ][pP][eE][gG]";
// The url suffix used by the old wallpaper picker.
constexpr char kHighResolutionSuffix[] = "_high_resolution.jpg";
#if defined(GOOGLE_CHROME_BUILD)
const char kWallpaperManifestBaseURL[] =
"https://storage.googleapis.com/chromeos-wallpaper-public/manifest_";
#endif
bool IsOEMDefaultWallpaper() {
return base::CommandLine::ForCurrentProcess()->HasSwitch(
chromeos::switches::kDefaultWallpaperIsOem);
}
bool IsUsingNewWallpaperPicker() {
return base::CommandLine::ForCurrentProcess()->HasSwitch(
chromeos::switches::kNewWallpaperPicker);
}
// Returns a suffix to be appended to the base url of Backdrop wallpapers.
std::string GetBackdropWallpaperSuffix() {
// FIFE url is used for Backdrop wallpapers and the desired image size should
// be specified. Currently we are using two times the display size. This is
// determined by trial and error and is subject to change.
const gfx::Size& display_size =
display::Screen::GetScreen()->GetPrimaryDisplay().size();
return "=w" + std::to_string(
2 * std::max(display_size.width(), display_size.height()));
}
// Saves |data| as |file_name| to directory with |key|. Return false if the
// directory can not be found/created or failed to write file.
bool SaveData(int key,
const std::string& file_name,
const std::vector<char>& data) {
base::FilePath data_dir;
CHECK(PathService::Get(key, &data_dir));
if (!base::DirectoryExists(data_dir) &&
!base::CreateDirectory(data_dir)) {
return false;
}
base::FilePath file_path = data_dir.Append(file_name);
return base::PathExists(file_path) ||
base::WriteFile(file_path, data.data(), data.size()) != -1;
}
// Gets |file_name| from directory with |key|. Return false if the directory can
// not be found or failed to read file to string |data|. Note if the |file_name|
// can not be found in the directory, return true with empty |data|. It is
// expected that we may try to access file which did not saved yet.
bool GetData(const base::FilePath& path, std::string* data) {
base::FilePath data_dir = path.DirName();
if (!base::DirectoryExists(data_dir) &&
!base::CreateDirectory(data_dir))
return false;
return !base::PathExists(path) ||
base::ReadFileToString(path, data);
}
// Gets the |User| for a given |BrowserContext|. The function will only return
// valid objects.
const user_manager::User* GetUserFromBrowserContext(
content::BrowserContext* context) {
Profile* profile = Profile::FromBrowserContext(context);
DCHECK(profile);
const user_manager::User* user =
chromeos::ProfileHelper::Get()->GetUserByProfile(profile);
DCHECK(user);
return user;
}
ash::WallpaperType getWallpaperType(wallpaper_private::WallpaperSource source) {
switch (source) {
case wallpaper_private::WALLPAPER_SOURCE_ONLINE:
return ash::ONLINE;
case wallpaper_private::WALLPAPER_SOURCE_DAILY:
return ash::DAILY;
case wallpaper_private::WALLPAPER_SOURCE_CUSTOM:
return ash::CUSTOMIZED;
case wallpaper_private::WALLPAPER_SOURCE_OEM:
return ash::DEFAULT;
case wallpaper_private::WALLPAPER_SOURCE_THIRDPARTY:
return ash::THIRDPARTY;
default:
return ash::ONLINE;
}
}
// Helper function to get the list of image paths under |path| that match
// |pattern|.
void EnumerateImages(const base::FilePath& path,
const std::string& pattern,
std::vector<std::string>* result_out) {
base::FileEnumerator image_enum(
path, true /* recursive */, base::FileEnumerator::FILES,
FILE_PATH_LITERAL(pattern),
base::FileEnumerator::FolderSearchPolicy::ALL);
for (base::FilePath image_path = image_enum.Next(); !image_path.empty();
image_path = image_enum.Next()) {
result_out->emplace_back(image_path.value());
}
}
// Recursively retrieves the paths of the image files under |path|.
std::vector<std::string> GetImagePaths(const base::FilePath& path) {
WallpaperFunctionBase::AssertCalledOnWallpaperSequence(
WallpaperFunctionBase::GetNonBlockingTaskRunner());
// TODO(crbug.com/810575): Add metrics on the number of files retrieved, and
// support getting paths incrementally in case the user has a large number of
// local images.
std::vector<std::string> image_paths;
EnumerateImages(path, kPngFilePattern, &image_paths);
EnumerateImages(path, kJpgFilePattern, &image_paths);
EnumerateImages(path, kJpegFilePattern, &image_paths);
return image_paths;
}
} // namespace
ExtensionFunction::ResponseAction WallpaperPrivateGetStringsFunction::Run() {
std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
#define SET_STRING(id, idr) \
dict->SetString(id, l10n_util::GetStringUTF16(idr))
SET_STRING("webFontFamily", IDS_WEB_FONT_FAMILY);
SET_STRING("webFontSize", IDS_WEB_FONT_SIZE);
SET_STRING("allCategoryLabel", IDS_WALLPAPER_MANAGER_ALL_CATEGORY_LABEL);
SET_STRING("deleteCommandLabel", IDS_WALLPAPER_MANAGER_DELETE_COMMAND_LABEL);
SET_STRING("customCategoryLabel",
IsUsingNewWallpaperPicker()
? IDS_WALLPAPER_MANAGER_MY_PHOTOS_CATEGORY_LABEL
: IDS_WALLPAPER_MANAGER_CUSTOM_CATEGORY_LABEL);
SET_STRING("selectCustomLabel",
IDS_WALLPAPER_MANAGER_SELECT_CUSTOM_LABEL);
SET_STRING("positionLabel", IDS_WALLPAPER_MANAGER_POSITION_LABEL);
SET_STRING("colorLabel", IDS_WALLPAPER_MANAGER_COLOR_LABEL);
SET_STRING("refreshLabel", IDS_WALLPAPER_MANAGER_REFRESH_LABEL);
SET_STRING("exploreLabel", IDS_WALLPAPER_MANAGER_EXPLORE_LABEL);
SET_STRING("centerCroppedLayout",
IDS_WALLPAPER_MANAGER_LAYOUT_CENTER_CROPPED);
SET_STRING("centerLayout", IDS_WALLPAPER_MANAGER_LAYOUT_CENTER);
SET_STRING("stretchLayout", IDS_WALLPAPER_MANAGER_LAYOUT_STRETCH);
SET_STRING("connectionFailed", IDS_WALLPAPER_MANAGER_ACCESS_FAIL);
SET_STRING("downloadFailed", IDS_WALLPAPER_MANAGER_DOWNLOAD_FAIL);
SET_STRING("downloadCanceled", IDS_WALLPAPER_MANAGER_DOWNLOAD_CANCEL);
SET_STRING("customWallpaperWarning",
IDS_WALLPAPER_MANAGER_SHOW_CUSTOM_WALLPAPER_ON_START_WARNING);
SET_STRING("accessFileFailure", IDS_WALLPAPER_MANAGER_ACCESS_FILE_FAILURE);
SET_STRING("invalidWallpaper", IDS_WALLPAPER_MANAGER_INVALID_WALLPAPER);
SET_STRING("noImagesAvailable", IDS_WALLPAPER_MANAGER_NO_IMAGES_AVAILABLE);
SET_STRING("surpriseMeLabel", IsUsingNewWallpaperPicker()
? IDS_WALLPAPER_MANAGER_DAILY_REFRESH_LABEL
: IDS_WALLPAPER_MANAGER_SURPRISE_ME_LABEL);
SET_STRING("learnMore", IDS_LEARN_MORE);
SET_STRING("currentWallpaperSetByMessage",
IDS_CURRENT_WALLPAPER_SET_BY_MESSAGE);
#undef SET_STRING
const std::string& app_locale = g_browser_process->GetApplicationLocale();
webui::SetLoadTimeDataDefaults(app_locale, dict.get());
#if defined(GOOGLE_CHROME_BUILD)
dict->SetString("manifestBaseURL", kWallpaperManifestBaseURL);
#endif
dict->SetBoolean("isOEMDefaultWallpaper", IsOEMDefaultWallpaper());
dict->SetString("canceledWallpaper",
wallpaper_api_util::kCancelWallpaperMessage);
dict->SetBoolean("useNewWallpaperPicker", IsUsingNewWallpaperPicker());
dict->SetString("highResolutionSuffix", IsUsingNewWallpaperPicker()
? GetBackdropWallpaperSuffix()
: kHighResolutionSuffix);
WallpaperControllerClient::Get()->GetActiveUserWallpaperLocation(
base::BindOnce(
&WallpaperPrivateGetStringsFunction::OnWallpaperLocationReturned,
this, std::move(dict)));
return RespondLater();
}
void WallpaperPrivateGetStringsFunction::OnWallpaperLocationReturned(
std::unique_ptr<base::DictionaryValue> dict,
const std::string& location) {
dict->SetString("currentWallpaper", location);
Respond(OneArgument(std::move(dict)));
}
ExtensionFunction::ResponseAction
WallpaperPrivateGetSyncSettingFunction::Run() {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::BindOnce(&WallpaperPrivateGetSyncSettingFunction::
CheckProfileSyncServiceStatus,
this));
return RespondLater();
}
void WallpaperPrivateGetSyncSettingFunction::CheckProfileSyncServiceStatus() {
std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
if (retry_number > kRetryLimit) {
// It's most likely that the wallpaper synchronization is enabled (It's
// enabled by default so unless the user disables it explicitly it remains
// enabled).
dict->SetBoolean("syncThemes", true);
Respond(OneArgument(std::move(dict)));
return;
}
Profile* profile = Profile::FromBrowserContext(browser_context());
browser_sync::ProfileSyncService* sync_service =
ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile);
if (!sync_service) {
dict->SetBoolean("syncThemes", false);
Respond(OneArgument(std::move(dict)));
return;
}
if (sync_service->IsSyncActive() && sync_service->ConfigurationDone()) {
dict->SetBoolean("syncThemes",
sync_service->GetActiveDataTypes().Has(syncer::THEMES));
Respond(OneArgument(std::move(dict)));
return;
}
// It's possible that the profile sync service hasn't finished configuring yet
// when we're trying to query the user preference (this seems only happen for
// the first time configuration). In this case GetActiveDataTypes() returns an
// empty set. So re-check the status later.
retry_number++;
BrowserThread::PostDelayedTask(
BrowserThread::UI, FROM_HERE,
base::BindOnce(&WallpaperPrivateGetSyncSettingFunction::
CheckProfileSyncServiceStatus,
this),
base::TimeDelta::FromSeconds(retry_number * kRetryDelay));
}
WallpaperPrivateSetWallpaperIfExistsFunction::
WallpaperPrivateSetWallpaperIfExistsFunction() {}
WallpaperPrivateSetWallpaperIfExistsFunction::
~WallpaperPrivateSetWallpaperIfExistsFunction() {}
ExtensionFunction::ResponseAction
WallpaperPrivateSetWallpaperIfExistsFunction::Run() {
params = set_wallpaper_if_exists::Params::Create(*args_);
EXTENSION_FUNCTION_VALIDATE(params);
// Gets account id from the caller, ensuring multiprofile compatibility.
const user_manager::User* user = GetUserFromBrowserContext(browser_context());
account_id_ = user->GetAccountId();
base::FilePath wallpaper_path;
base::FilePath fallback_path;
ash::WallpaperController::WallpaperResolution resolution =
ash::WallpaperController::GetAppropriateResolution();
std::string file_name = GURL(params->url).ExtractFileName();
CHECK(PathService::Get(chrome::DIR_CHROMEOS_WALLPAPERS,
&wallpaper_path));
fallback_path = wallpaper_path.Append(file_name);
if (params->layout != wallpaper_base::WALLPAPER_LAYOUT_STRETCH &&
resolution == ash::WallpaperController::WALLPAPER_RESOLUTION_SMALL) {
file_name = base::FilePath(file_name)
.InsertBeforeExtension(
ash::WallpaperController::kSmallWallpaperSuffix)
.value();
}
wallpaper_path = wallpaper_path.Append(file_name);
GetNonBlockingTaskRunner()->PostTask(
FROM_HERE, base::BindOnce(&WallpaperPrivateSetWallpaperIfExistsFunction::
ReadFileAndInitiateStartDecode,
this, wallpaper_path, fallback_path));
return RespondLater();
}
void WallpaperPrivateSetWallpaperIfExistsFunction::
ReadFileAndInitiateStartDecode(const base::FilePath& file_path,
const base::FilePath& fallback_path) {
AssertCalledOnWallpaperSequence(GetNonBlockingTaskRunner());
base::FilePath path = file_path;
if (!base::PathExists(file_path))
path = fallback_path;
std::string data;
if (base::PathExists(path) &&
base::ReadFileToString(path, &data)) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::BindOnce(
&WallpaperPrivateSetWallpaperIfExistsFunction::StartDecode, this,
std::vector<char>(data.begin(), data.end())));
return;
}
std::string error = base::StringPrintf(
"Failed to set wallpaper %s from file system.",
path.BaseName().value().c_str());
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::BindOnce(
&WallpaperPrivateSetWallpaperIfExistsFunction::OnFileNotExists, this,
error));
}
void WallpaperPrivateSetWallpaperIfExistsFunction::OnWallpaperDecoded(
const gfx::ImageSkia& image) {
// Set unsafe_wallpaper_decoder_ to null since the decoding already finished.
unsafe_wallpaper_decoder_ = nullptr;
ash::WallpaperLayout layout = wallpaper_api_util::GetLayoutEnum(
wallpaper_base::ToString(params->layout));
WallpaperControllerClient::Get()->SetOnlineWallpaper(
account_id_, image, params->url, layout, params->preview_mode);
Respond(OneArgument(std::make_unique<base::Value>(true)));
}
void WallpaperPrivateSetWallpaperIfExistsFunction::OnFileNotExists(
const std::string& error) {
auto args = std::make_unique<base::ListValue>();
args->AppendBoolean(false);
OnFailureWithArguments(std::move(args), error);
}
WallpaperPrivateSetWallpaperFunction::WallpaperPrivateSetWallpaperFunction() {
}
WallpaperPrivateSetWallpaperFunction::~WallpaperPrivateSetWallpaperFunction() {
}
ExtensionFunction::ResponseAction WallpaperPrivateSetWallpaperFunction::Run() {
params = set_wallpaper::Params::Create(*args_);
EXTENSION_FUNCTION_VALIDATE(params);
// Gets account id from the caller, ensuring multiprofile compatibility.
const user_manager::User* user = GetUserFromBrowserContext(browser_context());
account_id_ = user->GetAccountId();
StartDecode(params->wallpaper);
return RespondLater();
}
void WallpaperPrivateSetWallpaperFunction::OnWallpaperDecoded(
const gfx::ImageSkia& image) {
wallpaper_ = image;
// Set unsafe_wallpaper_decoder_ to null since the decoding already finished.
unsafe_wallpaper_decoder_ = nullptr;
GetBlockingTaskRunner()->PostTask(
FROM_HERE,
base::BindOnce(&WallpaperPrivateSetWallpaperFunction::SaveToFile, this));
}
void WallpaperPrivateSetWallpaperFunction::SaveToFile() {
AssertCalledOnWallpaperSequence(GetBlockingTaskRunner());
std::string file_name = GURL(params->url).ExtractFileName();
if (SaveData(chrome::DIR_CHROMEOS_WALLPAPERS, file_name, params->wallpaper)) {
wallpaper_.EnsureRepsForSupportedScales();
std::unique_ptr<gfx::ImageSkia> deep_copy(wallpaper_.DeepCopy());
// ImageSkia is not RefCountedThreadSafe. Use a deep copied ImageSkia if
// post to another thread.
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::BindOnce(
&WallpaperPrivateSetWallpaperFunction::SetDecodedWallpaper, this,
std::move(deep_copy)));
base::FilePath wallpaper_dir;
CHECK(PathService::Get(chrome::DIR_CHROMEOS_WALLPAPERS, &wallpaper_dir));
base::FilePath file_path =
wallpaper_dir.Append(file_name).InsertBeforeExtension(
ash::WallpaperController::kSmallWallpaperSuffix);
if (base::PathExists(file_path))
return;
// Generates and saves small resolution wallpaper. Uses CENTER_CROPPED to
// maintain the aspect ratio after resize.
ash::WallpaperController::ResizeAndSaveWallpaper(
wallpaper_, file_path, ash::WALLPAPER_LAYOUT_CENTER_CROPPED,
ash::WallpaperController::kSmallWallpaperMaxWidth,
ash::WallpaperController::kSmallWallpaperMaxHeight, nullptr);
} else {
std::string error = base::StringPrintf(
"Failed to create/write wallpaper to %s.", file_name.c_str());
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::BindOnce(&WallpaperPrivateSetWallpaperFunction::OnFailure, this,
error));
}
}
void WallpaperPrivateSetWallpaperFunction::SetDecodedWallpaper(
std::unique_ptr<gfx::ImageSkia> image) {
ash::WallpaperLayout layout = wallpaper_api_util::GetLayoutEnum(
wallpaper_base::ToString(params->layout));
WallpaperControllerClient::Get()->SetOnlineWallpaper(
account_id_, *image.get(), params->url, layout, params->preview_mode);
Respond(NoArguments());
}
WallpaperPrivateResetWallpaperFunction::
WallpaperPrivateResetWallpaperFunction() {}
WallpaperPrivateResetWallpaperFunction::
~WallpaperPrivateResetWallpaperFunction() {}
ExtensionFunction::ResponseAction
WallpaperPrivateResetWallpaperFunction::Run() {
const AccountId& account_id =
user_manager::UserManager::Get()->GetActiveUser()->GetAccountId();
WallpaperControllerClient::Get()->SetDefaultWallpaper(
account_id, true /* show_wallpaper */);
return RespondNow(NoArguments());
}
WallpaperPrivateSetCustomWallpaperFunction::
WallpaperPrivateSetCustomWallpaperFunction() {}
WallpaperPrivateSetCustomWallpaperFunction::
~WallpaperPrivateSetCustomWallpaperFunction() {}
ExtensionFunction::ResponseAction
WallpaperPrivateSetCustomWallpaperFunction::Run() {
params = set_custom_wallpaper::Params::Create(*args_);
EXTENSION_FUNCTION_VALIDATE(params);
// Gets account id from the caller, ensuring multiprofile compatibility.
const user_manager::User* user = GetUserFromBrowserContext(browser_context());
account_id_ = user->GetAccountId();
wallpaper_files_id_ =
WallpaperControllerClient::Get()->GetFilesId(account_id_);
StartDecode(params->wallpaper);
return RespondLater();
}
void WallpaperPrivateSetCustomWallpaperFunction::OnWallpaperDecoded(
const gfx::ImageSkia& image) {
ash::WallpaperLayout layout = wallpaper_api_util::GetLayoutEnum(
wallpaper_base::ToString(params->layout));
wallpaper_api_util::RecordCustomWallpaperLayout(layout);
WallpaperControllerClient::Get()->SetCustomWallpaper(
account_id_, wallpaper_files_id_, params->file_name, layout, image,
params->preview_mode);
unsafe_wallpaper_decoder_ = nullptr;
if (params->generate_thumbnail) {
image.EnsureRepsForSupportedScales();
scoped_refptr<base::RefCountedBytes> thumbnail_data;
GenerateThumbnail(
image, gfx::Size(kWallpaperThumbnailWidth, kWallpaperThumbnailHeight),
&thumbnail_data);
Respond(OneArgument(Value::CreateWithCopiedBuffer(
reinterpret_cast<const char*>(thumbnail_data->front()),
thumbnail_data->size())));
} else {
Respond(NoArguments());
}
}
WallpaperPrivateSetCustomWallpaperLayoutFunction::
WallpaperPrivateSetCustomWallpaperLayoutFunction() {}
WallpaperPrivateSetCustomWallpaperLayoutFunction::
~WallpaperPrivateSetCustomWallpaperLayoutFunction() {}
ExtensionFunction::ResponseAction
WallpaperPrivateSetCustomWallpaperLayoutFunction::Run() {
std::unique_ptr<set_custom_wallpaper_layout::Params> params(
set_custom_wallpaper_layout::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);
ash::WallpaperLayout new_layout = wallpaper_api_util::GetLayoutEnum(
wallpaper_base::ToString(params->layout));
wallpaper_api_util::RecordCustomWallpaperLayout(new_layout);
WallpaperControllerClient::Get()->UpdateCustomWallpaperLayout(
user_manager::UserManager::Get()->GetActiveUser()->GetAccountId(),
new_layout);
return RespondNow(NoArguments());
}
WallpaperPrivateMinimizeInactiveWindowsFunction::
WallpaperPrivateMinimizeInactiveWindowsFunction() {
}
WallpaperPrivateMinimizeInactiveWindowsFunction::
~WallpaperPrivateMinimizeInactiveWindowsFunction() {
}
ExtensionFunction::ResponseAction
WallpaperPrivateMinimizeInactiveWindowsFunction::Run() {
WallpaperControllerClient::Get()->MinimizeInactiveWindows(
user_manager::UserManager::Get()->GetActiveUser()->username_hash());
return RespondNow(NoArguments());
}
WallpaperPrivateRestoreMinimizedWindowsFunction::
WallpaperPrivateRestoreMinimizedWindowsFunction() {
}
WallpaperPrivateRestoreMinimizedWindowsFunction::
~WallpaperPrivateRestoreMinimizedWindowsFunction() {
}
ExtensionFunction::ResponseAction
WallpaperPrivateRestoreMinimizedWindowsFunction::Run() {
WallpaperControllerClient::Get()->RestoreMinimizedWindows(
user_manager::UserManager::Get()->GetActiveUser()->username_hash());
return RespondNow(NoArguments());
}
WallpaperPrivateGetThumbnailFunction::WallpaperPrivateGetThumbnailFunction() {
}
WallpaperPrivateGetThumbnailFunction::~WallpaperPrivateGetThumbnailFunction() {
}
ExtensionFunction::ResponseAction WallpaperPrivateGetThumbnailFunction::Run() {
std::unique_ptr<get_thumbnail::Params> params(
get_thumbnail::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);
base::FilePath thumbnail_path;
if (params->source == wallpaper_private::WALLPAPER_SOURCE_ONLINE) {
std::string file_name = GURL(params->url_or_file).ExtractFileName();
CHECK(PathService::Get(chrome::DIR_CHROMEOS_WALLPAPER_THUMBNAILS,
&thumbnail_path));
thumbnail_path = thumbnail_path.Append(file_name);
} else {
if (!IsOEMDefaultWallpaper())
return RespondNow(Error("No OEM wallpaper."));
// TODO(bshe): Small resolution wallpaper is used here as wallpaper
// thumbnail. We should either resize it or include a wallpaper thumbnail in
// addition to large and small wallpaper resolutions.
thumbnail_path = base::CommandLine::ForCurrentProcess()->GetSwitchValuePath(
chromeos::switches::kDefaultWallpaperSmall);
}
WallpaperFunctionBase::GetNonBlockingTaskRunner()->PostTask(
FROM_HERE, base::BindOnce(&WallpaperPrivateGetThumbnailFunction::Get,
this, thumbnail_path));
// WallpaperPrivateGetThumbnailFunction::Get will respond on UI thread
// asynchronously.
return RespondLater();
}
void WallpaperPrivateGetThumbnailFunction::Failure(
const std::string& file_name) {
Respond(Error(base::StringPrintf(
"Failed to access wallpaper thumbnails for %s.", file_name.c_str())));
}
void WallpaperPrivateGetThumbnailFunction::FileNotLoaded() {
// TODO(https://crbug.com/829657): This should fail instead of succeeding.
Respond(NoArguments());
}
void WallpaperPrivateGetThumbnailFunction::FileLoaded(
const std::string& data) {
Respond(
OneArgument(Value::CreateWithCopiedBuffer(data.c_str(), data.size())));
}
void WallpaperPrivateGetThumbnailFunction::Get(const base::FilePath& path) {
WallpaperFunctionBase::AssertCalledOnWallpaperSequence(
WallpaperFunctionBase::GetNonBlockingTaskRunner());
std::string data;
if (GetData(path, &data)) {
if (data.empty()) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::BindOnce(&WallpaperPrivateGetThumbnailFunction::FileNotLoaded,
this));
} else {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::BindOnce(&WallpaperPrivateGetThumbnailFunction::FileLoaded,
this, data));
}
} else {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::BindOnce(&WallpaperPrivateGetThumbnailFunction::Failure, this,
path.BaseName().value()));
}
}
WallpaperPrivateSaveThumbnailFunction::WallpaperPrivateSaveThumbnailFunction() {
}
WallpaperPrivateSaveThumbnailFunction::
~WallpaperPrivateSaveThumbnailFunction() {}
ExtensionFunction::ResponseAction WallpaperPrivateSaveThumbnailFunction::Run() {
std::unique_ptr<save_thumbnail::Params> params(
save_thumbnail::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);
WallpaperFunctionBase::GetNonBlockingTaskRunner()->PostTask(
FROM_HERE,
base::BindOnce(&WallpaperPrivateSaveThumbnailFunction::Save, this,
params->data, GURL(params->url).ExtractFileName()));
// WallpaperPrivateSaveThumbnailFunction::Save will repsond on UI thread
// asynchronously.
return RespondLater();
}
void WallpaperPrivateSaveThumbnailFunction::Failure(
const std::string& file_name) {
Respond(Error(base::StringPrintf("Failed to create/write thumbnail of %s.",
file_name.c_str())));
}
void WallpaperPrivateSaveThumbnailFunction::Success() {
Respond(NoArguments());
}
void WallpaperPrivateSaveThumbnailFunction::Save(const std::vector<char>& data,
const std::string& file_name) {
WallpaperFunctionBase::AssertCalledOnWallpaperSequence(
WallpaperFunctionBase::GetNonBlockingTaskRunner());
if (SaveData(chrome::DIR_CHROMEOS_WALLPAPER_THUMBNAILS, file_name, data)) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::BindOnce(&WallpaperPrivateSaveThumbnailFunction::Success, this));
} else {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::BindOnce(&WallpaperPrivateSaveThumbnailFunction::Failure, this,
file_name));
}
}
WallpaperPrivateGetOfflineWallpaperListFunction::
WallpaperPrivateGetOfflineWallpaperListFunction() {
}
WallpaperPrivateGetOfflineWallpaperListFunction::
~WallpaperPrivateGetOfflineWallpaperListFunction() {
}
ExtensionFunction::ResponseAction
WallpaperPrivateGetOfflineWallpaperListFunction::Run() {
WallpaperFunctionBase::GetNonBlockingTaskRunner()->PostTask(
FROM_HERE,
base::BindOnce(&WallpaperPrivateGetOfflineWallpaperListFunction::GetList,
this));
// OnComplete() responds asynchronously.
return RespondLater();
}
void WallpaperPrivateGetOfflineWallpaperListFunction::GetList() {
WallpaperFunctionBase::AssertCalledOnWallpaperSequence(
WallpaperFunctionBase::GetNonBlockingTaskRunner());
std::vector<std::string> file_list;
base::FilePath wallpaper_dir;
CHECK(PathService::Get(chrome::DIR_CHROMEOS_WALLPAPERS, &wallpaper_dir));
if (base::DirectoryExists(wallpaper_dir)) {
base::FileEnumerator files(wallpaper_dir, false,
base::FileEnumerator::FILES);
for (base::FilePath current = files.Next(); !current.empty();
current = files.Next()) {
std::string file_name = current.BaseName().RemoveExtension().value();
// Do not add file name of small resolution wallpaper to the list.
if (!base::EndsWith(file_name,
ash::WallpaperController::kSmallWallpaperSuffix,
base::CompareCase::SENSITIVE))
file_list.push_back(current.BaseName().value());
}
}
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::BindOnce(
&WallpaperPrivateGetOfflineWallpaperListFunction::OnComplete, this,
file_list));
}
void WallpaperPrivateGetOfflineWallpaperListFunction::OnComplete(
const std::vector<std::string>& file_list) {
auto results = std::make_unique<base::ListValue>();
results->AppendStrings(file_list);
Respond(OneArgument(std::move(results)));
}
ExtensionFunction::ResponseAction
WallpaperPrivateRecordWallpaperUMAFunction::Run() {
std::unique_ptr<record_wallpaper_uma::Params> params(
record_wallpaper_uma::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);
ash::WallpaperType source = getWallpaperType(params->source);
UMA_HISTOGRAM_ENUMERATION("Ash.Wallpaper.Source", source,
ash::WALLPAPER_TYPE_COUNT);
return RespondNow(NoArguments());
}
WallpaperPrivateGetCollectionsInfoFunction::
WallpaperPrivateGetCollectionsInfoFunction() = default;
WallpaperPrivateGetCollectionsInfoFunction::
~WallpaperPrivateGetCollectionsInfoFunction() = default;
ExtensionFunction::ResponseAction
WallpaperPrivateGetCollectionsInfoFunction::Run() {
collection_info_fetcher_ =
std::make_unique<backdrop_wallpaper_handlers::CollectionInfoFetcher>();
collection_info_fetcher_->Start(base::BindOnce(
&WallpaperPrivateGetCollectionsInfoFunction::OnCollectionsInfoFetched,
this));
return RespondLater();
}
void WallpaperPrivateGetCollectionsInfoFunction::OnCollectionsInfoFetched(
bool success,
const std::vector<extensions::api::wallpaper_private::CollectionInfo>&
collections_info_list) {
if (!success) {
Respond(Error("Collection names are not available."));
return;
}
Respond(ArgumentList(
get_collections_info::Results::Create(collections_info_list)));
}
WallpaperPrivateGetImagesInfoFunction::WallpaperPrivateGetImagesInfoFunction() =
default;
WallpaperPrivateGetImagesInfoFunction::
~WallpaperPrivateGetImagesInfoFunction() = default;
ExtensionFunction::ResponseAction WallpaperPrivateGetImagesInfoFunction::Run() {
std::unique_ptr<get_images_info::Params> params(
get_images_info::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);
image_info_fetcher_ =
std::make_unique<backdrop_wallpaper_handlers::ImageInfoFetcher>(
params->collection_id);
image_info_fetcher_->Start(base::BindOnce(
&WallpaperPrivateGetImagesInfoFunction::OnImagesInfoFetched, this));
return RespondLater();
}
void WallpaperPrivateGetImagesInfoFunction::OnImagesInfoFetched(
bool success,
const std::vector<extensions::api::wallpaper_private::ImageInfo>&
images_info_list) {
if (!success) {
Respond(Error("Images info is not available."));
return;
}
Respond(ArgumentList(get_images_info::Results::Create(images_info_list)));
}
WallpaperPrivateGetLocalImagePathsFunction::
WallpaperPrivateGetLocalImagePathsFunction() = default;
WallpaperPrivateGetLocalImagePathsFunction::
~WallpaperPrivateGetLocalImagePathsFunction() = default;
ExtensionFunction::ResponseAction
WallpaperPrivateGetLocalImagePathsFunction::Run() {
base::FilePath path = file_manager::util::GetDownloadsFolderForProfile(
Profile::FromBrowserContext(browser_context()));
base::PostTaskAndReplyWithResult(
WallpaperFunctionBase::GetNonBlockingTaskRunner(), FROM_HERE,
base::BindOnce(&GetImagePaths, path),
base::BindOnce(
&WallpaperPrivateGetLocalImagePathsFunction::OnGetImagePathsComplete,
this));
return RespondLater();
}
void WallpaperPrivateGetLocalImagePathsFunction::OnGetImagePathsComplete(
const std::vector<std::string>& image_paths) {
Respond(ArgumentList(get_local_image_paths::Results::Create(image_paths)));
}
WallpaperPrivateGetLocalImageDataFunction::
WallpaperPrivateGetLocalImageDataFunction() = default;
WallpaperPrivateGetLocalImageDataFunction::
~WallpaperPrivateGetLocalImageDataFunction() = default;
ExtensionFunction::ResponseAction
WallpaperPrivateGetLocalImageDataFunction::Run() {
std::unique_ptr<get_local_image_data::Params> params(
get_local_image_data::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);
// TODO(crbug.com/811564): Create file backed blob instead.
auto image_data = std::make_unique<std::string>();
std::string* image_data_ptr = image_data.get();
base::PostTaskAndReplyWithResult(
WallpaperFunctionBase::GetNonBlockingTaskRunner(), FROM_HERE,
base::BindOnce(&base::ReadFileToString,
base::FilePath(params->image_path), image_data_ptr),
base::BindOnce(
&WallpaperPrivateGetLocalImageDataFunction::OnReadImageDataComplete,
this, std::move(image_data)));
return RespondLater();
}
void WallpaperPrivateGetLocalImageDataFunction::OnReadImageDataComplete(
std::unique_ptr<std::string> image_data,
bool success) {
if (!success) {
Respond(Error("Reading image data failed."));
return;
}
Respond(ArgumentList(get_local_image_data::Results::Create(
std::vector<char>(image_data->begin(), image_data->end()))));
}
WallpaperPrivateConfirmPreviewWallpaperFunction::
WallpaperPrivateConfirmPreviewWallpaperFunction() = default;
WallpaperPrivateConfirmPreviewWallpaperFunction::
~WallpaperPrivateConfirmPreviewWallpaperFunction() = default;
ExtensionFunction::ResponseAction
WallpaperPrivateConfirmPreviewWallpaperFunction::Run() {
WallpaperControllerClient::Get()->ConfirmPreviewWallpaper();
return RespondNow(NoArguments());
}
WallpaperPrivateCancelPreviewWallpaperFunction::
WallpaperPrivateCancelPreviewWallpaperFunction() = default;
WallpaperPrivateCancelPreviewWallpaperFunction::
~WallpaperPrivateCancelPreviewWallpaperFunction() = default;
ExtensionFunction::ResponseAction
WallpaperPrivateCancelPreviewWallpaperFunction::Run() {
WallpaperControllerClient::Get()->CancelPreviewWallpaper();
return RespondNow(NoArguments());
}