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

Side by Side Diff: chrome/browser/ui/app_list/arc/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: Merged FakeArcBridgeService, comments addressed. Created 5 years 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/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 "base/task_runner_util.h"
13 #include "chrome/browser/image_decoder.h"
14 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
15 #include "content/public/browser/browser_thread.h"
16 #include "extensions/grit/extensions_browser_resources.h"
17 #include "ui/base/resource/resource_bundle.h"
18 #include "ui/gfx/geometry/size.h"
19 #include "ui/gfx/image/image_skia_source.h"
20
21 namespace {
22
23 bool g_disable_decoding = false;
24
25 }
jochen (gone - plz use gerrit) 2015/12/03 12:55:52 } // namespace
khmel1 2015/12/03 14:12:41 Done.
26
27 ////////////////////////////////////////////////////////////////////////////////
28 // ArcAppIcon::ReadResult
29
30 struct ArcAppIcon::ReadResult {
31 enum Status {
hidehiko 2015/12/03 13:08:39 enum class ?
khmel1 2015/12/03 14:12:41 Done.
32 OK,
33 FAIL,
34 REQUEST_TO_INSTALL,
35 };
36
37 ReadResult(Status status, ui::ScaleFactor scale_factor)
38 : status(status), scale_factor(scale_factor) {
39 }
40
41 Status status;
42 ui::ScaleFactor scale_factor;
43 std::string unsafe_icon_data;
44 };
45
46 ////////////////////////////////////////////////////////////////////////////////
47 // ArcAppIcon::Source
48
49 class ArcAppIcon::Source : public gfx::ImageSkiaSource {
50 public:
51 explicit Source(const base::WeakPtr<ArcAppIcon>& host);
52 ~Source() override;
53
54 private:
55 // gfx::ImageSkiaSource overrides:
56 gfx::ImageSkiaRep GetImageForScale(float scale) override;
57
58 // Used to load images asynchronously. NULLed out when the ArcAppIcon is
59 // destroyed.
60 base::WeakPtr<ArcAppIcon> host_;
61
62 DISALLOW_COPY_AND_ASSIGN(Source);
63 };
64
65 ArcAppIcon::Source::Source(const base::WeakPtr<ArcAppIcon>& host)
66 : host_(host) {
hidehiko 2015/12/03 13:08:39 4 indent.
khmel1 2015/12/03 14:12:41 Done.
67 }
68
69 ArcAppIcon::Source::~Source() {
70 }
71
72 gfx::ImageSkiaRep ArcAppIcon::Source::GetImageForScale(float scale) {
73 if (host_)
74 host_->LoadForScaleFactor(ui::GetSupportedScaleFactor(scale));
75
76 // Host loads icon asynchronously, so use default icon so far.
77 const gfx::ImageSkia* default_image = ResourceBundle::GetSharedInstance().
78 GetImageSkiaNamed(IDR_APP_DEFAULT_ICON);
79 CHECK(default_image);
80
81 return default_image->GetRepresentation(scale);
82 }
83
84 class ArcAppIcon::DecodeRequest : public ImageDecoder::ImageRequest {
85 public:
86 DecodeRequest(const base::WeakPtr<ArcAppIcon>& host,
87 int dimension,
88 ui::ScaleFactor scale_factor);
89 ~DecodeRequest() override;
90
91 // ImageDecoder::ImageRequest
92 void OnImageDecoded(const SkBitmap& bitmap) override;
93 void OnDecodeImageFailed() override;
94 private:
95 base::WeakPtr<ArcAppIcon> host_;
96 int dimension_;
97 ui::ScaleFactor scale_factor_;
98
99 DISALLOW_COPY_AND_ASSIGN(DecodeRequest);
100 };
101
102 ////////////////////////////////////////////////////////////////////////////////
103 // ArcAppIcon::DecodeRequest
104
105 ArcAppIcon::DecodeRequest::DecodeRequest(const base::WeakPtr<ArcAppIcon>& host,
106 int dimension,
107 ui::ScaleFactor scale_factor)
108 : host_(host),
hidehiko 2015/12/03 13:08:39 Ditto.
khmel1 2015/12/03 14:12:42 Done.
109 dimension_(dimension),
110 scale_factor_(scale_factor) {
111 }
112
113 ArcAppIcon::DecodeRequest::~DecodeRequest() {
114 }
115
116 void ArcAppIcon::DecodeRequest::OnImageDecoded(const SkBitmap& bitmap) {
117 DCHECK(!bitmap.isNull() && !bitmap.empty());
118
119 if (!host_) {
120 return;
jochen (gone - plz use gerrit) 2015/12/03 12:55:52 no {} for single line bodies, here and everywhere
khmel1 2015/12/03 14:12:42 Done.
121 }
122
123 int expected_dim = static_cast<int>(
124 ui::GetScaleForScaleFactor(scale_factor_) * dimension_ + 0.5f);
125 if (bitmap.width() != expected_dim || bitmap.height() != expected_dim) {
126 VLOG(2) << "Decoded ARC icon has unexpected dimension "
127 << bitmap.width() << "x" << bitmap.height() << ". Expected "
128 << expected_dim << "x" << ".";
129 return;
jochen (gone - plz use gerrit) 2015/12/03 12:55:51 don't you need to discard the request here as well
khmel1 2015/12/03 14:12:41 Yes, thanks for catching. In case something wrong
130 }
131
132 gfx::ImageSkia image_skia;
133 image_skia.AddRepresentation(gfx::ImageSkiaRep(
134 bitmap,
135 ui::GetScaleForScaleFactor(scale_factor_)));
136
137 host_->Update(&image_skia);
138 host_->DiscardDecodeRequest(this);
139 }
140
141 void ArcAppIcon::DecodeRequest::OnDecodeImageFailed() {
142 VLOG(2) << "Failed to decode ARC icon.";
143
144 if (!host_)
145 return;
146
147 host_->DiscardDecodeRequest(this);
148 }
149
150 ////////////////////////////////////////////////////////////////////////////////
151 // ArcAppIcon
152
153 // static
154 void ArcAppIcon::DisableDecodingForTesting() {
155 g_disable_decoding = true;
156 }
157
158 ArcAppIcon::ArcAppIcon(content::BrowserContext* context,
159 const std::string& app_id,
160 int resource_size_in_dip,
161 Observer* observer)
162 : context_(context),
163 app_id_(app_id),
164 resource_size_in_dip_(resource_size_in_dip),
165 observer_(observer),
166 weak_ptr_factory_(this) {
167 CHECK(observer_ != NULL);
168 source_ = new Source(weak_ptr_factory_.GetWeakPtr());
169 gfx::Size resource_size(resource_size_in_dip, resource_size_in_dip);
170 image_skia_ = gfx::ImageSkia(source_, resource_size);
171 }
172
173 ArcAppIcon::~ArcAppIcon() {
174 }
175
176 void ArcAppIcon::LoadForScaleFactor(ui::ScaleFactor scale_factor) {
177 ArcAppListPrefs* prefs = ArcAppListPrefs::Get(context_);
178 if (!prefs) {
179 VLOG(2) << "ARC preferences service is not available.";
jochen (gone - plz use gerrit) 2015/12/03 12:55:52 how can this ever happen?
khmel1 2015/12/03 14:12:42 It is impossible. I removed check here for consist
180 return;
181 }
182
183 base::FilePath path = prefs->GetIconPath(app_id_, scale_factor);
184 if (path.empty())
185 return;
186
187 base::PostTaskAndReplyWithResult(content::BrowserThread::GetBlockingPool(),
188 FROM_HERE,
189 base::Bind(&ArcAppIcon::ReadOnFileThread,
190 scale_factor,
191 path),
192 base::Bind(&ArcAppIcon::OnIconRead,
193 weak_ptr_factory_.GetWeakPtr()));
194 }
195
196 void ArcAppIcon::RequestIcon(ui::ScaleFactor scale_factor) {
197 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
198 ArcAppListPrefs* prefs = ArcAppListPrefs::Get(context_);
199 if (!prefs) {
200 VLOG(2) << "ARC preferences service is not available.";
201 return;
202 }
203 // ArcAppListPrefs notifies ArcAppModelBuilder via Observer when icon is ready
204 // and ArcAppModelBuilder refreshes the icon of the corresponding item by
205 // calling LoadScaleFactor.
206 prefs->RequestIcon(app_id_, scale_factor);
207 }
208
209 // static
210 scoped_ptr<ArcAppIcon::ReadResult> ArcAppIcon::ReadOnFileThread(
211 ui::ScaleFactor scale_factor,
212 const base::FilePath& path) {
213 DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
214 DCHECK(!path.empty());
215
216 scoped_ptr<ArcAppIcon::ReadResult> result(new ArcAppIcon::ReadResult(
hidehiko 2015/12/03 13:08:39 I think it's better to inline to the return statem
khmel1 2015/12/03 14:12:42 Good point, thanks
217 ArcAppIcon::ReadResult::OK, scale_factor));
218
219 if (!base::PathExists(path)) {
220 result->status = ArcAppIcon::ReadResult::REQUEST_TO_INSTALL;
221 return result.Pass();
222 }
223
224 // Read the file from disk.
225 if (!base::ReadFileToString(path, &result->unsafe_icon_data)) {
226 VLOG(2) << "Failed to read an ARC icon from file " << path.MaybeAsASCII();
227 result->status = ArcAppIcon::ReadResult::FAIL;
228 return result.Pass();
229 }
230
231 return result.Pass();
232 }
233
234 void ArcAppIcon::OnIconRead(scoped_ptr<ArcAppIcon::ReadResult> read_result) {
235 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
236
237 switch (read_result->status) {
238 case ReadResult::OK:
239 if (!g_disable_decoding) {
240 decode_requests_.push_back(
241 new DecodeRequest(weak_ptr_factory_.GetWeakPtr(),
242 resource_size_in_dip_,
243 read_result->scale_factor));
244 ImageDecoder::Start(decode_requests_.back(),
245 read_result->unsafe_icon_data);
246 }
247 break;
248 case ReadResult::FAIL:
249 break;
250 case ReadResult::REQUEST_TO_INSTALL:
251 RequestIcon(read_result->scale_factor);
252 break;
253 default:
254 NOTREACHED();
255 }
256 }
257
258 void ArcAppIcon::Update(const gfx::ImageSkia* image) {
259 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
260 CHECK(image && !image->isNull());
261
262 std::vector<gfx::ImageSkiaRep> reps = image->image_reps();
263 for (const auto& image_rep : reps) {
264 if (ui::IsSupportedScale(image_rep.scale())) {
265 image_skia_.RemoveRepresentation(image_rep.scale());
266 image_skia_.AddRepresentation(image_rep);
267 }
268 }
269
270 image_ = gfx::Image(image_skia_);
271
272 observer_->OnIconUpdated();
273 }
274
275 void ArcAppIcon::DiscardDecodeRequest(DecodeRequest* request) {
276 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
277
278 ScopedVector<DecodeRequest>::iterator it = std::find(decode_requests_.begin(),
279 decode_requests_.end(),
280 request);
281 CHECK(it != decode_requests_.end());
282 decode_requests_.erase(it);
283 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698