| // 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 <algorithm> |
| #include <utility> |
| |
| #include "ash/public/cpp/ash_features.h" |
| #include "base/command_line.h" |
| #include "base/files/file_enumerator.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/post_task.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/wallpaper_controller_client.h" |
| #include "chrome/common/chrome_paths.h" |
| #include "chrome/grit/generated_resources.h" |
| #include "chromeos/constants/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_task_traits.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/display.h" |
| #include "ui/display/screen.h" |
| #include "ui/strings/grit/app_locale_settings.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 get_current_wallpaper_thumbnail = |
| wallpaper_private::GetCurrentWallpaperThumbnail; |
| namespace get_surprise_me_image = wallpaper_private::GetSurpriseMeImage; |
| |
| namespace { |
| |
| // The time and retry limit to re-check the profile sync service status. The |
| // sync extension function can get the correct value of the "syncThemes" user |
| // preference only after the profile sync service has been configured. |
| constexpr base::TimeDelta kRetryDelay = base::TimeDelta::FromSeconds(10); |
| constexpr int kRetryLimit = 3; |
| |
| constexpr char kSyncThemes[] = "syncThemes"; |
| |
| constexpr char kPngFilePattern[] = "*.[pP][nN][gG]"; |
| constexpr char kJpgFilePattern[] = "*.[jJ][pP][gG]"; |
| constexpr char kJpegFilePattern[] = "*.[jJ][pP][eE][gG]"; |
| |
| bool IsOEMDefaultWallpaper() { |
| return base::CommandLine::ForCurrentProcess()->HasSwitch( |
| chromeos::switches::kDefaultWallpaperIsOem); |
| } |
| |
| // 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. |
| 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<uint8_t>& data) { |
| base::FilePath data_dir; |
| CHECK(base::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, reinterpret_cast<const char*>(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", |
| IDS_WALLPAPER_MANAGER_MY_IMAGES_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_NETWORK_ERROR); |
| SET_STRING("downloadFailed", IDS_WALLPAPER_MANAGER_IMAGE_ERROR); |
| 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", IDS_WALLPAPER_MANAGER_DAILY_REFRESH_LABEL); |
| SET_STRING("learnMore", IDS_LEARN_MORE); |
| SET_STRING("currentWallpaperSetByMessage", |
| IDS_CURRENT_WALLPAPER_SET_BY_MESSAGE); |
| SET_STRING("currentlySetLabel", IDS_WALLPAPER_MANAGER_CURRENTLY_SET_LABEL); |
| SET_STRING("confirmPreviewLabel", |
| IDS_WALLPAPER_MANAGER_CONFIRM_PREVIEW_WALLPAPER_LABEL); |
| SET_STRING("setSuccessfullyMessage", |
| IDS_WALLPAPER_MANAGER_SET_SUCCESSFULLY_MESSAGE); |
| SET_STRING("defaultWallpaperLabel", IDS_DEFAULT_WALLPAPER_ACCESSIBLE_LABEL); |
| #undef SET_STRING |
| |
| const std::string& app_locale = g_browser_process->GetApplicationLocale(); |
| webui::SetLoadTimeDataDefaults(app_locale, dict.get()); |
| |
| dict->SetBoolean("isOEMDefaultWallpaper", IsOEMDefaultWallpaper()); |
| dict->SetString("canceledWallpaper", |
| wallpaper_api_util::kCancelWallpaperMessage); |
| dict->SetString("highResolutionSuffix", GetBackdropWallpaperSuffix()); |
| |
| WallpaperControllerClient::Get()->GetActiveUserWallpaperInfo(base::BindOnce( |
| &WallpaperPrivateGetStringsFunction::OnWallpaperInfoReturned, this, |
| std::move(dict))); |
| return RespondLater(); |
| } |
| |
| void WallpaperPrivateGetStringsFunction::OnWallpaperInfoReturned( |
| std::unique_ptr<base::DictionaryValue> dict, |
| const std::string& location, |
| ash::WallpaperLayout layout) { |
| dict->SetString("currentWallpaper", location); |
| dict->SetString("currentWallpaperLayout", |
| wallpaper_api_util::GetLayoutString(layout)); |
| Respond(OneArgument(std::move(dict))); |
| } |
| |
| ExtensionFunction::ResponseAction |
| WallpaperPrivateGetSyncSettingFunction::Run() { |
| base::PostTaskWithTraits( |
| FROM_HERE, {BrowserThread::UI}, |
| base::BindOnce(&WallpaperPrivateGetSyncSettingFunction:: |
| CheckProfileSyncServiceStatus, |
| this)); |
| return RespondLater(); |
| } |
| |
| void WallpaperPrivateGetSyncSettingFunction::CheckProfileSyncServiceStatus() { |
| auto dict = std::make_unique<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(kSyncThemes, true); |
| Respond(OneArgument(std::move(dict))); |
| return; |
| } |
| |
| Profile* profile = Profile::FromBrowserContext(browser_context()); |
| browser_sync::ProfileSyncService* sync_service = |
| ProfileSyncServiceFactory::GetForProfile(profile); |
| if (!sync_service || !sync_service->CanSyncFeatureStart()) { |
| // Sync as a whole is disabled. |
| dict->SetBoolean(kSyncThemes, false); |
| Respond(OneArgument(std::move(dict))); |
| return; |
| } |
| |
| if (sync_service->GetUserSettings()->IsFirstSetupComplete()) { |
| // Sync is set up. Report whether the user has chosen to sync themes. |
| dict->SetBoolean(kSyncThemes, |
| sync_service->GetUserSettings()->GetChosenDataTypes().Has( |
| syncer::THEMES)); |
| Respond(OneArgument(std::move(dict))); |
| return; |
| } |
| |
| // The user hasn't finished setting up sync, so we don't know whether they'll |
| // want to sync themes. Try again in a bit. |
| // TODO(xdai): It would be cleaner to implement a SyncServiceObserver and wait |
| // for OnStateChanged() instead of polling. |
| retry_number_++; |
| base::PostDelayedTaskWithTraits( |
| FROM_HERE, {BrowserThread::UI}, |
| base::BindOnce(&WallpaperPrivateGetSyncSettingFunction:: |
| CheckProfileSyncServiceStatus, |
| this), |
| retry_number_ * kRetryDelay); |
| } |
| |
| WallpaperPrivateSetWallpaperIfExistsFunction:: |
| WallpaperPrivateSetWallpaperIfExistsFunction() {} |
| |
| WallpaperPrivateSetWallpaperIfExistsFunction:: |
| ~WallpaperPrivateSetWallpaperIfExistsFunction() {} |
| |
| ExtensionFunction::ResponseAction |
| WallpaperPrivateSetWallpaperIfExistsFunction::Run() { |
| std::unique_ptr< |
| extensions::api::wallpaper_private::SetWallpaperIfExists::Params> |
| params = set_wallpaper_if_exists::Params::Create(*args_); |
| EXTENSION_FUNCTION_VALIDATE(params); |
| |
| WallpaperControllerClient::Get()->SetOnlineWallpaperIfExists( |
| GetUserFromBrowserContext(browser_context())->GetAccountId(), params->url, |
| wallpaper_api_util::GetLayoutEnum( |
| wallpaper_base::ToString(params->layout)), |
| params->preview_mode, |
| base::BindOnce(&WallpaperPrivateSetWallpaperIfExistsFunction:: |
| OnSetOnlineWallpaperIfExistsCallback, |
| this)); |
| return RespondLater(); |
| } |
| |
| void WallpaperPrivateSetWallpaperIfExistsFunction:: |
| OnSetOnlineWallpaperIfExistsCallback(bool file_exists) { |
| if (file_exists) { |
| Respond(OneArgument(std::make_unique<base::Value>(true))); |
| } else { |
| auto args = std::make_unique<base::ListValue>(); |
| // TODO(crbug.com/830212): Do not send arguments when the function fails. |
| // Call sites should inspect chrome.runtime.lastError instead. |
| args->AppendBoolean(false); |
| Respond(ErrorWithArguments( |
| std::move(args), "The wallpaper doesn't exist in local file system.")); |
| } |
| } |
| |
| WallpaperPrivateSetWallpaperFunction::WallpaperPrivateSetWallpaperFunction() { |
| } |
| |
| WallpaperPrivateSetWallpaperFunction::~WallpaperPrivateSetWallpaperFunction() { |
| } |
| |
| ExtensionFunction::ResponseAction WallpaperPrivateSetWallpaperFunction::Run() { |
| std::unique_ptr<extensions::api::wallpaper_private::SetWallpaper::Params> |
| params = set_wallpaper::Params::Create(*args_); |
| EXTENSION_FUNCTION_VALIDATE(params); |
| |
| WallpaperControllerClient::Get()->SetOnlineWallpaperFromData( |
| GetUserFromBrowserContext(browser_context())->GetAccountId(), |
| std::string(params->wallpaper.begin(), params->wallpaper.end()), |
| params->url, |
| wallpaper_api_util::GetLayoutEnum( |
| wallpaper_base::ToString(params->layout)), |
| params->preview_mode, |
| base::BindOnce( |
| &WallpaperPrivateSetWallpaperFunction::OnSetWallpaperCallback, this)); |
| return RespondLater(); |
| } |
| |
| void WallpaperPrivateSetWallpaperFunction::OnSetWallpaperCallback( |
| bool success) { |
| if (!success) { |
| Respond(Error("Failed to set wallpaper.")); |
| return; |
| } |
| |
| 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); |
| |
| const std::string file_name = |
| base::FilePath(params->file_name).BaseName().value(); |
| WallpaperControllerClient::Get()->SetCustomWallpaper( |
| account_id_, wallpaper_files_id_, 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(base::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()) { |
| base::PostTaskWithTraits( |
| FROM_HERE, {BrowserThread::UI}, |
| base::BindOnce(&WallpaperPrivateGetThumbnailFunction::FileNotLoaded, |
| this)); |
| } else { |
| base::PostTaskWithTraits( |
| FROM_HERE, {BrowserThread::UI}, |
| base::BindOnce(&WallpaperPrivateGetThumbnailFunction::FileLoaded, |
| this, data)); |
| } |
| } else { |
| base::PostTaskWithTraits( |
| FROM_HERE, {BrowserThread::UI}, |
| 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<uint8_t>& data, |
| const std::string& file_name) { |
| WallpaperFunctionBase::AssertCalledOnWallpaperSequence( |
| WallpaperFunctionBase::GetNonBlockingTaskRunner()); |
| if (SaveData(chrome::DIR_CHROMEOS_WALLPAPER_THUMBNAILS, file_name, data)) { |
| base::PostTaskWithTraits( |
| FROM_HERE, {BrowserThread::UI}, |
| base::BindOnce(&WallpaperPrivateSaveThumbnailFunction::Success, this)); |
| } else { |
| base::PostTaskWithTraits( |
| FROM_HERE, {BrowserThread::UI}, |
| base::BindOnce(&WallpaperPrivateSaveThumbnailFunction::Failure, this, |
| file_name)); |
| } |
| } |
| |
| WallpaperPrivateGetOfflineWallpaperListFunction:: |
| WallpaperPrivateGetOfflineWallpaperListFunction() { |
| } |
| |
| WallpaperPrivateGetOfflineWallpaperListFunction:: |
| ~WallpaperPrivateGetOfflineWallpaperListFunction() { |
| } |
| |
| ExtensionFunction::ResponseAction |
| WallpaperPrivateGetOfflineWallpaperListFunction::Run() { |
| WallpaperControllerClient::Get()->GetOfflineWallpaperList( |
| base::BindOnce(&WallpaperPrivateGetOfflineWallpaperListFunction:: |
| OnOfflineWallpaperListReturned, |
| this)); |
| return RespondLater(); |
| } |
| |
| void WallpaperPrivateGetOfflineWallpaperListFunction:: |
| OnOfflineWallpaperListReturned(const std::vector<std::string>& url_list) { |
| auto results = std::make_unique<base::ListValue>(); |
| results->AppendStrings(url_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::GetMyFilesFolderForProfile( |
| 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<uint8_t>(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()); |
| } |
| |
| WallpaperPrivateGetCurrentWallpaperThumbnailFunction:: |
| WallpaperPrivateGetCurrentWallpaperThumbnailFunction() = default; |
| |
| WallpaperPrivateGetCurrentWallpaperThumbnailFunction:: |
| ~WallpaperPrivateGetCurrentWallpaperThumbnailFunction() = default; |
| |
| ExtensionFunction::ResponseAction |
| WallpaperPrivateGetCurrentWallpaperThumbnailFunction::Run() { |
| std::unique_ptr<get_current_wallpaper_thumbnail::Params> params( |
| get_current_wallpaper_thumbnail::Params::Create(*args_)); |
| EXTENSION_FUNCTION_VALIDATE(params); |
| |
| WallpaperControllerClient::Get()->GetWallpaperImage(base::BindOnce( |
| &WallpaperPrivateGetCurrentWallpaperThumbnailFunction:: |
| OnWallpaperImageReturned, |
| this, gfx::Size(params->thumbnail_width, params->thumbnail_height))); |
| return RespondLater(); |
| } |
| |
| void WallpaperPrivateGetCurrentWallpaperThumbnailFunction:: |
| OnWallpaperImageReturned(const gfx::Size& thumbnail_size, |
| const gfx::ImageSkia& image) { |
| image.EnsureRepsForSupportedScales(); |
| scoped_refptr<base::RefCountedBytes> thumbnail_data; |
| GenerateThumbnail(image, thumbnail_size, &thumbnail_data); |
| Respond(OneArgument(std::make_unique<Value>( |
| Value::BlobStorage(thumbnail_data->front(), |
| thumbnail_data->front() + thumbnail_data->size())))); |
| } |
| |
| void WallpaperPrivateGetCurrentWallpaperThumbnailFunction::OnWallpaperDecoded( |
| const gfx::ImageSkia& wallpaper) {} |
| |
| WallpaperPrivateGetSurpriseMeImageFunction:: |
| WallpaperPrivateGetSurpriseMeImageFunction() = default; |
| |
| WallpaperPrivateGetSurpriseMeImageFunction:: |
| ~WallpaperPrivateGetSurpriseMeImageFunction() = default; |
| |
| ExtensionFunction::ResponseAction |
| WallpaperPrivateGetSurpriseMeImageFunction::Run() { |
| std::unique_ptr<get_surprise_me_image::Params> params( |
| get_surprise_me_image::Params::Create(*args_)); |
| EXTENSION_FUNCTION_VALIDATE(params); |
| |
| surprise_me_image_fetcher_ = |
| std::make_unique<backdrop_wallpaper_handlers::SurpriseMeImageFetcher>( |
| params->collection_id, |
| params->resume_token ? *params->resume_token : std::string()); |
| surprise_me_image_fetcher_->Start(base::BindOnce( |
| &WallpaperPrivateGetSurpriseMeImageFunction::OnSurpriseMeImageFetched, |
| this)); |
| return RespondLater(); |
| } |
| |
| void WallpaperPrivateGetSurpriseMeImageFunction::OnSurpriseMeImageFetched( |
| bool success, |
| const extensions::api::wallpaper_private::ImageInfo& image_info, |
| const std::string& next_resume_token) { |
| if (!success) { |
| Respond(Error("Image not available.")); |
| return; |
| } |
| Respond(TwoArguments(image_info.ToValue(), |
| std::make_unique<Value>(next_resume_token))); |
| } |