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

Side by Side Diff: chrome/browser/ui/app_list/arc_app_list_prefs.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: revert wrongly update chrome/chrome_browser_ui.gypi 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_list_prefs.h"
6
7 #include "base/files/file_util.h"
8 #include "base/prefs/scoped_user_pref_update.h"
9 #include "base/task_runner_util.h"
10 #include "chrome/browser/profiles/profile.h"
11 #include "chrome/browser/ui/app_list/arc_app_list_prefs_factory.h"
12 #include "chrome/common/pref_names.h"
13 #include "components/crx_file/id_util.h"
14 #include "components/pref_registry/pref_registry_syncable.h"
15 #include "content/public/browser/browser_thread.h"
16
17 namespace {
18
19 const char kName[] = "name";
20 const char kPackage[] = "package";
21 const char kActivity[] = "activity";
22
23 // Provider of write access to a dictionary storing ARC app prefs.
24 class ScopedArcAppListPrefUpdate : public DictionaryPrefUpdate {
25 public:
26 ScopedArcAppListPrefUpdate(PrefService* service, const std::string& id)
27 : DictionaryPrefUpdate(service, prefs::kArcApps),
28 id_(id) {}
29
30 ~ScopedArcAppListPrefUpdate() override {}
31
32 // DictionaryPrefUpdate overrides:
33 base::DictionaryValue* Get() override {
34 base::DictionaryValue* dict = DictionaryPrefUpdate::Get();
35 base::DictionaryValue* app = NULL;
xiyuan 2015/11/13 17:14:22 nit: NULL -> nullptr
khmel1 2015/11/17 13:18:02 Done.
36 if (!dict->GetDictionary(id_, &app)) {
37 app = new base::DictionaryValue();
38 dict->SetWithoutPathExpansion(id_, app);
39 }
40 return app;
41 }
42
43 private:
44 const std::string id_;
45
46 DISALLOW_COPY_AND_ASSIGN(ScopedArcAppListPrefUpdate);
47 };
48
49 } // namespace
50
51 // static
52 ArcAppListPrefs* ArcAppListPrefs::Create(const base::FilePath& base_path,
53 PrefService* prefs) {
54 return new ArcAppListPrefs(base_path, prefs);
55 }
56
57 // static
58 void ArcAppListPrefs::RegisterProfilePrefs(
59 user_prefs::PrefRegistrySyncable* registry) {
60 registry->RegisterDictionaryPref(
61 prefs::kArcApps,
62 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
63 }
64
65 // static
66 ArcAppListPrefs* ArcAppListPrefs::Get(content::BrowserContext* context) {
67 return ArcAppListPrefsFactory::GetInstance()->GetForBrowserContext(context);
68 }
69
70 // static
71 std::string ArcAppListPrefs::GetAppId(const std::string& package,
72 const std::string& activity) {
73 std::string input = package + "#" + activity;
74 return crx_file::id_util::GenerateId(input);
75 }
76
77 ArcAppListPrefs::ArcAppListPrefs(const base::FilePath& base_path,
78 PrefService* prefs)
79 : prefs_(prefs),
80 weak_ptr_factory_(this) {
81 base_path_ = base_path.AppendASCII(prefs::kArcApps);
82
83 arc::ArcBridgeService* bridge_service = arc::ArcBridgeService::Get();
84 if (!bridge_service) {
85 LOG(ERROR) << "Bridge service is not available. Cannot init.";
86 return;
87 }
88
89 bridge_service->AddObserver(this);
90 OnStateChanged(bridge_service->state());
91 }
92
93 ArcAppListPrefs::~ArcAppListPrefs() {
94 arc::ArcBridgeService* bridge_service = arc::ArcBridgeService::Get();
95 if (bridge_service) {
96 bridge_service->RemoveObserver(this);
97 }
98 }
99
100 base::FilePath ArcAppListPrefs::GetIconPath(
101 const std::string& app_id,
102 ui::ScaleFactor scale_factor) const {
103 base::FilePath app_path = base_path_.AppendASCII(app_id);
104 switch (scale_factor) {
105 case ui::SCALE_FACTOR_100P:
106 return app_path.AppendASCII("icon_100p.png");
107 case ui::SCALE_FACTOR_125P:
108 return app_path.AppendASCII("icon_125p.png");
109 case ui::SCALE_FACTOR_133P:
110 return app_path.AppendASCII("icon_133p.png");
111 case ui::SCALE_FACTOR_140P:
112 return app_path.AppendASCII("icon_140p.png");
113 case ui::SCALE_FACTOR_150P:
114 return app_path.AppendASCII("icon_150p.png");
115 case ui::SCALE_FACTOR_180P:
116 return app_path.AppendASCII("icon_180p.png");
117 case ui::SCALE_FACTOR_200P:
118 return app_path.AppendASCII("icon_200p.png");
119 case ui::SCALE_FACTOR_250P:
120 return app_path.AppendASCII("icon_250p.png");
121 case ui::SCALE_FACTOR_300P:
122 return app_path.AppendASCII("icon_300p.png");
123 default:
124 NOTREACHED();
125 return base::FilePath();
126 }
127 }
128
129 void ArcAppListPrefs::RequestIcon(const std::string& app_id,
130 ui::ScaleFactor scale_factor) {
131 if (!IsRegistered(app_id)) {
132 LOG(ERROR) << "Request to load icon for non-registered app: "
133 << app_id << ".";
134 return;
135 }
136
137 // In case app is not ready, defer this request.
138 if (!ready_apps_.count(app_id)) {
139 request_icon_deferred_[app_id] =
140 request_icon_deferred_[app_id] | 1 << scale_factor;
141 return;
142 }
143
144 arc::ArcBridgeService* bridge_service = arc::ArcBridgeService::Get();
145 if (!bridge_service ||
146 bridge_service->state() != arc::ArcBridgeService::State::READY) {
147 LOG(ERROR) << "Request to load icon when bridge service is not ready: "
148 << app_id << ".";
149 return;
150 }
151
152 scoped_ptr<AppInfo> app_info = GetApp(app_id);
153 if (!app_info) {
154 LOG(ERROR) << "Failed to get app info: " << app_id << ".";
155 return;
156 }
157
158 bridge_service->RequestIcon(app_info->package,
159 app_info->activity,
160 static_cast<int>(scale_factor));
161 }
162
163 void ArcAppListPrefs::AddObserver(Observer* observer) {
164 observer_list_.AddObserver(observer);
165 }
166
167 void ArcAppListPrefs::RemoveObserver(Observer* observer) {
168 observer_list_.RemoveObserver(observer);
169 }
170
171 std::vector<std::string> ArcAppListPrefs::GetAppIds() const {
172 std::vector<std::string> ids;
173
174 // crx_file::id_util is de-factor utility for id generation.
175 const base::DictionaryValue* apps = prefs_->GetDictionary(prefs::kArcApps);
176 for (base::DictionaryValue::Iterator app_id(*apps);
177 !app_id.IsAtEnd(); app_id.Advance()) {
178 if (!crx_file::id_util::IdIsValid(app_id.key()))
179 continue;
180 ids.push_back(app_id.key());
181 }
182
183 return ids;
184 }
185
186 scoped_ptr<ArcAppListPrefs::AppInfo> ArcAppListPrefs::GetApp(
187 const std::string& app_id) const {
188 const base::DictionaryValue* app = NULL;
xiyuan 2015/11/13 17:14:22 nit: NULL -> nullptr
khmel1 2015/11/17 13:18:02 Done.
189 const base::DictionaryValue* apps = prefs_->GetDictionary(prefs::kArcApps);
190 if (!apps ||
191 !apps->GetDictionaryWithoutPathExpansion(app_id, &app)) {
192 return scoped_ptr<AppInfo>();
193 }
194
195 scoped_ptr<AppInfo> app_info(new AppInfo);
196 app->GetString(kName, &app_info->name);
197 app->GetString(kPackage, &app_info->package);
198 app->GetString(kActivity, &app_info->activity);
199 app_info->ready = ready_apps_.count(app_id) > 0;
200
201 return app_info.Pass();
202 }
203
204 bool ArcAppListPrefs::IsRegistered(const std::string& app_id) {
205 const base::DictionaryValue* app = NULL;
xiyuan 2015/11/13 17:14:22 nit: NULL -> nullptr
khmel1 2015/11/17 13:18:02 Done.
206 const base::DictionaryValue* apps = prefs_->GetDictionary(prefs::kArcApps);
207 if (!apps || !apps->GetDictionary(app_id, &app)) {
208 return false;
209 }
210 return true;
211 }
212
213 void ArcAppListPrefs::DisableAllApps() {
214 for (auto& app_id : ready_apps_) {
215 FOR_EACH_OBSERVER(Observer,
216 observer_list_,
217 OnAppReadyChanged(app_id, false));
218 }
219 ready_apps_.clear();
220 }
221
222 void ArcAppListPrefs::OnStateChanged(arc::ArcBridgeService::State state) {
223 if (state == arc::ArcBridgeService::State::READY) {
224 arc::ArcBridgeService::Get()->RefreshApps();
225 } else {
226 DisableAllApps();
227 }
228 }
229
230 void ArcAppListPrefs::OnAppReady(const std::string& name,
231 const std::string& package,
232 const std::string& activity) {
233 if (name.empty() || package.empty() || activity.empty()) {
234 LOG(ERROR) << "Name, package and activity cannot be empty.";
235 return;
236 }
237 std::string app_id = GetAppId(package, activity);
238 bool was_registered = IsRegistered(app_id);
239
240 ScopedArcAppListPrefUpdate update(prefs_, app_id);
241 base::DictionaryValue* app_dict = update.Get();
242 app_dict->SetString(kName, name);
243 app_dict->SetString(kPackage, package);
244 app_dict->SetString(kActivity, activity);
245
246 // From now, app is ready.
247 if (!ready_apps_.count(app_id)) {
248 ready_apps_.insert(app_id);
249 }
250
251 if (was_registered) {
252 FOR_EACH_OBSERVER(Observer,
253 observer_list_,
254 OnAppReadyChanged(app_id, true));
255 } else {
256 AppInfo app_info;
257 app_info.name = name;
258 app_info.package = package;
259 app_info.activity = activity;
260 app_info.ready = true;
261 FOR_EACH_OBSERVER(Observer,
262 observer_list_,
263 OnAppRegistered(app_id, app_info));
264 }
265
266 std::map<std::string, uint32>::iterator deferred_icons =
267 request_icon_deferred_.find(app_id);
268 if (deferred_icons != request_icon_deferred_.end()) {
269 for (uint32 i = ui::SCALE_FACTOR_100P; i < ui::NUM_SCALE_FACTORS; ++i) {
270 if (deferred_icons->second & (1 << i)) {
271 RequestIcon(app_id, static_cast<ui::ScaleFactor>(i));
272 }
273 }
274 request_icon_deferred_.erase(deferred_icons);
275 }
276 }
277
278 void ArcAppListPrefs::OnAppsRefreshed(
279 const std::vector<std::string>& names,
280 const std::vector<std::string>& packages,
281 const std::vector<std::string>& activities) {
282 if (names.size() != packages.size() || names.size() != activities.size()) {
283 LOG(ERROR) << "Name, package and activity must be the same size.";
284 return;
285 }
286
287 std::set<std::string> old_ready_apps;
288 old_ready_apps.swap(ready_apps_);
289
290 for (size_t i = 0; i < names.size(); ++i) {
291 OnAppReady(names[i], packages[i], activities[i]);
292 }
293
294 // Detect unavailable apps after current refresh.
295 for (auto& app_id : old_ready_apps) {
296 if (!ready_apps_.count(app_id)) {
297 FOR_EACH_OBSERVER(Observer,
298 observer_list_,
299 OnAppReadyChanged(app_id, false));
300 }
301 }
302 }
303
304 void ArcAppListPrefs::OnAppIcon(const std::string& package,
305 const std::string& activity,
306 int scale_factor,
307 const std::vector<uint8_t>& icon_png_data) {
308 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
309 DCHECK(!icon_png_data.empty());
310 DCHECK(scale_factor >= ui::SCALE_FACTOR_100P &&
311 scale_factor < ui::NUM_SCALE_FACTORS);
312
313 std::string app_id = GetAppId(package, activity);
314 if (!IsRegistered(app_id)) {
315 LOG(ERROR) << "Request to update icon for non-registered app: " << app_id;
316 return;
317 }
318
319 InstallIcon(app_id,
320 static_cast<ui::ScaleFactor>(scale_factor),
321 icon_png_data);
322 }
323
324
325 void ArcAppListPrefs::InstallIcon(const std::string& app_id,
326 ui::ScaleFactor scale_factor,
327 const std::vector<uint8>& content_png) {
328 base::Closure task = base::Bind(&ArcAppListPrefs::InstallIconFromFileThread,
329 weak_ptr_factory_.GetWeakPtr(),
330 app_id,
331 scale_factor,
332 content_png);
333 content::BrowserThread::GetBlockingPool()->PostTask(FROM_HERE, task);
334 }
335
336 void ArcAppListPrefs::InstallIconFromFileThread(
337 const std::string& app_id,
338 ui::ScaleFactor scale_factor,
339 const std::vector<uint8>& content_png) {
340 DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
341 DCHECK(!content_png.empty());
342
343 base::FilePath app_path = base_path_.AppendASCII(app_id);
344 base::CreateDirectory(app_path);
345 base::FilePath icon_path = GetIconPath(app_id, scale_factor);
346
347 int wrote = base::WriteFile(icon_path,
348 reinterpret_cast<const char*>(&content_png[0]),
349 content_png.size());
350 if (wrote != static_cast<int>(content_png.size())) {
351 LOG(ERROR) << "Failed to write ARC icon file: " << icon_path.MaybeAsASCII()
352 << ".";
353 DCHECK(base::DeleteFile(icon_path, false));
354 return;
355 }
356
357 base::Closure task = base::Bind(&ArcAppListPrefs::OnIconInstalled,
358 weak_ptr_factory_.GetWeakPtr(),
359 app_id,
360 scale_factor);
361 content::BrowserThread::PostTask(content::BrowserThread::UI,
362 FROM_HERE,
363 task);
364 }
365
366 void ArcAppListPrefs::OnIconInstalled(const std::string& app_id,
367 ui::ScaleFactor scale_factor) {
368 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
369
370 FOR_EACH_OBSERVER(Observer,
371 observer_list_,
372 OnAppIconUpdated(app_id, scale_factor));
373 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698