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

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

Powered by Google App Engine
This is Rietveld 408576698