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

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: Fix WeakPtr issue. Change PostTask on PostTaskAndReplyWithResult 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 "base/task_runner_util.h"
13 #include "chrome/browser/image_decoder.h"
14 #include "chrome/browser/ui/app_list/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 ////////////////////////////////////////////////////////////////////////////////
22 // ArcAppIcon::ReadResult
23
24 struct ArcAppIcon::ReadResult {
khmel1 2015/11/18 01:16:16 I need to return more statuses than just ok/fail.
25 enum Status {
26 OK,
27 FAIL,
28 REQUEST_TO_INSTALL,
29 };
30
31 Status status;
32 ui::ScaleFactor scale_factor;
33 std::string unsafe_icon_data;
34 };
35
36 namespace {
37
38 scoped_ptr<ArcAppIcon::ReadResult> ReadOnFileThread(
xiyuan 2015/11/18 03:42:16 nit: Having this in an anonymous namespace in midd
khmel1 2015/11/18 06:10:04 Yep, I also had filling that this was a little str
39 ui::ScaleFactor scale_factor,
40 const base::FilePath& path) {
41 DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
42 DCHECK(!path.empty());
43
44 scoped_ptr<ArcAppIcon::ReadResult> result(new ArcAppIcon::ReadResult());
45 result->scale_factor = scale_factor;
46
47 if (!base::PathExists(path)) {
48 result->status = ArcAppIcon::ReadResult::REQUEST_TO_INSTALL;
49 return result.Pass();
50 }
51
52 // Read the file from disk.
53 if (!base::ReadFileToString(path, &result->unsafe_icon_data)) {
54 LOG(ERROR) << "Failed to read an ARC icon from file "
55 << path.MaybeAsASCII();
56 result->status = ArcAppIcon::ReadResult::FAIL;
57 return result.Pass();
58 }
59
60 result->status = ArcAppIcon::ReadResult::OK;
61 return result.Pass();
62 }
63
64 } // namespace
65
66 ////////////////////////////////////////////////////////////////////////////////
67 // ArcAppIcon::Source
68
69 class ArcAppIcon::Source : public gfx::ImageSkiaSource {
70 public:
71 explicit Source(const base::WeakPtr<ArcAppIcon>& host);
72 ~Source() override;
73
74 private:
75 // gfx::ImageSkiaSource overrides:
76 gfx::ImageSkiaRep GetImageForScale(float scale) override;
77
78 // Used to load images asynchronously. NULLed out when the ArcAppIcon is
79 // destroyed.
80 base::WeakPtr<ArcAppIcon> host_;
81
82 DISALLOW_COPY_AND_ASSIGN(Source);
83 };
84
85 ArcAppIcon::Source::Source(const base::WeakPtr<ArcAppIcon>& host)
86 : host_(host) {
87 }
88
89 ArcAppIcon::Source::~Source() {
90 }
91
92 gfx::ImageSkiaRep ArcAppIcon::Source::GetImageForScale(float scale) {
93 if (host_) {
94 host_->LoadForScaleFactor(ui::GetSupportedScaleFactor(scale));
95 }
96
97 // Host loads icon asynchronously, so use default icon so far.
98 const gfx::ImageSkia* default_image = ResourceBundle::GetSharedInstance().
99 GetImageSkiaNamed(IDR_APP_DEFAULT_ICON);
100 CHECK(default_image);
101
102 return default_image->GetRepresentation(scale);
103 }
104
105 class ArcAppIcon::DecodeRequest : public ImageDecoder::ImageRequest {
106 public:
107 DecodeRequest(const base::WeakPtr<ArcAppIcon>& host,
108 int dimension,
109 ui::ScaleFactor scale_factor);
110 ~DecodeRequest() override;
111
112 // ImageDecoder::ImageRequest
113 void OnImageDecoded(const SkBitmap& bitmap) override;
114 void OnDecodeImageFailed() override;
115 private:
116 base::WeakPtr<ArcAppIcon> host_;
117 int dimension_;
118 ui::ScaleFactor scale_factor_;
119
120 DISALLOW_COPY_AND_ASSIGN(DecodeRequest);
121 };
122
123 ////////////////////////////////////////////////////////////////////////////////
124 // ArcAppIcon::DecodeRequest
125
126 ArcAppIcon::DecodeRequest::DecodeRequest(const base::WeakPtr<ArcAppIcon>& host,
127 int dimension,
128 ui::ScaleFactor scale_factor)
129 : host_(host),
130 dimension_(dimension),
131 scale_factor_(scale_factor) {
132 }
133
134 ArcAppIcon::DecodeRequest::~DecodeRequest() {
135 }
136
137 void ArcAppIcon::DecodeRequest::OnImageDecoded(const SkBitmap& bitmap) {
138 DCHECK(!bitmap.isNull() && !bitmap.empty());
139
140 if (!host_) {
141 return;
142 }
143
144 int expected_dim = static_cast<int>(
145 ui::GetScaleForScaleFactor(scale_factor_) * dimension_ + 0.5f);
146 if (bitmap.width() != expected_dim || bitmap.height() != expected_dim) {
147 LOG(ERROR) << "Decoded ARC icon has unexpected dimension "
148 << bitmap.width() << "x" << bitmap.height() << ". Expected "
149 << expected_dim << "x" << ".";
150 return;
151 }
152
153 gfx::ImageSkia image_skia;
154 image_skia.AddRepresentation(gfx::ImageSkiaRep(
155 bitmap,
156 ui::GetScaleForScaleFactor(scale_factor_)));
157
158 host_->Update(&image_skia);
159 host_->DiscardDecodeRequest(this);
160 }
161
162 void ArcAppIcon::DecodeRequest::OnDecodeImageFailed() {
163 LOG(ERROR) << "Failed to decode ARC icon.";
164
165 if (!host_) {
166 return;
167 }
168
169 host_->DiscardDecodeRequest(this);
170 }
171
172 ////////////////////////////////////////////////////////////////////////////////
173 // ArcAppIcon
174
175 ArcAppIcon::ArcAppIcon(content::BrowserContext* context,
176 const std::string& app_id,
177 int resource_size_in_dip,
178 Observer* observer)
179 : context_(context),
180 app_id_(app_id),
181 resource_size_in_dip_(resource_size_in_dip),
182 observer_(observer),
183 weak_ptr_factory_(this) {
184 CHECK(observer_ != NULL);
185 source_ = new Source(weak_ptr_factory_.GetWeakPtr());
186 gfx::Size resource_size(resource_size_in_dip, resource_size_in_dip);
187 image_skia_ = gfx::ImageSkia(source_, resource_size);
188 }
189
190 ArcAppIcon::~ArcAppIcon() {
191 }
192
193 void ArcAppIcon::LoadForScaleFactor(ui::ScaleFactor scale_factor) {
194 ArcAppListPrefs* prefs = ArcAppListPrefs::Get(context_);
195 if (!prefs) {
196 LOG(ERROR) << "ARC preferences service is not available.";
197 return;
198 }
199
200 base::FilePath path = prefs->GetIconPath(app_id_, scale_factor);
201 if (path.empty()) {
202 return;
203 }
204
205 base::PostTaskAndReplyWithResult(content::BrowserThread::GetBlockingPool(),
206 FROM_HERE,
207 base::Bind(&ReadOnFileThread,
208 scale_factor,
209 path),
210 base::Bind(&ArcAppIcon::OnIconRead,
211 weak_ptr_factory_.GetWeakPtr()));
212 }
213
214 void ArcAppIcon::RequestIcon(ui::ScaleFactor scale_factor) {
215 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
216 ArcAppListPrefs* prefs = ArcAppListPrefs::Get(context_);
217 if (!prefs) {
218 LOG(ERROR) << "ARC preferences service is not available.";
219 return;
220 }
221 // ArcAppListPrefs notifies ArcAppModelBuilder via Observer when icon is ready
222 // and ArcAppModelBuilder refreshes the icon of the corresponding item by
223 // calling LoadScaleFactor.
224 prefs->RequestIcon(app_id_, scale_factor);
225 }
226
227 void ArcAppIcon::OnIconRead(scoped_ptr<ArcAppIcon::ReadResult> read_result) {
228 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
229
230 switch (read_result->status) {
231 case ReadResult::OK:
232 decode_requests_.push_back(new DecodeRequest(weak_ptr_factory_.GetWeakPtr(),
233 resource_size_in_dip_,
234 read_result->scale_factor));
235 ImageDecoder::Start(decode_requests_.back(), read_result->unsafe_icon_data);
236 break;
237 case ReadResult::FAIL:
238 break;
239 case ReadResult::REQUEST_TO_INSTALL:
240 RequestIcon(read_result->scale_factor);
241 break;
242 default:
243 NOTREACHED();
244 }
245 }
246
247 void ArcAppIcon::Update(const gfx::ImageSkia* image) {
248 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
249 CHECK(image && !image->isNull());
250
251 std::vector<gfx::ImageSkiaRep> reps = image->image_reps();
252 for (const auto& image_rep : reps) {
253 if (ui::IsSupportedScale(image_rep.scale())) {
254 image_skia_.RemoveRepresentation(image_rep.scale());
255 image_skia_.AddRepresentation(image_rep);
256 }
257 }
258
259 image_ = gfx::Image(image_skia_);
260
261 observer_->OnIconUpdated();
262 }
263
264 void ArcAppIcon::DiscardDecodeRequest(DecodeRequest* request) {
265 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
266
267 ScopedVector<DecodeRequest>::iterator it = std::find(decode_requests_.begin(),
268 decode_requests_.end(),
269 request);
270 CHECK(it != decode_requests_.end());
271 decode_requests_.erase(it);
272 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698