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

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: 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 "chromeos/dbus/dbus_thread_manager.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 kArcApps[] = "arcapps";
20 const char kName[] = "name";
21 const char kPackage[] = "package";
22 const char kActivity[] = "activity";
23 const char kIcons[] = "icons";
24
25 // Provider of write access to a dictionary storing arc app prefs.
26 class ScopedArcAppPrefUpdate : public DictionaryPrefUpdate {
27 public:
28 ScopedArcAppPrefUpdate(PrefService* service, const std::string& id)
29 : DictionaryPrefUpdate(service, kArcApps),
30 id_(id) {}
31
32 ~ScopedArcAppPrefUpdate() override {}
33
34 // DictionaryPrefUpdate overrides:
35 base::DictionaryValue* Get() override {
36 base::DictionaryValue* dict = DictionaryPrefUpdate::Get();
37 base::DictionaryValue* app = NULL;
38 if (!dict->GetDictionary(id_, &app)) {
39 app = new base::DictionaryValue();
40 dict->SetWithoutPathExpansion(id_, app);
41 }
42 return app;
43 }
44
45 private:
46 const std::string id_;
47
48 DISALLOW_COPY_AND_ASSIGN(ScopedArcAppPrefUpdate);
49 };
50
51 base::FilePath GetIconPath(const base::FilePath& base_path,
52 ui::ScaleFactor scale_factor) {
53 switch (scale_factor) {
elijahtaylor1 2015/10/28 06:32:39 it's not clear what all of these icon sizes are fo
khmel1 2015/10/29 08:12:18 Required icon is determined by scale factor of Dis
54 case ui::SCALE_FACTOR_100P:
55 return base_path.AppendASCII("icon_100p.png");
56 case ui::SCALE_FACTOR_125P:
57 return base_path.AppendASCII("icon_125p.png");
58 case ui::SCALE_FACTOR_133P:
59 return base_path.AppendASCII("icon_133p.png");
60 case ui::SCALE_FACTOR_140P:
61 return base_path.AppendASCII("icon_140p.png");
62 case ui::SCALE_FACTOR_150P:
63 return base_path.AppendASCII("icon_150p.png");
64 case ui::SCALE_FACTOR_180P:
65 return base_path.AppendASCII("icon_180p.png");
66 case ui::SCALE_FACTOR_200P:
67 return base_path.AppendASCII("icon_200p.png");
68 case ui::SCALE_FACTOR_250P:
69 return base_path.AppendASCII("icon_250p.png");
70 case ui::SCALE_FACTOR_300P:
71 return base_path.AppendASCII("icon_300p.png");
72 default:
73 CHECK(false);
74 return base::FilePath();
75 }
76 }
77
78 } // namespace
79
80 // static
81 ArcAppPrefs* ArcAppPrefs::Create(content::BrowserContext* browser_context,
82 const base::FilePath& base_path,
83 PrefService* prefs) {
84 return new ArcAppPrefs(browser_context, base_path, prefs);
85 }
86
87 // static
88 void ArcAppPrefs::RegisterProfilePrefs(
89 user_prefs::PrefRegistrySyncable* registry) {
90 registry->RegisterDictionaryPref(
91 kArcApps,
92 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
93 }
94
95 // static
96 ArcAppPrefs* ArcAppPrefs::Get(content::BrowserContext* context) {
97 return ArcAppPrefsFactory::GetInstance()->GetForBrowserContext(context);
98 }
99
100 // static
101 std::string ArcAppPrefs::GetAppId(const std::string& package,
102 const std::string& activity) {
103 std::string input = package + "#" + activity;
104 return crx_file::id_util::GenerateId(input);
elijahtaylor1 2015/10/28 06:32:39 does this need to be a CRX style ID? It would be
khmel1 2015/10/29 08:12:18 My first impl was the same as you suggested. Howev
105 }
106
107 ArcAppPrefs::ArcAppPrefs(content::BrowserContext* browser_context,
108 const base::FilePath& base_path,
109 PrefService* prefs)
110 : browser_context_(browser_context),
111 prefs_(prefs) {
elijahtaylor1 2015/10/28 06:32:39 alignment
khmel1 2015/10/29 08:12:18 Done.
112 base_path_ = base_path.AppendASCII(kArcApps);
113
114 chromeos::DBusThreadManager::Get()->GetArcBridgeClient()->
115 AddAppObserver(this);
116 chromeos::DBusThreadManager::Get()->GetArcBridgeClient()->Refresh();
117 }
118
119 ArcAppPrefs::~ArcAppPrefs() {
120 chromeos::DBusThreadManager::Get()->GetArcBridgeClient()->
121 RemoveAppObserver(this);
122 }
123
124 void ArcAppPrefs::AddObserver(Observer* observer) {
125 observer_list_.AddObserver(observer);
126 }
127
128 void ArcAppPrefs::RemoveObserver(Observer* observer) {
129 observer_list_.RemoveObserver(observer);
130 }
131
132 std::vector<std::string> ArcAppPrefs::GetAppIds() const {
133 std::vector<std::string> ids;
134
135 const base::DictionaryValue* apps = prefs_->GetDictionary(kArcApps);
136 for (base::DictionaryValue::Iterator app_id(*apps);
137 !app_id.IsAtEnd(); app_id.Advance()) {
138 if (!crx_file::id_util::IdIsValid(app_id.key()))
139 continue;
140 ids.push_back(app_id.key());
141 }
142
143 return ids;
144 }
145
146 scoped_ptr<ArcAppPrefs::AppInfo> ArcAppPrefs::GetApp(
147 const std::string& app_id) const {
148 const base::DictionaryValue* app = NULL;
149 const base::DictionaryValue* apps = prefs_->GetDictionary(kArcApps);
150 if (!apps ||
151 !apps->GetDictionaryWithoutPathExpansion(app_id, &app))
152 return scoped_ptr<AppInfo>();
153
154 scoped_ptr<AppInfo> app_info(new AppInfo);
155 app->GetString(kName, &app_info->name);
156 app->GetString(kPackage, &app_info->package);
157 app->GetString(kActivity, &app_info->activity);
158 app_info->enabled = enable_apps_.count(app_id) > 0;
159
160 base::FilePath app_path = base_path_.AppendASCII(app_id);
161
162 int icon_flags = 0;
163 if (app->GetInteger(kIcons, &icon_flags)) {
164 for (int i = ui::SCALE_FACTOR_100P; i < ui::NUM_SCALE_FACTORS; ++i) {
165 if (icon_flags & (1 << i)) {
166 IconInfo icon_info;
167 icon_info.scale_factor = static_cast<ui::ScaleFactor>(i);
168 icon_info.path = GetIconPath(app_path, icon_info.scale_factor);
169 app_info->icons.push_back(icon_info);
170 }
171 }
172 }
173
174 return app_info.Pass();
175 }
176
177 bool ArcAppPrefs::IsRegistered(const std::string& app_id) {
178 const base::DictionaryValue* app = NULL;
179 const base::DictionaryValue* apps = prefs_->GetDictionary(kArcApps);
180 if (!apps || !apps->GetDictionary(app_id, &app)) {
181 return false;
182 }
183 return true;
184 }
185
186 void ArcAppPrefs::OnAppReady(const chromeos::ArcBridgeClient::AppInfo& app) {
187 std::string app_id = GetAppId(app.package, app.activity);
188 bool was_registered = IsRegistered(app_id);
189
190 ScopedArcAppPrefUpdate update(prefs_, app_id);
191 base::DictionaryValue* app_dict = update.Get();
192 app_dict->SetString(kName, app.name);
193 app_dict->SetString(kPackage, app.package);
194 app_dict->SetString(kActivity, app.activity);
195
196 // From now, app is ready.
197 if (!enable_apps_.count(app_id)) {
198 enable_apps_.insert(app_id);
199 }
200
201 AppInfo app_info;
202 app_info.name = app.name;
203 app_info.enabled = true;
204
205 if (was_registered) {
206 FOR_EACH_OBSERVER(Observer,
207 observer_list_,
208 OnAppEnabled(app_id, true));
209 } else {
210 FOR_EACH_OBSERVER(Observer,
211 observer_list_,
212 OnAppRegistered(app_id, app_info));
213 }
214
215 if (!app.icon.empty()) {
216 // Currently only default 100p icon is supported.
217 InstallIcon(app_id, ui::SCALE_FACTOR_100P, app.icon);
218 }
219 }
220
221 void ArcAppPrefs::OnAppsRefreshed(
222 const std::vector<chromeos::ArcBridgeClient::AppInfo>& apps) {
223 std::set<std::string> old_enable_apps_;
224 old_enable_apps_.swap(enable_apps_);
225
226 for (size_t i = 0; i < apps.size(); ++i) {
227 OnAppReady(apps[i]);
228 }
229
230 // Detect unavailable apps after current refresh.
231 std::set<std::string>::const_iterator it;
232 for (it = old_enable_apps_.begin(); it != old_enable_apps_.end(); ++it) {
233 const std::string app_id = *it;
234 if (!enable_apps_.count(app_id)) {
235 FOR_EACH_OBSERVER(Observer,
236 observer_list_,
237 OnAppEnabled(app_id, false));
238 }
239 }
240 }
241
242 void ArcAppPrefs::InstallIcon(const std::string& app_id,
243 ui::ScaleFactor scale_factor,
244 const std::vector<uint8>& contentPng) {
245 base::Closure task = base::Bind(&ArcAppPrefs::InstallIconFromFileThread,
246 base::Unretained(this),
247 app_id,
248 scale_factor,
249 contentPng);
250 content::BrowserThread::PostTask(content::BrowserThread::FILE,
251 FROM_HERE,
252 task);
253 }
254
255 void ArcAppPrefs::InstallIconFromFileThread(
256 const std::string& app_id,
257 ui::ScaleFactor scale_factor,
258 const std::vector<uint8>& contentPng) {
259 DCHECK_CURRENTLY_ON(content::BrowserThread::FILE);
260
261 DCHECK(!contentPng.empty());
262
263 IconInfo icon_info;
264
265 base::FilePath app_path = base_path_.AppendASCII(app_id);
266 base::CreateDirectory(app_path);
267 icon_info.scale_factor = scale_factor;
268 icon_info.path = GetIconPath(app_path, scale_factor);
269
270 int wrote = base::WriteFile(icon_info.path,
271 reinterpret_cast<const char*>(&contentPng[0]),
272 contentPng.size());
273 DCHECK(wrote == static_cast<int>(contentPng.size()));
274
275 base::Closure task = base::Bind(&ArcAppPrefs::OnIconInstalled,
276 base::Unretained(this),
277 app_id,
278 icon_info);
279 content::BrowserThread::PostTask(content::BrowserThread::UI,
280 FROM_HERE,
281 task);
282 }
283
284 void ArcAppPrefs::OnIconInstalled(const std::string& app_id,
285 const IconInfo& icon_info) {
286 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
287
288 FOR_EACH_OBSERVER(Observer,
289 observer_list_,
290 OnAppIconUpdated(app_id, icon_info));
291
292 // Set flag that icon is available for specific scale factor.
293 ScopedArcAppPrefUpdate update(prefs_, app_id);
294 base::DictionaryValue* app_dict = update.Get();
295 int icon_flags = 0;
296 app_dict->GetInteger(kIcons, &icon_flags);
297 icon_flags |= (1 << icon_info.scale_factor);
298 app_dict->SetInteger(kIcons, icon_flags);
299 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698