File: arc_app_icon.h

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 (283 lines) | stat: -rw-r--r-- 11,734 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
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_ASH_APP_LIST_ARC_ARC_APP_ICON_H_
#define CHROME_BROWSER_ASH_APP_LIST_ARC_ARC_APP_ICON_H_

#include <map>
#include <memory>
#include <set>
#include <string>
#include <vector>

#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "ui/base/resource/resource_scale_factor.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/image/image_skia.h"

struct ArcAppIconDescriptor;

namespace apps {
class ArcIconOnceLoader;
}

namespace base {
class FilePath;
}

namespace content {
class BrowserContext;
}

// A class that provides an ImageSkia for UI code to use. It handles ARC app
// icon resource loading, screen scale factor change etc. UI code that uses
// ARC app icon should host this class.
//
// Icon images are sometimes subject to post-processing effects, such as
// desaturating (graying out) disabled apps. Applying those effects are the
// responsibility of code that uses this ArcAppIcon class, not the
// responsibility of ArcAppIcon itself.
class ArcAppIcon {
 public:
  class Observer {
   public:
    // Invoked when a new image rep for an additional scale factor
    // is loaded and added to |image|.
    virtual void OnIconUpdated(ArcAppIcon* icon) = 0;

    // Invoked when failed to generate an icon.
    virtual void OnIconFailed(ArcAppIcon* icon) {}

   protected:
    virtual ~Observer() = default;
  };

  enum IconType {
    kUncompressed,
    kCompressed,
    kAdaptive,
  };

  ArcAppIcon(content::BrowserContext* context,
             const std::string& app_id,
             int resource_size_in_dip,
             Observer* observer,
             IconType icon_type = IconType::kUncompressed);

  ArcAppIcon(const ArcAppIcon&) = delete;
  ArcAppIcon& operator=(const ArcAppIcon&) = delete;

  virtual ~ArcAppIcon();

  // Starts loading the icon at every supported scale factor. The |observer_|
  // will be notified as progress is made. "Supported" is in the same sense as
  // ui::GetSupportedResourceScaleFactors().
  virtual void LoadSupportedScaleFactors();

  // Whether every supported scale factor was successfully loaded. "Supported"
  // is in the same sense as ui::GetSupportedResourceScaleFactors().
  //
  // For the adaptive icon, if there is a non-adaptive icon for some scale
  // refactors, sets all scale factors as the non-adaptive icon, and copy
  // the decode result from |foreground_image_skia_| to |image_skia_|.
  bool EverySupportedScaleFactorIsLoaded();

  const std::string& app_id() const { return app_id_; }

  bool is_adaptive_icon() const {
    return is_adaptive_icons_.empty() ? true
                                      : is_adaptive_icons_.begin()->second;
  }

  // Returns |image_skia_| and valid if the |icon_type_| is
  // IconType::kUncompressed.
  const gfx::ImageSkia& image_skia() const {
    return image_skia_;
  }
  // Returns |compressed_images_| and valid if the |icon_type_| is
  // IconType::kCompressed.
  const std::map<ui::ResourceScaleFactor, std::string>& compressed_images()
      const {
    DCHECK_EQ(IconType::kCompressed, icon_type_);
    return compressed_images_;
  }
  // Returns |foreground_image_skia_| and valid if the |icon_type_| is
  // IconType::kAdaptive.
  const gfx::ImageSkia& foreground_image_skia() const {
    DCHECK_EQ(IconType::kAdaptive, icon_type_);
    return foreground_image_skia_;
  }
  // Returns |background_image_skia_| and valid if the |icon_type_| is
  // IconType::kAdaptive.
  const gfx::ImageSkia& background_image_skia() const {
    DCHECK_EQ(IconType::kAdaptive, icon_type_);
    return background_image_skia_;
  }

  // Disables async safe decoding requests when unit tests are executed. This is
  // done to avoid two problems. Problems come because icons are decoded at a
  // separate process created by ImageDecoder. ImageDecoder has 5 seconds delay
  // to stop since the last request (see its kBatchModeTimeoutSeconds for more
  // details). This is unacceptably long for unit tests because the test
  // framework waits until external process is finished. Another problem happens
  // when we issue a decoding request, but the process has not started its
  // processing yet by the time when a test exits. This might cause situation
  // when g_one_utility_thread_lock from in_process_utility_thread.cc gets
  // released in an acquired state which is crash condition in debug builds.
  static void DisableSafeDecodingForTesting();
  static bool IsSafeDecodingDisabledForTesting();

 protected:
  struct ReadResult {
    ReadResult(bool error,
               bool request_to_install,
               ui::ResourceScaleFactor scale_factor,
               bool resize_allowed,
               std::vector<std::string> unsafe_icon_data);
    ~ReadResult();

    const bool error;
    const bool request_to_install;
    const ui::ResourceScaleFactor scale_factor;
    const bool resize_allowed;
    const std::vector<std::string> unsafe_icon_data;
  };

  // Icon loading is performed in several steps. It is initiated by
  // LoadImageForScaleFactor request that specifies a required scale factor.
  // ArcAppListPrefs is used to resolve a path to resource. Content of file is
  // asynchronously read in context of browser file thread. On successful read,
  // an icon data is decoded to an image in the special utility process.
  // DecodeRequest is used to interact with the utility process, and each
  // active request is stored at |decode_requests_| vector. When decoding is
  // complete, results are returned in context of UI thread, and corresponding
  // request is removed from |decode_requests_|. In case of some requests are
  // not completed by the time of deleting this icon, they are automatically
  // canceled.
  // In case of the icon file is not available this requests ArcAppListPrefs to
  // install required resource from ARC side. ArcAppListPrefs notifies UI items
  // that new icon is available and corresponding item should invoke
  // LoadImageForScaleFactor again.
  virtual void LoadForScaleFactor(ui::ResourceScaleFactor scale_factor);

  virtual void OnIconRead(std::unique_ptr<ArcAppIcon::ReadResult> read_result);

 private:
  friend class ArcAppIconLoader;
  friend class apps::ArcIconOnceLoader;

  class Source;
  class DecodeRequest;

  void MaybeRequestIcon(ui::ResourceScaleFactor scale_factor);
  static std::unique_ptr<ArcAppIcon::ReadResult> ReadOnBackgroundThread(
      ArcAppIcon::IconType icon_type,
      ui::ResourceScaleFactor scale_factor,
      const std::vector<base::FilePath>& paths,
      const std::vector<base::FilePath>& default_app_paths);
  static std::unique_ptr<ArcAppIcon::ReadResult> ReadSingleIconFile(
      ui::ResourceScaleFactor scale_factor,
      const base::FilePath& path,
      const base::FilePath& default_app_path);

  // For the adaptive icon, currently, there are 3 images returned from the ARC
  // side:
  // (1) Icon_png_data, the adaptive icon generated by the ARC side, for
  // backward compatibility.
  // (2) Foreground_icon_png_data, the foreground image for
  // the adaptive icon. Some icons are not adaptive icons, and don’t have the
  // background images, then the foreground image is the app icon.
  // (3) Background_icon_png_data, the background image for the adaptive icon.
  // Some icons are not adaptive icons, and don’t have the background images.
  //
  // There are a few scenarios for the adaptive icon feature:
  // A. For the adaptive icon, the foreground image and the background image are
  // merged by the Chromium side, and applied with the mask, to generate the
  // adaptive icon.
  // B. For the non adaptive icon, the Chromium side adds a white background to
  // the foreground image, then applies the mask to generate the adaptive icon.
  // C. For the migration scenario (from the adaptive icon feature disable to
  // enable), since neither foreground images and background images present on
  // the system, the Chromium side sends requests to the ARC side to load the
  // foreground and background images. However, it might take a few seconds to
  // get the images files, so for users, it has a long lag for the ARC icon
  // loading. To resolve the ARC icon lag issue, the old icon_png_data on the
  // system is used to generate the icon, the same as the previous
  // implementation, and at the same time, sending the request to the ARC side
  // to request the new foreground and background images.
  //
  // TODO(crbug.com/40131344): Remove the migration handling code, which reads
  // the old icon_png_data, when the adaptive icon feature is enabled in the
  // stable release, and the adaptive icon flag is removed.
  static std::unique_ptr<ArcAppIcon::ReadResult> ReadAdaptiveIconFiles(
      ui::ResourceScaleFactor scale_factor,
      const std::vector<base::FilePath>& paths,
      const std::vector<base::FilePath>& default_app_paths);
  static std::unique_ptr<ArcAppIcon::ReadResult>
  ReadDefaultAppAdaptiveIconFiles(
      ui::ResourceScaleFactor scale_factor,
      const std::vector<base::FilePath>& default_app_paths);
  static std::unique_ptr<ArcAppIcon::ReadResult> ReadFile(
      bool request_to_install,
      ui::ResourceScaleFactor scale_factor,
      bool resize_allowed,
      const base::FilePath& path);
  static std::unique_ptr<ArcAppIcon::ReadResult> ReadFiles(
      bool request_to_install,
      ui::ResourceScaleFactor scale_factor,
      bool resize_allowed,
      const base::FilePath& foreground_path,
      const base::FilePath& background_path);
  void DecodeImage(
      std::string unsafe_icon_data,
      const ArcAppIconDescriptor& descriptor,
      bool resize_allowed,
      bool retain_padding,
      gfx::ImageSkia& image_skia,
      std::map<ui::ResourceScaleFactor, base::Time>& incomplete_scale_factors);
  void UpdateImageSkia(
      ui::ResourceScaleFactor scale_factor,
      const SkBitmap& bitmap,
      gfx::ImageSkia& image_skia,
      std::map<ui::ResourceScaleFactor, base::Time>& incomplete_scale_factors);
  void UpdateCompressed(ui::ResourceScaleFactor scale_factor, std::string data);
  void DiscardDecodeRequest(DecodeRequest* request, bool is_decode_success);

  const raw_ptr<content::BrowserContext> context_;
  const std::string app_id_;
  // Contains app id that is actually used to read an icon resource to support
  // shelf group mapping to shortcut.
  const std::string mapped_app_id_;
  const int resource_size_in_dip_;
  const raw_ptr<Observer> observer_;
  const IconType icon_type_;
  // Used to separate first 5 loaded app icons and other app icons.
  // Only one form of app icons will be loaded, compressed or uncompressed, so
  // only one counter is needed.
  int icon_loaded_count_ = 0;

  // For some apps, some scales have the adaptive icons, but some are not. So
  // using a map to present which scale is the adaptive icon, which is not.
  std::map<ui::ResourceScaleFactor, bool> is_adaptive_icons_;

  gfx::ImageSkia image_skia_;
  std::map<ui::ResourceScaleFactor, std::string> compressed_images_;
  gfx::ImageSkia foreground_image_skia_;
  gfx::ImageSkia background_image_skia_;

  std::map<ui::ResourceScaleFactor, base::Time> incomplete_scale_factors_;
  std::map<ui::ResourceScaleFactor, base::Time>
      foreground_incomplete_scale_factors_;
  std::map<ui::ResourceScaleFactor, base::Time>
      background_incomplete_scale_factors_;

  // Contains pending image decode requests.
  std::vector<std::unique_ptr<DecodeRequest>> decode_requests_;

  base::WeakPtrFactory<ArcAppIcon> weak_ptr_factory_{this};
};

#endif  // CHROME_BROWSER_ASH_APP_LIST_ARC_ARC_APP_ICON_H_