File: customization_wallpaper_util.cc

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (207 lines) | stat: -rw-r--r-- 8,287 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ash/customization/customization_wallpaper_util.h"

#include "ash/public/cpp/wallpaper/wallpaper_controller.h"
#include "base/files/file_util.h"
#include "base/functional/bind.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/thread_pool.h"
#include "chrome/browser/ash/customization/customization_document.h"
#include "chrome/browser/ash/login/users/avatar/user_image_loader.h"
#include "chrome/browser/browser_process.h"
#include "chrome/common/pref_names.h"
#include "components/prefs/pref_service.h"
#include "components/user_manager/user_image/user_image.h"
#include "content/public/browser/browser_thread.h"
#include "ui/gfx/codec/jpeg_codec.h"
#include "ui/gfx/image/image_skia_operations.h"
#include "url/gurl.h"

namespace ash {

namespace {

// File path suffixes of resized wallpapers.
constexpr char kSmallWallpaperSuffix[] = "_small";
constexpr char kLargeWallpaperSuffix[] = "_large";

// Returns true if saving the resized |image| to |file_path| succeeded.
bool SaveResizedWallpaper(const gfx::ImageSkia& image,
                          const gfx::Size& size,
                          const base::FilePath& file_path) {
  gfx::ImageSkia resized_image = gfx::ImageSkiaOperations::CreateResizedImage(
      image, skia::ImageOperations::RESIZE_LANCZOS3, size);

  std::optional<std::vector<uint8_t>> image_data =
      gfx::JPEGCodec::Encode(*resized_image.bitmap(), /*quality=*/90);
  if (!image_data) {
    return false;
  }

  return base::WriteFile(file_path, image_data.value());
}

// Returns true if both file paths exist.
bool CheckCustomizedWallpaperFilesExist(
    const base::FilePath& resized_small_path,
    const base::FilePath& resized_large_path) {
  return base::PathExists(resized_small_path) &&
         base::PathExists(resized_large_path);
}

// Resizes and saves the customized default wallpapers.
bool ResizeAndSaveCustomizedDefaultWallpaper(
    gfx::ImageSkia image,
    const base::FilePath& resized_small_path,
    const base::FilePath& resized_large_path) {
  return SaveResizedWallpaper(
             image,
             gfx::Size(kSmallWallpaperMaxWidth, kSmallWallpaperMaxHeight),
             resized_small_path) &&
         SaveResizedWallpaper(
             image,
             gfx::Size(kLargeWallpaperMaxWidth, kLargeWallpaperMaxHeight),
             resized_large_path);
}

// Checks the result of |ResizeAndSaveCustomizedDefaultWallpaper| and sends
// the paths to apply the wallpapers.
void OnCustomizedDefaultWallpaperResizedAndSaved(
    const GURL& wallpaper_url,
    const base::FilePath& resized_small_path,
    const base::FilePath& resized_large_path,
    bool success) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  if (!success) {
    LOG(WARNING) << "Failed to save resized customized default wallpaper";
    return;
  }

  g_browser_process->local_state()->SetString(
      prefs::kCustomizationDefaultWallpaperURL, wallpaper_url.spec());
  ash::WallpaperController::Get()->SetCustomizedDefaultWallpaperPaths(
      resized_small_path, resized_large_path);
  VLOG(1) << "Customized default wallpaper applied.";
}

// Initiates resizing and saving the customized default wallpapers if decoding
// is successful.
void OnCustomizedDefaultWallpaperDecoded(
    const GURL& wallpaper_url,
    const base::FilePath& resized_small_path,
    const base::FilePath& resized_large_path,
    std::unique_ptr<user_manager::UserImage> wallpaper) {
  // Empty image indicates decode failure.
  if (wallpaper->image().isNull()) {
    LOG(WARNING) << "Failed to decode customized wallpaper.";
    return;
  }

  wallpaper->image().EnsureRepsForSupportedScales();

  scoped_refptr<base::SequencedTaskRunner> task_runner =
      base::ThreadPool::CreateSequencedTaskRunner(
          {base::MayBlock(), base::TaskPriority::USER_BLOCKING,
           base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN});
  task_runner->PostTaskAndReplyWithResult(
      FROM_HERE,
      base::BindOnce(&ResizeAndSaveCustomizedDefaultWallpaper,
                     wallpaper->image().DeepCopy(), resized_small_path,
                     resized_large_path),
      base::BindOnce(&OnCustomizedDefaultWallpaperResizedAndSaved,
                     wallpaper_url, resized_small_path, resized_large_path));
}

// If |both_sizes_exist| is false or the url doesn't match the current value,
// initiates image decoding, otherwise directly sends the paths.
void SetCustomizedDefaultWallpaperAfterCheck(
    const GURL& wallpaper_url,
    const base::FilePath& file_path,
    const base::FilePath& resized_small_path,
    const base::FilePath& resized_large_path,
    bool both_sizes_exist) {
  const std::string current_url = g_browser_process->local_state()->GetString(
      prefs::kCustomizationDefaultWallpaperURL);
  if (both_sizes_exist && current_url == wallpaper_url.spec()) {
    ash::WallpaperController::Get()->SetCustomizedDefaultWallpaperPaths(
        resized_small_path, resized_small_path);
  } else {
    // Either resized images do not exist or cached version is incorrect.
    // Need to start decoding again.
    scoped_refptr<base::SequencedTaskRunner> task_runner =
        base::ThreadPool::CreateSequencedTaskRunner(
            {base::MayBlock(), base::TaskPriority::USER_BLOCKING,
             base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN});
    user_image_loader::StartWithFilePath(
        task_runner, file_path, ImageDecoder::DEFAULT_CODEC,
        0,  // Do not crop.
        base::BindOnce(&OnCustomizedDefaultWallpaperDecoded, wallpaper_url,
                       resized_small_path, resized_large_path));
  }
}

}  // namespace

namespace customization_wallpaper_util {

void StartSettingCustomizedDefaultWallpaper(const GURL& wallpaper_url,
                                            const base::FilePath& file_path) {
  // Should fail if this ever happens in tests.
  DCHECK(wallpaper_url.is_valid());
  if (!wallpaper_url.is_valid()) {
    if (!wallpaper_url.is_empty()) {
      LOG(WARNING) << "Invalid Customized Wallpaper URL '"
                   << wallpaper_url.spec() << "'";
    }
    return;
  }

  std::string downloaded_file_name = file_path.BaseName().value();
  base::FilePath resized_small_path;
  base::FilePath resized_large_path;
  if (!GetCustomizedDefaultWallpaperPaths(&resized_small_path,
                                          &resized_large_path)) {
    return;
  }

  scoped_refptr<base::SequencedTaskRunner> task_runner =
      base::ThreadPool::CreateSequencedTaskRunner(
          {base::MayBlock(), base::TaskPriority::USER_BLOCKING,
           base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN});
  task_runner->PostTaskAndReplyWithResult(
      FROM_HERE,
      base::BindOnce(&CheckCustomizedWallpaperFilesExist, resized_small_path,
                     resized_large_path),
      base::BindOnce(&SetCustomizedDefaultWallpaperAfterCheck, wallpaper_url,
                     file_path, resized_small_path, resized_large_path));
}

bool GetCustomizedDefaultWallpaperPaths(base::FilePath* small_path_out,
                                        base::FilePath* large_path_out) {
  const base::FilePath default_downloaded_file_name =
      ServicesCustomizationDocument::GetCustomizedWallpaperDownloadedFileName();
  const base::FilePath default_cache_dir =
      ServicesCustomizationDocument::GetCustomizedWallpaperCacheDir();
  if (default_downloaded_file_name.empty() || default_cache_dir.empty()) {
    LOG(ERROR) << "Unable to get customized default wallpaper paths.";
    return false;
  }
  const std::string file_name = default_downloaded_file_name.BaseName().value();
  *small_path_out = default_cache_dir.Append(file_name + kSmallWallpaperSuffix);
  *large_path_out = default_cache_dir.Append(file_name + kLargeWallpaperSuffix);
  return true;
}

bool ShouldUseCustomizedDefaultWallpaper() {
  PrefService* pref_service = g_browser_process->local_state();
  return !pref_service->FindPreference(prefs::kCustomizationDefaultWallpaperURL)
              ->IsDefaultValue();
}

}  // namespace customization_wallpaper_util
}  // namespace ash