Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(49)

Side by Side Diff: chrome/browser/ui/app_list/arc_app_icon.cc

Issue 1413153007: arc-app-launcher: Minimal support for ARC app launcher. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Discard accidental change in chrome/browser/prefs/browser_prefs.cc Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/ui/app_list/arc_app_icon.h"
6
7 #include <algorithm>
8
9 #include "base/bind.h"
10 #include "base/files/file_path.h"
11 #include "base/files/file_util.h"
12 #include "chrome/browser/image_decoder.h"
13 #include "chrome/browser/ui/app_list/arc_app_prefs.h"
14 #include "content/public/browser/browser_thread.h"
15 #include "extensions/grit/extensions_browser_resources.h"
16 #include "ui/base/resource/resource_bundle.h"
17 #include "ui/gfx/geometry/size.h"
18 #include "ui/gfx/image/image_skia_source.h"
19
20 ////////////////////////////////////////////////////////////////////////////////
21 // ArcAppIcon::Source
22
23 class ArcAppIcon::Source : public gfx::ImageSkiaSource {
24 public:
25 explicit Source(const base::WeakPtr<ArcAppIcon>& host);
26 ~Source() override;
27
28 private:
29 // gfx::ImageSkiaSource overrides:
30 gfx::ImageSkiaRep GetImageForScale(float scale) override;
31
32 // Used to load images asynchronously. NULLed out when the ArcAppIcon is
33 // destroyed.
34 base::WeakPtr<ArcAppIcon> host_;
35
36 DISALLOW_COPY_AND_ASSIGN(Source);
37 };
38
39 ArcAppIcon::Source::Source(const base::WeakPtr<ArcAppIcon>& host)
40 : host_(host) {
41 }
42
43 ArcAppIcon::Source::~Source() {
44 }
45
46 gfx::ImageSkiaRep ArcAppIcon::Source::GetImageForScale(float scale) {
47 if (host_) {
48 host_->LoadForScaleFactor(ui::GetSupportedScaleFactor(scale));
49 }
50
51 // Host loads icon asynchronously, so use default icon so far.
52 const gfx::ImageSkia* default_image = ResourceBundle::GetSharedInstance().
53 GetImageSkiaNamed(IDR_APP_DEFAULT_ICON);
54 CHECK(default_image);
55
56 return default_image->GetRepresentation(scale);
57 }
58
59 class ArcAppIcon::DecodeRequest : public ImageDecoder::ImageRequest {
60 public:
61 DecodeRequest(const base::WeakPtr<ArcAppIcon>& host,
62 int dimension,
63 ui::ScaleFactor scale_factor);
64 ~DecodeRequest() override;
65
66 // ImageDecoder::ImageRequest
67 void OnImageDecoded(const SkBitmap& bitmap) override;
68 void OnDecodeImageFailed() override;
69 private:
70 base::WeakPtr<ArcAppIcon> host_;
71 int dimension_;
72 ui::ScaleFactor scale_factor_;
73
74 DISALLOW_COPY_AND_ASSIGN(DecodeRequest);
75 };
76
77 ////////////////////////////////////////////////////////////////////////////////
78 // ArcAppIcon::DecodeRequest
79
80 ArcAppIcon::DecodeRequest::DecodeRequest(const base::WeakPtr<ArcAppIcon>& host,
81 int dimension,
82 ui::ScaleFactor scale_factor)
83 : host_(host),
84 dimension_(dimension),
85 scale_factor_(scale_factor) {
86 }
87
88 ArcAppIcon::DecodeRequest::~DecodeRequest() {
89 }
90
91 void ArcAppIcon::DecodeRequest::OnImageDecoded(const SkBitmap& bitmap) {
92 DCHECK(!bitmap.isNull() && !bitmap.empty());
93
94 if (!host_) {
95 return;
96 }
97
98 int expected_dim = static_cast<int>(
99 ui::GetScaleForScaleFactor(scale_factor_) * dimension_ + 0.5f);
100 if (bitmap.width() != expected_dim || bitmap.height() != expected_dim) {
101 LOG(ERROR) << "Decoded ARC icon has unexpected dimension "
102 << bitmap.width() << "x" << bitmap.height() << ". Expected "
103 << expected_dim << "x" << ".";
104 return;
105 }
106
107 gfx::ImageSkia image_skia;
108 image_skia.AddRepresentation(gfx::ImageSkiaRep(
109 bitmap,
110 ui::GetScaleForScaleFactor(scale_factor_)));
111
112 host_->Update(&image_skia);
113 host_->DiscardDecodeRequest(this);
114 }
115
116 void ArcAppIcon::DecodeRequest::OnDecodeImageFailed() {
117 LOG(ERROR) << "Failed to decode ARC icon.";
118
119 if (!host_) {
120 return;
121 }
122
123 host_->DiscardDecodeRequest(this);
124 }
125
126 ////////////////////////////////////////////////////////////////////////////////
127 // ArcAppIcon
128
129 ArcAppIcon::ArcAppIcon(content::BrowserContext* context,
130 const std::string& app_id,
131 int resource_size_in_dip,
132 Observer* observer)
133 : context_(context),
134 app_id_(app_id),
135 resource_size_in_dip_(resource_size_in_dip),
136 observer_(observer),
137 weak_ptr_factory_(this) {
138 CHECK(observer_ != NULL);
139 source_ = new Source(weak_ptr_factory_.GetWeakPtr());
140 gfx::Size resource_size(resource_size_in_dip, resource_size_in_dip);
141 image_skia_ = gfx::ImageSkia(source_, resource_size);
142 }
143
144 ArcAppIcon::~ArcAppIcon() {
145 }
146
147 void ArcAppIcon::LoadForScaleFactor(ui::ScaleFactor scale_factor) {
148 ArcAppPrefs* prefs = ArcAppPrefs::Get(context_);
149 if (!prefs) {
150 LOG(ERROR) << "ARC preferences service is not available.";
151 return;
152 }
153
154 base::FilePath path = prefs->GetIconPath(app_id_, scale_factor);
155 if (path.empty()) {
156 return;
157 }
158
159 base::Closure task = base::Bind(&ArcAppIcon::ReadOnFileThread,
160 weak_ptr_factory_.GetWeakPtr(),
161 scale_factor,
162 path);
163 content::BrowserThread::GetBlockingPool()->PostTask(FROM_HERE, task);
164 }
165
166 void ArcAppIcon::RequestIcon(ui::ScaleFactor scale_factor) {
167 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
168 ArcAppPrefs* prefs = ArcAppPrefs::Get(context_);
169 if (!prefs) {
170 LOG(ERROR) << "ARC preferences service is not available.";
171 return;
172 }
173 // ArcAppPrefs notifies ArcAppModelBuilder via Observer when icon is ready and
174 // ArcAppModelBuilder refreshes the icon of the corresponding item by calling
175 // LoadScaleFactor.
176 prefs->RequestIcon(app_id_, scale_factor);
177 }
178
179 void ArcAppIcon::ReadOnFileThread(ui::ScaleFactor scale_factor,
180 const base::FilePath& path) {
181 DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
182 DCHECK(!path.empty());
183
184 if (!base::PathExists(path)) {
185 base::Closure task = base::Bind(&ArcAppIcon::RequestIcon,
186 weak_ptr_factory_.GetWeakPtr(),
187 scale_factor);
188 content::BrowserThread::PostTask(content::BrowserThread::UI,
189 FROM_HERE,
190 task);
191 return;
192 }
193
194 std::string unsafe_icon_data;
195 // Read the file from disk.
196 if (!base::ReadFileToString(path, &unsafe_icon_data)) {
197 LOG(ERROR) << "Failed to read an ARC icon from file "
198 << path.MaybeAsASCII();
199 return;
200 }
201
202 base::Closure task = base::Bind(&ArcAppIcon::OnIconRead,
203 weak_ptr_factory_.GetWeakPtr(),
204 scale_factor,
205 unsafe_icon_data);
206 content::BrowserThread::PostTask(content::BrowserThread::UI,
207 FROM_HERE,
208 task);
209 }
210
211 void ArcAppIcon::OnIconRead(ui::ScaleFactor scale_factor,
212 const std::string& unsafe_image_data) {
213 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
214
215 decode_requests_.push_back(new DecodeRequest(weak_ptr_factory_.GetWeakPtr(),
216 resource_size_in_dip_,
217 scale_factor));
218 ImageDecoder::Start(decode_requests_.back(), unsafe_image_data);
219 }
220
221 void ArcAppIcon::Update(const gfx::ImageSkia* image) {
222 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
223 CHECK(image && !image->isNull());
224
225 std::vector<gfx::ImageSkiaRep> reps = image->image_reps();
226 for (const auto& image_rep : reps) {
227 if (ui::IsSupportedScale(image_rep.scale())) {
228 image_skia_.RemoveRepresentation(image_rep.scale());
229 image_skia_.AddRepresentation(image_rep);
230 }
231 }
232
233 image_ = gfx::Image(image_skia_);
234
235 observer_->OnIconUpdated();
236 }
237
238 void ArcAppIcon::DiscardDecodeRequest(DecodeRequest* request) {
239 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
240
241 ScopedVector<DecodeRequest>::iterator it = std::find(decode_requests_.begin(),
242 decode_requests_.end(),
243 request);
244 CHECK(it != decode_requests_.end());
245 decode_requests_.erase(it);
246 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698