1 // Copyright 2014 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.
5 #include "chrome/browser/ui/webui/options/supervised_user_import_handler.h"
10 #include "base/prefs/pref_service.h"
11 #include "base/values.h"
12 #include "chrome/browser/browser_process.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/profiles/profile_avatar_icon_util.h"
15 #include "chrome/browser/profiles/profile_info_cache.h"
16 #include "chrome/browser/profiles/profile_manager.h"
17 #include "chrome/browser/signin/signin_error_controller_factory.h"
18 #include "chrome/browser/signin/signin_manager_factory.h"
19 #include "chrome/browser/supervised_user/legacy/supervised_user_shared_settings_service.h"
20 #include "chrome/browser/supervised_user/legacy/supervised_user_shared_settings_service_factory.h"
21 #include "chrome/browser/supervised_user/legacy/supervised_user_sync_service.h"
22 #include "chrome/browser/supervised_user/legacy/supervised_user_sync_service_factory.h"
23 #include "chrome/browser/supervised_user/supervised_user_constants.h"
24 #include "chrome/common/url_constants.h"
25 #include "chrome/grit/generated_resources.h"
26 #include "components/signin/core/browser/signin_error_controller.h"
27 #include "components/signin/core/browser/signin_manager.h"
28 #include "content/public/browser/web_ui.h"
29 #include "grit/theme_resources.h"
33 scoped_ptr
<base::ListValue
> GetAvatarIcons() {
34 scoped_ptr
<base::ListValue
> avatar_icons(new base::ListValue
);
35 for (size_t i
= 0; i
< profiles::GetDefaultAvatarIconCount(); ++i
) {
36 std::string avatar_url
= profiles::GetDefaultAvatarIconUrl(i
);
37 avatar_icons
->Append(new base::StringValue(avatar_url
));
40 return avatar_icons
.Pass();
43 bool ProfileIsLegacySupervised(const base::FilePath
& profile_path
) {
44 const ProfileInfoCache
& cache
=
45 g_browser_process
->profile_manager()->GetProfileInfoCache();
46 size_t index
= cache
.GetIndexOfProfileWithPath(profile_path
);
47 if (index
== std::string::npos
)
49 return cache
.ProfileIsLegacySupervisedAtIndex(index
);
56 SupervisedUserImportHandler::SupervisedUserImportHandler()
57 : profile_observer_(this),
58 signin_error_observer_(this),
59 supervised_user_sync_service_observer_(this),
60 removed_profile_is_supervised_(false),
61 weak_ptr_factory_(this) {
64 SupervisedUserImportHandler::~SupervisedUserImportHandler() {
67 void SupervisedUserImportHandler::GetLocalizedValues(
68 base::DictionaryValue
* localized_strings
) {
69 DCHECK(localized_strings
);
71 static OptionsStringResource resources
[] = {
72 { "supervisedUserImportTitle",
73 IDS_IMPORT_EXISTING_SUPERVISED_USER_TITLE
},
74 { "supervisedUserImportText", IDS_IMPORT_EXISTING_SUPERVISED_USER_TEXT
},
75 { "createNewUserLink", IDS_CREATE_NEW_USER_LINK
},
76 { "supervisedUserImportOk", IDS_IMPORT_EXISTING_SUPERVISED_USER_OK
},
77 { "supervisedUserImportSigninError",
78 IDS_SUPERVISED_USER_IMPORT_SIGN_IN_ERROR
},
79 { "supervisedUserAlreadyOnThisDevice",
80 IDS_SUPERVISED_USER_ALREADY_ON_THIS_DEVICE
},
81 { "noExistingSupervisedUsers", IDS_SUPERVISED_USER_NO_EXISTING_ERROR
},
82 { "supervisedUserSelectAvatarTitle",
83 IDS_SUPERVISED_USER_SELECT_AVATAR_TITLE
},
84 { "supervisedUserSelectAvatarText",
85 IDS_SUPERVISED_USER_SELECT_AVATAR_TEXT
},
86 { "supervisedUserSelectAvatarOk", IDS_SUPERVISED_USER_SELECT_AVATAR_OK
},
89 RegisterStrings(localized_strings
, resources
, arraysize(resources
));
90 localized_strings
->Set("avatarIcons", GetAvatarIcons().release());
93 void SupervisedUserImportHandler::InitializeHandler() {
94 Profile
* profile
= Profile::FromWebUI(web_ui());
95 if (!profile
->IsSupervised()) {
96 profile_observer_
.Add(
97 &g_browser_process
->profile_manager()->GetProfileInfoCache());
98 SupervisedUserSyncService
* sync_service
=
99 SupervisedUserSyncServiceFactory::GetForProfile(profile
);
101 supervised_user_sync_service_observer_
.Add(sync_service
);
102 signin_error_observer_
.Add(
103 SigninErrorControllerFactory::GetForProfile(profile
));
104 SupervisedUserSharedSettingsService
* settings_service
=
105 SupervisedUserSharedSettingsServiceFactory::GetForBrowserContext(
107 subscription_
= settings_service
->Subscribe(
108 base::Bind(&SupervisedUserImportHandler::OnSharedSettingChanged
,
109 weak_ptr_factory_
.GetWeakPtr()));
111 DCHECK(!SupervisedUserSharedSettingsServiceFactory::GetForBrowserContext(
113 DCHECK(!SigninErrorControllerFactory::GetForProfile(profile
));
118 void SupervisedUserImportHandler::RegisterMessages() {
119 web_ui()->RegisterMessageCallback("requestSupervisedUserImportUpdate",
120 base::Bind(&SupervisedUserImportHandler::
121 RequestSupervisedUserImportUpdate
,
122 base::Unretained(this)));
125 void SupervisedUserImportHandler::OnProfileAdded(
126 const base::FilePath
& profile_path
) {
127 // When a supervised profile is added, re-send the list to update the
128 // the "already on this device" status.
129 if (ProfileIsLegacySupervised(profile_path
))
130 FetchSupervisedUsers();
133 void SupervisedUserImportHandler::OnProfileWillBeRemoved(
134 const base::FilePath
& profile_path
) {
135 DCHECK(!removed_profile_is_supervised_
);
136 // When a supervised profile is removed, re-send the list to update the
137 // "already on this device" status. We can't do that right now because the
138 // profile still exists, so defer to OnProfileWasRemoved.
139 if (ProfileIsLegacySupervised(profile_path
))
140 removed_profile_is_supervised_
= true;
143 void SupervisedUserImportHandler::OnProfileWasRemoved(
144 const base::FilePath
& profile_path
,
145 const base::string16
& profile_name
) {
146 if (removed_profile_is_supervised_
) {
147 removed_profile_is_supervised_
= false;
148 FetchSupervisedUsers();
152 void SupervisedUserImportHandler::OnProfileIsOmittedChanged(
153 const base::FilePath
& profile_path
) {
154 if (ProfileIsLegacySupervised(profile_path
))
155 FetchSupervisedUsers();
158 void SupervisedUserImportHandler::OnSupervisedUsersChanged() {
159 FetchSupervisedUsers();
162 void SupervisedUserImportHandler::FetchSupervisedUsers() {
163 web_ui()->CallJavascriptFunction(
164 "options.SupervisedUserListData.resetPromise");
165 RequestSupervisedUserImportUpdate(NULL
);
168 void SupervisedUserImportHandler::RequestSupervisedUserImportUpdate(
169 const base::ListValue
* /* args */) {
170 if (Profile::FromWebUI(web_ui())->IsSupervised())
173 if (!IsAccountConnected() || HasAuthError()) {
174 ClearSupervisedUsersAndShowError();
176 SupervisedUserSyncService
* supervised_user_sync_service
=
177 SupervisedUserSyncServiceFactory::GetForProfile(
178 Profile::FromWebUI(web_ui()));
179 if (supervised_user_sync_service
) {
180 supervised_user_sync_service
->GetSupervisedUsersAsync(
181 base::Bind(&SupervisedUserImportHandler::SendExistingSupervisedUsers
,
182 weak_ptr_factory_
.GetWeakPtr()));
187 void SupervisedUserImportHandler::SendExistingSupervisedUsers(
188 const base::DictionaryValue
* dict
) {
190 const ProfileInfoCache
& cache
=
191 g_browser_process
->profile_manager()->GetProfileInfoCache();
193 // Collect the ids of local supervised user profiles.
194 std::set
<std::string
> supervised_user_ids
;
195 for (size_t i
= 0; i
< cache
.GetNumberOfProfiles(); ++i
) {
196 // Filter out omitted profiles. These are currently being imported, and
197 // shouldn't show up as "already on this device" just yet.
198 if (cache
.ProfileIsLegacySupervisedAtIndex(i
) &&
199 !cache
.IsOmittedProfileAtIndex(i
)) {
200 supervised_user_ids
.insert(cache
.GetSupervisedUserIdOfProfileAtIndex(i
));
204 base::ListValue supervised_users
;
205 Profile
* profile
= Profile::FromWebUI(web_ui());
206 SupervisedUserSharedSettingsService
* service
=
207 SupervisedUserSharedSettingsServiceFactory::GetForBrowserContext(profile
);
208 for (base::DictionaryValue::Iterator
it(*dict
); !it
.IsAtEnd(); it
.Advance()) {
209 const base::DictionaryValue
* value
= NULL
;
210 bool success
= it
.value().GetAsDictionary(&value
);
213 value
->GetString(SupervisedUserSyncService::kName
, &name
);
215 base::DictionaryValue
* supervised_user
= new base::DictionaryValue
;
216 supervised_user
->SetString("id", it
.key());
217 supervised_user
->SetString("name", name
);
219 int avatar_index
= SupervisedUserSyncService::kNoAvatar
;
220 const base::Value
* avatar_index_value
=
221 service
->GetValue(it
.key(), supervised_users::kChromeAvatarIndex
);
222 if (avatar_index_value
) {
223 success
= avatar_index_value
->GetAsInteger(&avatar_index
);
225 // Check if there is a legacy avatar index stored.
226 std::string avatar_str
;
227 value
->GetString(SupervisedUserSyncService::kChromeAvatar
, &avatar_str
);
229 SupervisedUserSyncService::GetAvatarIndex(avatar_str
, &avatar_index
);
232 supervised_user
->SetBoolean(
234 avatar_index
== SupervisedUserSyncService::kNoAvatar
);
236 std::string supervised_user_icon
=
237 std::string(chrome::kChromeUIThemeURL
) +
238 "IDR_SUPERVISED_USER_PLACEHOLDER";
239 std::string avatar_url
=
240 avatar_index
== SupervisedUserSyncService::kNoAvatar
?
241 supervised_user_icon
:
242 profiles::GetDefaultAvatarIconUrl(avatar_index
);
243 supervised_user
->SetString("iconURL", avatar_url
);
244 bool on_current_device
=
245 supervised_user_ids
.find(it
.key()) != supervised_user_ids
.end();
246 supervised_user
->SetBoolean("onCurrentDevice", on_current_device
);
248 supervised_users
.Append(supervised_user
);
251 web_ui()->CallJavascriptFunction(
252 "options.SupervisedUserListData.receiveExistingSupervisedUsers",
256 void SupervisedUserImportHandler::ClearSupervisedUsersAndShowError() {
257 web_ui()->CallJavascriptFunction(
258 "options.SupervisedUserListData.onSigninError");
261 bool SupervisedUserImportHandler::IsAccountConnected() const {
262 Profile
* profile
= Profile::FromWebUI(web_ui());
263 SigninManagerBase
* signin_manager
=
264 SigninManagerFactory::GetForProfile(profile
);
265 return signin_manager
&& signin_manager
->IsAuthenticated();
268 bool SupervisedUserImportHandler::HasAuthError() const {
269 Profile
* profile
= Profile::FromWebUI(web_ui());
270 SigninErrorController
* error_controller
=
271 SigninErrorControllerFactory::GetForProfile(profile
);
272 if (!error_controller
)
275 GoogleServiceAuthError::State state
= error_controller
->auth_error().state();
277 return state
== GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS
||
278 state
== GoogleServiceAuthError::USER_NOT_SIGNED_UP
||
279 state
== GoogleServiceAuthError::ACCOUNT_DELETED
||
280 state
== GoogleServiceAuthError::ACCOUNT_DISABLED
;
283 void SupervisedUserImportHandler::OnSharedSettingChanged(
284 const std::string
& supervised_user_id
,
285 const std::string
& key
) {
286 if (key
== supervised_users::kChromeAvatarIndex
)
287 FetchSupervisedUsers();
290 void SupervisedUserImportHandler::OnErrorChanged() {
291 FetchSupervisedUsers();
294 } // namespace options