OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h" | 5 #include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 #include <set> | 8 #include <set> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
12 #include "base/memory/scoped_ptr.h" | |
13 #include "base/path_service.h" | 12 #include "base/path_service.h" |
14 #include "base/prefs/pref_registry_simple.h" | 13 #include "base/prefs/pref_registry_simple.h" |
15 #include "base/stl_util.h" | 14 #include "base/stl_util.h" |
16 #include "base/values.h" | |
17 #include "chrome/browser/chromeos/app_mode/kiosk_app_data.h" | 15 #include "chrome/browser/chromeos/app_mode/kiosk_app_data.h" |
18 #include "chrome/browser/chromeos/app_mode/kiosk_app_manager_observer.h" | 16 #include "chrome/browser/chromeos/app_mode/kiosk_app_manager_observer.h" |
19 #include "chrome/browser/chromeos/login/user_manager.h" | 17 #include "chrome/browser/chromeos/policy/device_local_account.h" |
20 #include "chrome/browser/chromeos/settings/cros_settings.h" | 18 #include "chrome/browser/chromeos/settings/cros_settings.h" |
19 #include "chrome/browser/chromeos/settings/cros_settings_names.h" | |
21 #include "chrome/common/chrome_notification_types.h" | 20 #include "chrome/common/chrome_notification_types.h" |
22 #include "chrome/common/chrome_paths.h" | 21 #include "chrome/common/chrome_paths.h" |
23 #include "chromeos/cryptohome/async_method_caller.h" | 22 #include "chromeos/cryptohome/async_method_caller.h" |
24 | 23 |
25 namespace chromeos { | 24 namespace chromeos { |
26 | 25 |
27 namespace { | 26 namespace { |
28 | 27 |
29 std::string FormatKioskAppUserId(const std::string& app_id) { | 28 // Domain that is used for kiosk-app account IDs. |
30 return app_id + '@' + UserManager::kKioskAppUserDomain; | 29 const char kKioskAppAccountDomain[] = "kiosk-apps"; |
30 | |
31 std::string GenerateKioskAppAccountId(const std::string& app_id) { | |
32 return app_id + '@' + kKioskAppAccountDomain; | |
31 } | 33 } |
32 | 34 |
33 void OnRemoveAppCryptohomeComplete(const std::string& app, | 35 void OnRemoveAppCryptohomeComplete(const std::string& app, |
34 bool success, | 36 bool success, |
35 cryptohome::MountError return_code) { | 37 cryptohome::MountError return_code) { |
36 if (!success) { | 38 if (!success) { |
37 LOG(ERROR) << "Remove cryptohome for " << app | 39 LOG(ERROR) << "Remove cryptohome for " << app |
38 << " failed, return code: " << return_code; | 40 << " failed, return code: " << return_code; |
39 } | 41 } |
40 } | 42 } |
41 | 43 |
42 // Decodes a device-local account dictionary and extracts the |account_id| and | |
43 // |app_id| if decoding is successful and the entry refers to a Kiosk App. | |
44 bool DecodeDeviceLocalAccount(const base::Value* account_spec, | |
45 std::string* account_id, | |
46 std::string* app_id) { | |
47 const base::DictionaryValue* account_dict = NULL; | |
48 if (!account_spec->GetAsDictionary(&account_dict)) { | |
49 NOTREACHED(); | |
50 return false; | |
51 } | |
52 | |
53 if (!account_dict->GetStringWithoutPathExpansion( | |
54 kAccountsPrefDeviceLocalAccountsKeyId, account_id)) { | |
55 LOG(ERROR) << "Account ID missing"; | |
56 return false; | |
57 } | |
58 | |
59 int type; | |
60 if (!account_dict->GetIntegerWithoutPathExpansion( | |
61 kAccountsPrefDeviceLocalAccountsKeyType, &type) || | |
62 type != DEVICE_LOCAL_ACCOUNT_TYPE_KIOSK_APP) { | |
63 // Not a kiosk app. | |
64 return false; | |
65 } | |
66 | |
67 if (!account_dict->GetStringWithoutPathExpansion( | |
68 kAccountsPrefDeviceLocalAccountsKeyKioskAppId, app_id)) { | |
69 LOG(ERROR) << "Kiosk app id missing for " << *account_id; | |
70 return false; | |
71 } | |
72 | |
73 return true; | |
74 } | |
75 | |
76 } // namespace | 44 } // namespace |
77 | 45 |
78 // static | 46 // static |
79 const char KioskAppManager::kKioskDictionaryName[] = "kiosk"; | 47 const char KioskAppManager::kKioskDictionaryName[] = "kiosk"; |
80 const char KioskAppManager::kKeyApps[] = "apps"; | 48 const char KioskAppManager::kKeyApps[] = "apps"; |
81 const char KioskAppManager::kIconCacheDir[] = "kiosk"; | 49 const char KioskAppManager::kIconCacheDir[] = "kiosk"; |
82 | 50 |
83 // static | 51 // static |
84 static base::LazyInstance<KioskAppManager> instance = LAZY_INSTANCE_INITIALIZER; | 52 static base::LazyInstance<KioskAppManager> instance = LAZY_INSTANCE_INITIALIZER; |
85 KioskAppManager* KioskAppManager::Get() { | 53 KioskAppManager* KioskAppManager::Get() { |
86 return instance.Pointer(); | 54 return instance.Pointer(); |
87 } | 55 } |
88 | 56 |
89 // static | 57 // static |
90 void KioskAppManager::Shutdown() { | 58 void KioskAppManager::Shutdown() { |
91 if (instance == NULL) | 59 if (instance == NULL) |
92 return; | 60 return; |
93 | 61 |
94 instance.Pointer()->CleanUp(); | 62 instance.Pointer()->CleanUp(); |
95 } | 63 } |
96 | 64 |
97 // static | 65 // static |
98 void KioskAppManager::RegisterPrefs(PrefRegistrySimple* registry) { | 66 void KioskAppManager::RegisterPrefs(PrefRegistrySimple* registry) { |
99 registry->RegisterDictionaryPref(kKioskDictionaryName); | 67 registry->RegisterDictionaryPref(kKioskDictionaryName); |
100 } | 68 } |
101 | 69 |
102 KioskAppManager::App::App(const KioskAppData& data) | 70 KioskAppManager::App::App(const KioskAppData& data) |
103 : id(data.id()), | 71 : id(data.app_id()), |
104 name(data.name()), | 72 name(data.name()), |
105 icon(data.icon()), | 73 icon(data.icon()), |
106 is_loading(data.IsLoading()) { | 74 is_loading(data.IsLoading()) { |
107 } | 75 } |
108 | 76 |
109 KioskAppManager::App::App() : is_loading(false) {} | 77 KioskAppManager::App::App() : is_loading(false) {} |
110 KioskAppManager::App::~App() {} | 78 KioskAppManager::App::~App() {} |
111 | 79 |
112 std::string KioskAppManager::GetAutoLaunchApp() const { | 80 std::string KioskAppManager::GetAutoLaunchApp() const { |
113 return auto_launch_app_id_; | 81 return auto_launch_app_id_; |
114 } | 82 } |
115 | 83 |
116 void KioskAppManager::SetAutoLaunchApp(const std::string& app_id) { | 84 void KioskAppManager::SetAutoLaunchApp(const std::string& app_id) { |
117 CrosSettings::Get()->SetString( | 85 CrosSettings::Get()->SetString( |
118 kAccountsPrefDeviceLocalAccountAutoLoginId, | 86 kAccountsPrefDeviceLocalAccountAutoLoginId, |
119 app_id.empty() ? std::string() : FormatKioskAppUserId(app_id)); | 87 app_id.empty() ? std::string() : GenerateKioskAppAccountId(app_id)); |
120 CrosSettings::Get()->SetInteger( | 88 CrosSettings::Get()->SetInteger( |
121 kAccountsPrefDeviceLocalAccountAutoLoginDelay, 0); | 89 kAccountsPrefDeviceLocalAccountAutoLoginDelay, 0); |
122 } | 90 } |
123 | 91 |
124 void KioskAppManager::AddApp(const std::string& app_id) { | 92 void KioskAppManager::AddApp(const std::string& app_id) { |
125 CrosSettings* cros_settings = CrosSettings::Get(); | 93 std::vector<policy::DeviceLocalAccount> device_local_accounts = |
126 const base::ListValue* accounts_list = NULL; | 94 policy::GetDeviceLocalAccounts(CrosSettings::Get()); |
127 cros_settings->GetList(kAccountsPrefDeviceLocalAccounts, &accounts_list); | |
128 | 95 |
129 // Don't insert if the app if it's already in the list. | 96 // Don't insert if the app if it's already in the list. |
130 base::ListValue new_accounts_list; | 97 for (std::vector<policy::DeviceLocalAccount>::const_iterator |
131 if (accounts_list) { | 98 it = device_local_accounts.begin(); |
132 for (base::ListValue::const_iterator entry(accounts_list->begin()); | 99 it != device_local_accounts.end(); ++it) { |
133 entry != accounts_list->end(); ++entry) { | 100 if (it->type == policy::DeviceLocalAccount::TYPE_KIOSK_APP && |
134 std::string account_id; | 101 it->kiosk_app_id == app_id) { |
135 std::string kiosk_app_id; | 102 return; |
136 if (DecodeDeviceLocalAccount(*entry, &account_id, &kiosk_app_id) && | 103 } |
137 kiosk_app_id == app_id) { | 104 } |
138 return; | 105 device_local_accounts.push_back(policy::DeviceLocalAccount( |
139 } | 106 policy::DeviceLocalAccount::TYPE_KIOSK_APP, |
140 new_accounts_list.Append((*entry)->DeepCopy()); | 107 GenerateKioskAppAccountId(app_id), |
108 app_id, | |
109 std::string())); | |
110 | |
111 policy::SetDeviceLocalAccounts(CrosSettings::Get(), device_local_accounts); | |
112 } | |
113 | |
114 void KioskAppManager::RemoveApp(const std::string& app_id) { | |
115 std::vector<policy::DeviceLocalAccount> device_local_accounts = | |
116 policy::GetDeviceLocalAccounts(CrosSettings::Get()); | |
117 if (device_local_accounts.empty()) | |
118 return; | |
119 | |
120 // Remove entries that match |app_id|. | |
121 for (std::vector<policy::DeviceLocalAccount>::iterator | |
122 it = device_local_accounts.begin(); | |
123 it != device_local_accounts.end(); ) { | |
124 if (it->type == policy::DeviceLocalAccount::TYPE_KIOSK_APP && | |
125 it->kiosk_app_id == app_id) { | |
126 it = device_local_accounts.erase(it); | |
xiyuan
2013/05/17 15:46:52
nit: we could break out here since kiosk app id sh
bartfab (slow)
2013/05/17 16:08:47
Done.
| |
127 } else { | |
128 ++it; | |
141 } | 129 } |
142 } | 130 } |
143 | 131 |
144 // Add the new account. | 132 policy::SetDeviceLocalAccounts(CrosSettings::Get(), device_local_accounts); |
145 scoped_ptr<base::DictionaryValue> new_entry(new base::DictionaryValue()); | |
146 new_entry->SetStringWithoutPathExpansion( | |
147 kAccountsPrefDeviceLocalAccountsKeyId, FormatKioskAppUserId(app_id)); | |
148 new_entry->SetIntegerWithoutPathExpansion( | |
149 kAccountsPrefDeviceLocalAccountsKeyType, | |
150 DEVICE_LOCAL_ACCOUNT_TYPE_KIOSK_APP); | |
151 new_entry->SetStringWithoutPathExpansion( | |
152 kAccountsPrefDeviceLocalAccountsKeyKioskAppId, app_id); | |
153 new_accounts_list.Append(new_entry.release()); | |
154 cros_settings->Set(kAccountsPrefDeviceLocalAccounts, new_accounts_list); | |
155 } | |
156 | |
157 void KioskAppManager::RemoveApp(const std::string& app_id) { | |
158 CrosSettings* cros_settings = CrosSettings::Get(); | |
159 const base::ListValue* accounts_list = NULL; | |
160 cros_settings->GetList(kAccountsPrefDeviceLocalAccounts, &accounts_list); | |
161 if (!accounts_list) | |
162 return; | |
163 | |
164 // Duplicate the list, filtering out entries that match |app_id|. | |
165 base::ListValue new_accounts_list; | |
166 for (base::ListValue::const_iterator entry(accounts_list->begin()); | |
167 entry != accounts_list->end(); ++entry) { | |
168 std::string account_id; | |
169 std::string kiosk_app_id; | |
170 if (DecodeDeviceLocalAccount(*entry, &account_id, &kiosk_app_id) && | |
171 kiosk_app_id == app_id) { | |
172 continue; | |
173 } | |
174 new_accounts_list.Append((*entry)->DeepCopy()); | |
175 } | |
176 | |
177 cros_settings->Set(kAccountsPrefDeviceLocalAccounts, new_accounts_list); | |
178 } | 133 } |
179 | 134 |
180 void KioskAppManager::GetApps(Apps* apps) const { | 135 void KioskAppManager::GetApps(Apps* apps) const { |
181 apps->reserve(apps_.size()); | 136 apps->reserve(apps_.size()); |
182 for (size_t i = 0; i < apps_.size(); ++i) | 137 for (size_t i = 0; i < apps_.size(); ++i) |
183 apps->push_back(App(*apps_[i])); | 138 apps->push_back(App(*apps_[i])); |
184 } | 139 } |
185 | 140 |
186 bool KioskAppManager::GetApp(const std::string& app_id, App* app) const { | 141 bool KioskAppManager::GetApp(const std::string& app_id, App* app) const { |
187 const KioskAppData* data = GetAppData(app_id); | 142 const KioskAppData* data = GetAppData(app_id); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
234 kAccountsPrefDeviceLocalAccounts, this); | 189 kAccountsPrefDeviceLocalAccounts, this); |
235 CrosSettings::Get()->RemoveSettingsObserver( | 190 CrosSettings::Get()->RemoveSettingsObserver( |
236 kAccountsPrefDeviceLocalAccountAutoLoginId, this); | 191 kAccountsPrefDeviceLocalAccountAutoLoginId, this); |
237 apps_.clear(); | 192 apps_.clear(); |
238 } | 193 } |
239 | 194 |
240 const KioskAppData* KioskAppManager::GetAppData( | 195 const KioskAppData* KioskAppManager::GetAppData( |
241 const std::string& app_id) const { | 196 const std::string& app_id) const { |
242 for (size_t i = 0; i < apps_.size(); ++i) { | 197 for (size_t i = 0; i < apps_.size(); ++i) { |
243 const KioskAppData* data = apps_[i]; | 198 const KioskAppData* data = apps_[i]; |
244 if (data->id() == app_id) | 199 if (data->app_id() == app_id) |
245 return data; | 200 return data; |
246 } | 201 } |
247 | 202 |
248 return NULL; | 203 return NULL; |
249 } | 204 } |
250 | 205 |
251 void KioskAppManager::UpdateAppData() { | 206 void KioskAppManager::UpdateAppData() { |
252 // Gets app id to data mapping for existing apps. | 207 // Gets app id to data mapping for existing apps. |
253 std::map<std::string, KioskAppData*> old_apps; | 208 std::map<std::string, KioskAppData*> old_apps; |
254 for (size_t i = 0; i < apps_.size(); ++i) | 209 for (size_t i = 0; i < apps_.size(); ++i) |
255 old_apps[apps_[i]->id()] = apps_[i]; | 210 old_apps[apps_[i]->app_id()] = apps_[i]; |
256 apps_.weak_clear(); // |old_apps| takes ownership | 211 apps_.weak_clear(); // |old_apps| takes ownership |
257 | 212 |
258 auto_launch_app_id_.clear(); | 213 auto_launch_app_id_.clear(); |
259 std::string auto_login_account_id; | 214 std::string auto_login_account_id; |
260 CrosSettings::Get()->GetString(kAccountsPrefDeviceLocalAccountAutoLoginId, | 215 CrosSettings::Get()->GetString(kAccountsPrefDeviceLocalAccountAutoLoginId, |
261 &auto_login_account_id); | 216 &auto_login_account_id); |
262 | 217 |
263 const base::ListValue* local_accounts; | 218 // Re-populates |apps_| and reuses existing KioskAppData when possible. |
264 if (CrosSettings::Get()->GetList(kAccountsPrefDeviceLocalAccounts, | 219 const std::vector<policy::DeviceLocalAccount> device_local_accounts = |
265 &local_accounts)) { | 220 policy::GetDeviceLocalAccounts(CrosSettings::Get()); |
266 // Re-populates |apps_| and reuses existing KioskAppData when possible. | 221 for (std::vector<policy::DeviceLocalAccount>::const_iterator |
267 for (base::ListValue::const_iterator account(local_accounts->begin()); | 222 it = device_local_accounts.begin(); |
268 account != local_accounts->end(); ++account) { | 223 it != device_local_accounts.end(); ++it) { |
269 std::string account_id; | 224 if (it->type != policy::DeviceLocalAccount::TYPE_KIOSK_APP) |
270 std::string kiosk_app_id; | 225 continue; |
271 if (!DecodeDeviceLocalAccount(*account, &account_id, &kiosk_app_id)) | |
272 continue; | |
273 | 226 |
274 if (account_id == auto_login_account_id) | 227 if (it->account_id == auto_login_account_id) |
275 auto_launch_app_id_ = kiosk_app_id; | 228 auto_launch_app_id_ = it->kiosk_app_id; |
276 | 229 |
277 // TODO(mnissler): Support non-CWS update URLs. | 230 // TODO(mnissler): Support non-CWS update URLs. |
278 | 231 |
279 std::map<std::string, KioskAppData*>::iterator old_it = | 232 std::map<std::string, KioskAppData*>::iterator old_it = |
280 old_apps.find(kiosk_app_id); | 233 old_apps.find(it->kiosk_app_id); |
281 if (old_it != old_apps.end()) { | 234 if (old_it != old_apps.end()) { |
282 apps_.push_back(old_it->second); | 235 apps_.push_back(old_it->second); |
283 old_apps.erase(old_it); | 236 old_apps.erase(old_it); |
284 } else { | 237 } else { |
285 KioskAppData* new_app = new KioskAppData(this, kiosk_app_id); | 238 KioskAppData* new_app = new KioskAppData(this, it->kiosk_app_id); |
286 apps_.push_back(new_app); // Takes ownership of |new_app|. | 239 apps_.push_back(new_app); // Takes ownership of |new_app|. |
287 new_app->Load(); | 240 new_app->Load(); |
288 } | |
289 } | 241 } |
290 } | 242 } |
291 | 243 |
292 // Clears cache and deletes the remaining old data. | 244 // Clears cache and deletes the remaining old data. |
293 for (std::map<std::string, KioskAppData*>::iterator it = old_apps.begin(); | 245 for (std::map<std::string, KioskAppData*>::iterator it = old_apps.begin(); |
294 it != old_apps.end(); ++it) { | 246 it != old_apps.end(); ++it) { |
295 it->second->ClearCache(); | 247 it->second->ClearCache(); |
296 cryptohome::AsyncMethodCaller::GetInstance()->AsyncRemove( | 248 cryptohome::AsyncMethodCaller::GetInstance()->AsyncRemove( |
297 it->first, base::Bind(&OnRemoveAppCryptohomeComplete, it->first)); | 249 it->first, base::Bind(&OnRemoveAppCryptohomeComplete, it->first)); |
298 } | 250 } |
(...skipping 23 matching lines...) Expand all Loading... | |
322 } | 274 } |
323 | 275 |
324 void KioskAppManager::OnKioskAppDataLoadFailure(const std::string& app_id) { | 276 void KioskAppManager::OnKioskAppDataLoadFailure(const std::string& app_id) { |
325 FOR_EACH_OBSERVER(KioskAppManagerObserver, | 277 FOR_EACH_OBSERVER(KioskAppManagerObserver, |
326 observers_, | 278 observers_, |
327 OnKioskAppDataLoadFailure(app_id)); | 279 OnKioskAppDataLoadFailure(app_id)); |
328 RemoveApp(app_id); | 280 RemoveApp(app_id); |
329 } | 281 } |
330 | 282 |
331 } // namespace chromeos | 283 } // namespace chromeos |
OLD | NEW |