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

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

Powered by Google App Engine
This is Rietveld 408576698