| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 /** | 5 /** |
| 6 * @fileoverview 'create-profile' is a page that contains controls for creating | 6 * @fileoverview 'create-profile' is a page that contains controls for creating |
| 7 * a (optionally supervised) profile, including choosing a name, and an avatar. | 7 * a (optionally supervised) profile, including choosing a name, and an avatar. |
| 8 */ | 8 */ |
| 9 | 9 |
| 10 /** @typedef {{url: string, label:string}} */ | 10 /** @typedef {{url: string, label:string}} */ |
| 11 var AvatarIcon; | 11 var AvatarIcon; |
| 12 | 12 |
| 13 (function() { | 13 (function() { |
| 14 /** | 14 /** |
| 15 * Sentinel signed-in user's index value. | 15 * Sentinel signed-in user's index value. |
| 16 * @const {number} | 16 * @const {number} |
| 17 */ | 17 */ |
| 18 var NO_USER_SELECTED = -1; | 18 var NO_USER_SELECTED = -1; |
| 19 | 19 |
| 20 Polymer({ | 20 Polymer({ |
| 21 is: 'create-profile', | 21 is: 'create-profile', |
| 22 | 22 |
| 23 behaviors: [ | 23 behaviors: [I18nBehavior, WebUIListenerBehavior], |
| 24 I18nBehavior, | 24 |
| 25 WebUIListenerBehavior | 25 properties: { |
| 26 ], | 26 /** |
| 27 | 27 * The current profile name. |
| 28 properties: { | 28 * @private {string} |
| 29 /** | 29 */ |
| 30 * The current profile name. | 30 profileName_: {type: String, value: ''}, |
| 31 * @private {string} | 31 |
| 32 */ | 32 /** |
| 33 profileName_: { | 33 * The list of available profile icon Urls and labels. |
| 34 type: String, | 34 * @private {!Array<!AvatarIcon>} |
| 35 value: '' | 35 */ |
| 36 }, | 36 availableIcons_: { |
| 37 | 37 type: Array, |
| 38 /** | 38 value: function() { |
| 39 * The list of available profile icon Urls and labels. | 39 return []; |
| 40 * @private {!Array<!AvatarIcon>} | 40 } |
| 41 */ | |
| 42 availableIcons_: { | |
| 43 type: Array, | |
| 44 value: function() { return []; } | |
| 45 }, | |
| 46 | |
| 47 /** | |
| 48 * The currently selected profile icon URL. May be a data URL. | |
| 49 * @private {string} | |
| 50 */ | |
| 51 profileIconUrl_: { | |
| 52 type: String, | |
| 53 value: '' | |
| 54 }, | |
| 55 | |
| 56 /** | |
| 57 * True if the existing supervised users are being loaded. | |
| 58 * @private {boolean} | |
| 59 */ | |
| 60 loadingSupervisedUsers_: { | |
| 61 type: Boolean, | |
| 62 value: false | |
| 63 }, | |
| 64 | |
| 65 /** | |
| 66 * True if a profile is being created or imported. | |
| 67 * @private {boolean} | |
| 68 */ | |
| 69 createInProgress_: { | |
| 70 type: Boolean, | |
| 71 value: false | |
| 72 }, | |
| 73 | |
| 74 /** | |
| 75 * True if the error/warning message is displaying. | |
| 76 * @private {boolean} | |
| 77 */ | |
| 78 isMessageVisble_: { | |
| 79 type: Boolean, | |
| 80 value: false | |
| 81 }, | |
| 82 | |
| 83 /** | |
| 84 * The current error/warning message. | |
| 85 * @private {string} | |
| 86 */ | |
| 87 message_: { | |
| 88 type: String, | |
| 89 value: '' | |
| 90 }, | |
| 91 | |
| 92 /** | |
| 93 * if true, a desktop shortcut will be created for the new profile. | |
| 94 * @private {boolean} | |
| 95 */ | |
| 96 createShortcut_: { | |
| 97 type: Boolean, | |
| 98 value: true | |
| 99 }, | |
| 100 | |
| 101 /** | |
| 102 * True if the new profile is a supervised profile. | |
| 103 * @private {boolean} | |
| 104 */ | |
| 105 isSupervised_: { | |
| 106 type: Boolean, | |
| 107 value: false | |
| 108 }, | |
| 109 | |
| 110 /** | |
| 111 * The list of usernames and profile paths for currently signed-in users. | |
| 112 * @private {!Array<!SignedInUser>} | |
| 113 */ | |
| 114 signedInUsers_: { | |
| 115 type: Array, | |
| 116 value: function() { return []; } | |
| 117 }, | |
| 118 | |
| 119 /** | |
| 120 * Index of the selected signed-in user. | |
| 121 * @private {number} | |
| 122 */ | |
| 123 signedInUserIndex_: { | |
| 124 type: Number, | |
| 125 value: NO_USER_SELECTED | |
| 126 }, | |
| 127 | |
| 128 /** @private {!signin.ProfileBrowserProxy} */ | |
| 129 browserProxy_: Object, | |
| 130 | |
| 131 /** | |
| 132 * True if the profile shortcuts feature is enabled. | |
| 133 * @private | |
| 134 */ | |
| 135 isProfileShortcutsEnabled_: { | |
| 136 type: Boolean, | |
| 137 value: function() { | |
| 138 return loadTimeData.getBoolean('profileShortcutsEnabled'); | |
| 139 }, | 41 }, |
| 140 readOnly: true | 42 |
| 141 }, | 43 /** |
| 142 | 44 * The currently selected profile icon URL. May be a data URL. |
| 143 /** | 45 * @private {string} |
| 144 * True if the force sign in policy is enabled. | 46 */ |
| 145 * @private {boolean} | 47 profileIconUrl_: {type: String, value: ''}, |
| 146 */ | 48 |
| 147 isForceSigninEnabled_: { | 49 /** |
| 148 type: Boolean, | 50 * True if the existing supervised users are being loaded. |
| 149 value: function() { | 51 * @private {boolean} |
| 150 return loadTimeData.getBoolean('isForceSigninEnabled'); | 52 */ |
| 53 loadingSupervisedUsers_: {type: Boolean, value: false}, |
| 54 |
| 55 /** |
| 56 * True if a profile is being created or imported. |
| 57 * @private {boolean} |
| 58 */ |
| 59 createInProgress_: {type: Boolean, value: false}, |
| 60 |
| 61 /** |
| 62 * True if the error/warning message is displaying. |
| 63 * @private {boolean} |
| 64 */ |
| 65 isMessageVisble_: {type: Boolean, value: false}, |
| 66 |
| 67 /** |
| 68 * The current error/warning message. |
| 69 * @private {string} |
| 70 */ |
| 71 message_: {type: String, value: ''}, |
| 72 |
| 73 /** |
| 74 * if true, a desktop shortcut will be created for the new profile. |
| 75 * @private {boolean} |
| 76 */ |
| 77 createShortcut_: {type: Boolean, value: true}, |
| 78 |
| 79 /** |
| 80 * True if the new profile is a supervised profile. |
| 81 * @private {boolean} |
| 82 */ |
| 83 isSupervised_: {type: Boolean, value: false}, |
| 84 |
| 85 /** |
| 86 * The list of usernames and profile paths for currently signed-in users. |
| 87 * @private {!Array<!SignedInUser>} |
| 88 */ |
| 89 signedInUsers_: { |
| 90 type: Array, |
| 91 value: function() { |
| 92 return []; |
| 93 } |
| 151 }, | 94 }, |
| 152 } | 95 |
| 153 }, | 96 /** |
| 154 | 97 * Index of the selected signed-in user. |
| 155 listeners: { | 98 * @private {number} |
| 156 'tap': 'onTap_', | 99 */ |
| 157 'importUserPopup.import': 'onImportUserPopupImport_' | 100 signedInUserIndex_: {type: Number, value: NO_USER_SELECTED}, |
| 158 }, | 101 |
| 159 | 102 /** @private {!signin.ProfileBrowserProxy} */ |
| 160 /** @override */ | 103 browserProxy_: Object, |
| 161 created: function() { | 104 |
| 162 this.browserProxy_ = signin.ProfileBrowserProxyImpl.getInstance(); | 105 /** |
| 163 }, | 106 * True if the profile shortcuts feature is enabled. |
| 164 | 107 * @private |
| 165 /** @override */ | 108 */ |
| 166 ready: function() { | 109 isProfileShortcutsEnabled_: { |
| 167 this.addWebUIListener( | 110 type: Boolean, |
| 168 'create-profile-success', this.handleSuccess_.bind(this)); | 111 value: function() { |
| 169 this.addWebUIListener( | 112 return loadTimeData.getBoolean('profileShortcutsEnabled'); |
| 170 'create-profile-warning', this.handleMessage_.bind(this)); | 113 }, |
| 171 this.addWebUIListener( | 114 readOnly: true |
| 172 'create-profile-error', this.handleMessage_.bind(this)); | 115 }, |
| 173 this.addWebUIListener( | 116 |
| 174 'profile-icons-received', this.handleProfileIcons_.bind(this)); | 117 /** |
| 175 this.addWebUIListener( | 118 * True if the force sign in policy is enabled. |
| 176 'profile-defaults-received', this.handleProfileDefaults_.bind(this)); | 119 * @private {boolean} |
| 177 this.addWebUIListener( | 120 */ |
| 178 'signedin-users-received', this.handleSignedInUsers_.bind(this)); | 121 isForceSigninEnabled_: { |
| 179 | 122 type: Boolean, |
| 180 this.browserProxy_.getAvailableIcons(); | 123 value: function() { |
| 181 this.browserProxy_.getSignedInUsers(); | 124 return loadTimeData.getBoolean('isForceSigninEnabled'); |
| 182 }, | 125 }, |
| 183 | 126 } |
| 184 /** @override */ | 127 }, |
| 185 attached: function() { | 128 |
| 186 this.$.nameInput.focus(); | 129 listeners: |
| 187 }, | 130 {'tap': 'onTap_', 'importUserPopup.import': 'onImportUserPopupImport_'}, |
| 188 | 131 |
| 189 /** | 132 /** @override */ |
| 190 * Handles tap events from: | 133 created: function() { |
| 191 * - links within dynamic warning/error messages pushed from the browser. | 134 this.browserProxy_ = signin.ProfileBrowserProxyImpl.getInstance(); |
| 192 * - the 'noSignedInUserMessage' i18n string. | 135 }, |
| 193 * @param {!Event} event | 136 |
| 194 * @private | 137 /** @override */ |
| 195 */ | 138 ready: function() { |
| 196 onTap_: function(event) { | 139 this.addWebUIListener( |
| 197 var element = Polymer.dom(event).rootTarget; | 140 'create-profile-success', this.handleSuccess_.bind(this)); |
| 198 | 141 this.addWebUIListener( |
| 199 if (element.id == 'supervised-user-import-existing') { | 142 'create-profile-warning', this.handleMessage_.bind(this)); |
| 200 this.onImportUserTap_(event); | 143 this.addWebUIListener( |
| 201 event.preventDefault(); | 144 'create-profile-error', this.handleMessage_.bind(this)); |
| 202 } else if (element.id == 'sign-in-to-chrome') { | 145 this.addWebUIListener( |
| 203 this.browserProxy_.openUrlInLastActiveProfileBrowser(element.href); | 146 'profile-icons-received', this.handleProfileIcons_.bind(this)); |
| 204 event.preventDefault(); | 147 this.addWebUIListener( |
| 205 } else if (element.id == 'reauth') { | 148 'profile-defaults-received', this.handleProfileDefaults_.bind(this)); |
| 206 var elementData = /** @type {{userEmail: string}} */ (element.dataset); | 149 this.addWebUIListener( |
| 207 this.browserProxy_.authenticateCustodian(elementData.userEmail); | 150 'signedin-users-received', this.handleSignedInUsers_.bind(this)); |
| 208 this.hideMessage_(); | 151 |
| 209 event.preventDefault(); | 152 this.browserProxy_.getAvailableIcons(); |
| 210 } | 153 this.browserProxy_.getSignedInUsers(); |
| 211 }, | 154 }, |
| 212 | 155 |
| 213 /** | 156 /** @override */ |
| 214 * Handler for when the profile icons are pushed from the browser. | 157 attached: function() { |
| 215 * @param {!Array<!AvatarIcon>} icons | 158 this.$.nameInput.focus(); |
| 216 * @private | 159 }, |
| 217 */ | 160 |
| 218 handleProfileIcons_: function(icons) { | 161 /** |
| 219 this.availableIcons_ = icons; | 162 * Handles tap events from: |
| 220 this.profileIconUrl_ = icons[0].url; | 163 * - links within dynamic warning/error messages pushed from the browser. |
| 221 }, | 164 * - the 'noSignedInUserMessage' i18n string. |
| 222 | 165 * @param {!Event} event |
| 223 /** | 166 * @private |
| 224 * Handler for when the profile defaults are pushed from the browser. | 167 */ |
| 225 * @param {!ProfileInfo} profileInfo Default Info for the new profile. | 168 onTap_: function(event) { |
| 226 * @private | 169 var element = Polymer.dom(event).rootTarget; |
| 227 */ | 170 |
| 228 handleProfileDefaults_: function(profileInfo) { | 171 if (element.id == 'supervised-user-import-existing') { |
| 229 this.profileName_ = profileInfo.name; | 172 this.onImportUserTap_(event); |
| 230 }, | 173 event.preventDefault(); |
| 231 | 174 } else if (element.id == 'sign-in-to-chrome') { |
| 232 /** | 175 this.browserProxy_.openUrlInLastActiveProfileBrowser(element.href); |
| 233 * Handler for when signed-in users are pushed from the browser. | 176 event.preventDefault(); |
| 234 * @param {!Array<!SignedInUser>} signedInUsers | 177 } else if (element.id == 'reauth') { |
| 235 * @private | 178 var elementData = /** @type {{userEmail: string}} */ (element.dataset); |
| 236 */ | 179 this.browserProxy_.authenticateCustodian(elementData.userEmail); |
| 237 handleSignedInUsers_: function(signedInUsers) { | 180 this.hideMessage_(); |
| 238 this.signedInUsers_ = signedInUsers; | 181 event.preventDefault(); |
| 239 }, | 182 } |
| 240 | 183 }, |
| 241 /** | 184 |
| 185 /** |
| 186 * Handler for when the profile icons are pushed from the browser. |
| 187 * @param {!Array<!AvatarIcon>} icons |
| 188 * @private |
| 189 */ |
| 190 handleProfileIcons_: function(icons) { |
| 191 this.availableIcons_ = icons; |
| 192 this.profileIconUrl_ = icons[0].url; |
| 193 }, |
| 194 |
| 195 /** |
| 196 * Handler for when the profile defaults are pushed from the browser. |
| 197 * @param {!ProfileInfo} profileInfo Default Info for the new profile. |
| 198 * @private |
| 199 */ |
| 200 handleProfileDefaults_: function(profileInfo) { |
| 201 this.profileName_ = profileInfo.name; |
| 202 }, |
| 203 |
| 204 /** |
| 205 * Handler for when signed-in users are pushed from the browser. |
| 206 * @param {!Array<!SignedInUser>} signedInUsers |
| 207 * @private |
| 208 */ |
| 209 handleSignedInUsers_: function(signedInUsers) { |
| 210 this.signedInUsers_ = signedInUsers; |
| 211 }, |
| 212 |
| 213 /** |
| 242 * Returns the currently selected signed-in user. | 214 * Returns the currently selected signed-in user. |
| 243 * @return {(!SignedInUser|undefined)} | 215 * @return {(!SignedInUser|undefined)} |
| 244 * @private | 216 * @private |
| 245 */ | 217 */ |
| 246 signedInUser_: function(signedInUserIndex) { | 218 signedInUser_: function(signedInUserIndex) { |
| 247 return this.signedInUsers_[signedInUserIndex]; | 219 return this.signedInUsers_[signedInUserIndex]; |
| 248 }, | 220 }, |
| 249 | 221 |
| 250 /** | 222 /** |
| 251 * Handler for the 'Learn More' link tap event. | 223 * Handler for the 'Learn More' link tap event. |
| 252 * @param {!Event} event | 224 * @param {!Event} event |
| 253 * @private | 225 * @private |
| 254 */ | 226 */ |
| 255 onLearnMoreTap_: function(event) { | 227 onLearnMoreTap_: function(event) { |
| 256 this.fire('change-page', {page: 'supervised-learn-more-page'}); | 228 this.fire('change-page', {page: 'supervised-learn-more-page'}); |
| 257 }, | 229 }, |
| 258 | 230 |
| 259 /** | 231 /** |
| 260 * Handler for the 'Import Supervised User' link tap event. | 232 * Handler for the 'Import Supervised User' link tap event. |
| 261 * @param {!Event} event | 233 * @param {!Event} event |
| 262 * @private | 234 * @private |
| 263 */ | 235 */ |
| 264 onImportUserTap_: function(event) { | 236 onImportUserTap_: function(event) { |
| 265 if (this.signedInUserIndex_ == NO_USER_SELECTED) { | 237 if (this.signedInUserIndex_ == NO_USER_SELECTED) { |
| 266 // A custodian must be selected. | 238 // A custodian must be selected. |
| 267 this.handleMessage_(this.i18n('custodianAccountNotSelectedError')); | 239 this.handleMessage_(this.i18n('custodianAccountNotSelectedError')); |
| 268 } else { | 240 } else { |
| 269 var signedInUser = this.signedInUser_(this.signedInUserIndex_); | 241 var signedInUser = this.signedInUser_(this.signedInUserIndex_); |
| 242 this.hideMessage_(); |
| 243 this.loadingSupervisedUsers_ = true; |
| 244 this.browserProxy_.getExistingSupervisedUsers(signedInUser.profilePath) |
| 245 .then( |
| 246 this.showImportSupervisedUserPopup_.bind(this), |
| 247 this.handleMessage_.bind(this)); |
| 248 } |
| 249 }, |
| 250 |
| 251 /** |
| 252 * Handler for the 'Save' button tap event. |
| 253 * @param {!Event} event |
| 254 * @private |
| 255 */ |
| 256 onSaveTap_: function(event) { |
| 257 if (!this.isSupervised_) { |
| 258 // The new profile is not supervised. Go ahead and create it. |
| 259 this.createProfile_(); |
| 260 } else if (this.signedInUserIndex_ == NO_USER_SELECTED) { |
| 261 // If the new profile is supervised, a custodian must be selected. |
| 262 this.handleMessage_(this.i18n('custodianAccountNotSelectedError')); |
| 263 } else { |
| 264 var signedInUser = this.signedInUser_(this.signedInUserIndex_); |
| 265 this.hideMessage_(); |
| 266 this.loadingSupervisedUsers_ = true; |
| 267 this.browserProxy_.getExistingSupervisedUsers(signedInUser.profilePath) |
| 268 .then( |
| 269 this.createProfileIfValidSupervisedUser_.bind(this), |
| 270 this.handleMessage_.bind(this)); |
| 271 } |
| 272 }, |
| 273 |
| 274 /** |
| 275 * Displays the import supervised user popup or an error message if there |
| 276 * are |
| 277 * no existing supervised users. |
| 278 * @param {!Array<!SupervisedUser>} supervisedUsers The list of existing |
| 279 * supervised users. |
| 280 * @private |
| 281 */ |
| 282 showImportSupervisedUserPopup_: function(supervisedUsers) { |
| 283 this.loadingSupervisedUsers_ = false; |
| 284 if (supervisedUsers.length > 0) { |
| 285 this.$.importUserPopup.show( |
| 286 this.signedInUser_(this.signedInUserIndex_), supervisedUsers); |
| 287 } else { |
| 288 this.handleMessage_(this.i18n('noSupervisedUserImportText')); |
| 289 } |
| 290 }, |
| 291 |
| 292 /** |
| 293 * Checks if the entered name matches name of an existing supervised user. |
| 294 * If yes, the user is prompted to import the existing supervised user. |
| 295 * If no, the new supervised profile gets created. |
| 296 * @param {!Array<!SupervisedUser>} supervisedUsers The list of existing |
| 297 * supervised users. |
| 298 * @private |
| 299 */ |
| 300 createProfileIfValidSupervisedUser_: function(supervisedUsers) { |
| 301 for (var i = 0; i < supervisedUsers.length; ++i) { |
| 302 if (supervisedUsers[i].name != this.profileName_) |
| 303 continue; |
| 304 // Check if another supervised user also exists with that name. |
| 305 var nameIsUnique = true; |
| 306 // Handling the case when multiple supervised users with the same |
| 307 // name exist, but not all of them are on the device. |
| 308 // If at least one is not imported, we want to offer that |
| 309 // option to the user. This could happen due to a bug that allowed |
| 310 // creating SUs with the same name (https://crbug.com/557445). |
| 311 var allOnCurrentDevice = supervisedUsers[i].onCurrentDevice; |
| 312 for (var j = i + 1; j < supervisedUsers.length; ++j) { |
| 313 if (supervisedUsers[j].name == this.profileName_) { |
| 314 nameIsUnique = false; |
| 315 allOnCurrentDevice = |
| 316 allOnCurrentDevice && supervisedUsers[j].onCurrentDevice; |
| 317 } |
| 318 } |
| 319 |
| 320 var opts = { |
| 321 'substitutions': |
| 322 [HTMLEscape(elide(this.profileName_, /* maxLength */ 50))], |
| 323 'attrs': { |
| 324 'id': function(node, value) { |
| 325 return node.tagName == 'A'; |
| 326 }, |
| 327 'is': function(node, value) { |
| 328 return node.tagName == 'A' && value == 'action-link'; |
| 329 }, |
| 330 'role': function(node, value) { |
| 331 return node.tagName == 'A' && value == 'link'; |
| 332 }, |
| 333 'tabindex': function(node, value) { |
| 334 return node.tagName == 'A'; |
| 335 } |
| 336 } |
| 337 }; |
| 338 |
| 339 this.handleMessage_( |
| 340 allOnCurrentDevice ? |
| 341 this.i18n('managedProfilesExistingLocalSupervisedUser') : |
| 342 this.i18nAdvanced( |
| 343 'manageProfilesExistingSupervisedUser', opts)); |
| 344 return; |
| 345 } |
| 346 // No existing supervised user's name matches the entered profile name. |
| 347 // Continue with creating the new supervised profile. |
| 348 this.createProfile_(); |
| 349 // Set this to false after createInProgress_ has been set to true in |
| 350 // order for the 'Save' button to remain disabled. |
| 351 this.loadingSupervisedUsers_ = false; |
| 352 }, |
| 353 |
| 354 /** |
| 355 * Creates the new profile. |
| 356 * @private |
| 357 */ |
| 358 createProfile_: function() { |
| 359 var custodianProfilePath = ''; |
| 360 if (this.signedInUserIndex_ != NO_USER_SELECTED) { |
| 361 custodianProfilePath = |
| 362 this.signedInUser_(this.signedInUserIndex_).profilePath; |
| 363 } |
| 270 this.hideMessage_(); | 364 this.hideMessage_(); |
| 271 this.loadingSupervisedUsers_ = true; | 365 this.createInProgress_ = true; |
| 272 this.browserProxy_.getExistingSupervisedUsers(signedInUser.profilePath) | 366 var createShortcut = |
| 273 .then(this.showImportSupervisedUserPopup_.bind(this), | 367 this.isProfileShortcutsEnabled_ && this.createShortcut_; |
| 274 this.handleMessage_.bind(this)); | 368 this.browserProxy_.createProfile( |
| 275 } | 369 this.profileName_, this.profileIconUrl_, createShortcut, |
| 276 }, | 370 this.isSupervised_, '', custodianProfilePath); |
| 277 | 371 }, |
| 278 /** | 372 |
| 279 * Handler for the 'Save' button tap event. | 373 /** |
| 280 * @param {!Event} event | 374 * Handler for the 'import' event fired by #importUserPopup once a |
| 281 * @private | 375 * supervised |
| 282 */ | 376 * user is selected to be imported and the popup closes. |
| 283 onSaveTap_: function(event) { | 377 * @param {!{detail: {supervisedUser: !SupervisedUser, |
| 284 if (!this.isSupervised_) { | 378 * signedInUser: !SignedInUser}}} event |
| 285 // The new profile is not supervised. Go ahead and create it. | 379 * @private |
| 286 this.createProfile_(); | 380 */ |
| 287 } else if (this.signedInUserIndex_ == NO_USER_SELECTED) { | 381 onImportUserPopupImport_: function(event) { |
| 288 // If the new profile is supervised, a custodian must be selected. | 382 var supervisedUser = event.detail.supervisedUser; |
| 289 this.handleMessage_(this.i18n('custodianAccountNotSelectedError')); | 383 var signedInUser = event.detail.signedInUser; |
| 290 } else { | |
| 291 var signedInUser = this.signedInUser_(this.signedInUserIndex_); | |
| 292 this.hideMessage_(); | 384 this.hideMessage_(); |
| 293 this.loadingSupervisedUsers_ = true; | 385 this.createInProgress_ = true; |
| 294 this.browserProxy_.getExistingSupervisedUsers(signedInUser.profilePath) | 386 var createShortcut = this.isProfileShortcutsEnabled_; |
| 295 .then(this.createProfileIfValidSupervisedUser_.bind(this), | 387 this.browserProxy_.createProfile( |
| 296 this.handleMessage_.bind(this)); | 388 supervisedUser.name, supervisedUser.iconURL, createShortcut, |
| 297 } | 389 true /* isSupervised */, supervisedUser.id, signedInUser.profilePath); |
| 298 }, | 390 }, |
| 299 | 391 |
| 300 /** | 392 /** |
| 301 * Displays the import supervised user popup or an error message if there are | 393 * Handler for the 'Cancel' button tap event. |
| 302 * no existing supervised users. | 394 * @param {!Event} event |
| 303 * @param {!Array<!SupervisedUser>} supervisedUsers The list of existing | 395 * @private |
| 304 * supervised users. | 396 */ |
| 305 * @private | 397 onCancelTap_: function(event) { |
| 306 */ | 398 if (this.createInProgress_) { |
| 307 showImportSupervisedUserPopup_: function(supervisedUsers) { | 399 this.createInProgress_ = false; |
| 308 this.loadingSupervisedUsers_ = false; | 400 this.browserProxy_.cancelCreateProfile(); |
| 309 if (supervisedUsers.length > 0) { | 401 } else if (this.loadingSupervisedUsers_) { |
| 310 this.$.importUserPopup.show(this.signedInUser_(this.signedInUserIndex_), | 402 this.loadingSupervisedUsers_ = false; |
| 311 supervisedUsers); | 403 this.browserProxy_.cancelLoadingSupervisedUsers(); |
| 312 } else { | 404 } else { |
| 313 this.handleMessage_(this.i18n('noSupervisedUserImportText')); | 405 this.fire('change-page', {page: 'user-pods-page'}); |
| 314 } | 406 } |
| 315 }, | 407 }, |
| 316 | 408 |
| 317 /** | 409 /** |
| 318 * Checks if the entered name matches name of an existing supervised user. | 410 * Handles profile create/import success message pushed by the browser. |
| 319 * If yes, the user is prompted to import the existing supervised user. | 411 * @param {!ProfileInfo} profileInfo Details of the created/imported |
| 320 * If no, the new supervised profile gets created. | 412 * profile. |
| 321 * @param {!Array<!SupervisedUser>} supervisedUsers The list of existing | 413 * @private |
| 322 * supervised users. | 414 */ |
| 323 * @private | 415 handleSuccess_: function(profileInfo) { |
| 324 */ | 416 this.createInProgress_ = false; |
| 325 createProfileIfValidSupervisedUser_: function(supervisedUsers) { | 417 if (profileInfo.showConfirmation) { |
| 326 for (var i = 0; i < supervisedUsers.length; ++i) { | 418 this.fire( |
| 327 if (supervisedUsers[i].name != this.profileName_) | 419 'change-page', |
| 328 continue; | 420 {page: 'supervised-create-confirm-page', data: profileInfo}); |
| 329 // Check if another supervised user also exists with that name. | 421 } else { |
| 330 var nameIsUnique = true; | 422 this.fire('change-page', {page: 'user-pods-page'}); |
| 331 // Handling the case when multiple supervised users with the same | 423 } |
| 332 // name exist, but not all of them are on the device. | 424 }, |
| 333 // If at least one is not imported, we want to offer that | 425 |
| 334 // option to the user. This could happen due to a bug that allowed | 426 /** |
| 335 // creating SUs with the same name (https://crbug.com/557445). | 427 * Hides the warning/error message. |
| 336 var allOnCurrentDevice = supervisedUsers[i].onCurrentDevice; | 428 * @private |
| 337 for (var j = i + 1; j < supervisedUsers.length; ++j) { | 429 */ |
| 338 if (supervisedUsers[j].name == this.profileName_) { | 430 hideMessage_: function() { |
| 339 nameIsUnique = false; | 431 this.isMessageVisble_ = false; |
| 340 allOnCurrentDevice = allOnCurrentDevice && | 432 }, |
| 341 supervisedUsers[j].onCurrentDevice; | 433 |
| 342 } | 434 /** |
| 343 } | 435 * Handles warning/error messages when a profile is being created/imported |
| 344 | 436 * or the existing supervised users are being loaded. |
| 437 * @param {*} message An HTML warning/error message. |
| 438 * @private |
| 439 */ |
| 440 handleMessage_: function(message) { |
| 441 this.createInProgress_ = false; |
| 442 this.loadingSupervisedUsers_ = false; |
| 443 this.message_ = '' + message; |
| 444 this.isMessageVisble_ = true; |
| 445 }, |
| 446 |
| 447 /** |
| 448 * Returns a translated message that contains link elements with the 'id' |
| 449 * attribute. |
| 450 * @param {string} id The ID of the string to translate. |
| 451 * @private |
| 452 */ |
| 453 i18nAllowIDAttr_: function(id) { |
| 345 var opts = { | 454 var opts = { |
| 346 'substitutions': | |
| 347 [HTMLEscape(elide(this.profileName_, /* maxLength */ 50))], | |
| 348 'attrs': { | 455 'attrs': { |
| 349 'id': function(node, value) { | 456 'id': function(node, value) { |
| 350 return node.tagName == 'A'; | 457 return node.tagName == 'A'; |
| 351 }, | |
| 352 'is': function(node, value) { | |
| 353 return node.tagName == 'A' && value == 'action-link'; | |
| 354 }, | |
| 355 'role': function(node, value) { | |
| 356 return node.tagName == 'A' && value == 'link'; | |
| 357 }, | |
| 358 'tabindex': function(node, value) { | |
| 359 return node.tagName == 'A'; | |
| 360 } | 458 } |
| 361 } | 459 } |
| 362 }; | 460 }; |
| 363 | 461 |
| 364 this.handleMessage_(allOnCurrentDevice ? | 462 return this.i18nAdvanced(id, opts); |
| 365 this.i18n('managedProfilesExistingLocalSupervisedUser') : | 463 }, |
| 366 this.i18nAdvanced('manageProfilesExistingSupervisedUser', opts)); | 464 |
| 367 return; | 465 /** |
| 368 } | |
| 369 // No existing supervised user's name matches the entered profile name. | |
| 370 // Continue with creating the new supervised profile. | |
| 371 this.createProfile_(); | |
| 372 // Set this to false after createInProgress_ has been set to true in | |
| 373 // order for the 'Save' button to remain disabled. | |
| 374 this.loadingSupervisedUsers_ = false; | |
| 375 }, | |
| 376 | |
| 377 /** | |
| 378 * Creates the new profile. | |
| 379 * @private | |
| 380 */ | |
| 381 createProfile_: function() { | |
| 382 var custodianProfilePath = ''; | |
| 383 if (this.signedInUserIndex_ != NO_USER_SELECTED) { | |
| 384 custodianProfilePath = | |
| 385 this.signedInUser_(this.signedInUserIndex_).profilePath; | |
| 386 } | |
| 387 this.hideMessage_(); | |
| 388 this.createInProgress_ = true; | |
| 389 var createShortcut = this.isProfileShortcutsEnabled_ && | |
| 390 this.createShortcut_; | |
| 391 this.browserProxy_.createProfile( | |
| 392 this.profileName_, this.profileIconUrl_, createShortcut, | |
| 393 this.isSupervised_, '', custodianProfilePath); | |
| 394 }, | |
| 395 | |
| 396 /** | |
| 397 * Handler for the 'import' event fired by #importUserPopup once a supervised | |
| 398 * user is selected to be imported and the popup closes. | |
| 399 * @param {!{detail: {supervisedUser: !SupervisedUser, | |
| 400 * signedInUser: !SignedInUser}}} event | |
| 401 * @private | |
| 402 */ | |
| 403 onImportUserPopupImport_: function(event) { | |
| 404 var supervisedUser = event.detail.supervisedUser; | |
| 405 var signedInUser = event.detail.signedInUser; | |
| 406 this.hideMessage_(); | |
| 407 this.createInProgress_ = true; | |
| 408 var createShortcut = this.isProfileShortcutsEnabled_; | |
| 409 this.browserProxy_.createProfile( | |
| 410 supervisedUser.name, supervisedUser.iconURL, createShortcut, | |
| 411 true /* isSupervised */, supervisedUser.id, signedInUser.profilePath); | |
| 412 }, | |
| 413 | |
| 414 /** | |
| 415 * Handler for the 'Cancel' button tap event. | |
| 416 * @param {!Event} event | |
| 417 * @private | |
| 418 */ | |
| 419 onCancelTap_: function(event) { | |
| 420 if (this.createInProgress_) { | |
| 421 this.createInProgress_ = false; | |
| 422 this.browserProxy_.cancelCreateProfile(); | |
| 423 } else if (this.loadingSupervisedUsers_) { | |
| 424 this.loadingSupervisedUsers_ = false; | |
| 425 this.browserProxy_.cancelLoadingSupervisedUsers(); | |
| 426 } else { | |
| 427 this.fire('change-page', {page: 'user-pods-page'}); | |
| 428 } | |
| 429 }, | |
| 430 | |
| 431 /** | |
| 432 * Handles profile create/import success message pushed by the browser. | |
| 433 * @param {!ProfileInfo} profileInfo Details of the created/imported profile. | |
| 434 * @private | |
| 435 */ | |
| 436 handleSuccess_: function(profileInfo) { | |
| 437 this.createInProgress_ = false; | |
| 438 if (profileInfo.showConfirmation) { | |
| 439 this.fire('change-page', {page: 'supervised-create-confirm-page', | |
| 440 data: profileInfo}); | |
| 441 } else { | |
| 442 this.fire('change-page', {page: 'user-pods-page'}); | |
| 443 } | |
| 444 }, | |
| 445 | |
| 446 /** | |
| 447 * Hides the warning/error message. | |
| 448 * @private | |
| 449 */ | |
| 450 hideMessage_: function() { | |
| 451 this.isMessageVisble_ = false; | |
| 452 }, | |
| 453 | |
| 454 /** | |
| 455 * Handles warning/error messages when a profile is being created/imported | |
| 456 * or the existing supervised users are being loaded. | |
| 457 * @param {*} message An HTML warning/error message. | |
| 458 * @private | |
| 459 */ | |
| 460 handleMessage_: function(message) { | |
| 461 this.createInProgress_ = false; | |
| 462 this.loadingSupervisedUsers_ = false; | |
| 463 this.message_ = '' + message; | |
| 464 this.isMessageVisble_ = true; | |
| 465 }, | |
| 466 | |
| 467 /** | |
| 468 * Returns a translated message that contains link elements with the 'id' | |
| 469 * attribute. | |
| 470 * @param {string} id The ID of the string to translate. | |
| 471 * @private | |
| 472 */ | |
| 473 i18nAllowIDAttr_: function(id) { | |
| 474 var opts = { | |
| 475 'attrs': { | |
| 476 'id' : function(node, value) { | |
| 477 return node.tagName == 'A'; | |
| 478 } | |
| 479 } | |
| 480 }; | |
| 481 | |
| 482 return this.i18nAdvanced(id, opts); | |
| 483 }, | |
| 484 | |
| 485 /** | |
| 486 * Computed binding determining which profile icon button is toggled on. | 466 * Computed binding determining which profile icon button is toggled on. |
| 487 * @param {string} iconUrl icon URL of a given icon button. | 467 * @param {string} iconUrl icon URL of a given icon button. |
| 488 * @param {string} profileIconUrl Currently selected icon URL. | 468 * @param {string} profileIconUrl Currently selected icon URL. |
| 489 * @return {boolean} | 469 * @return {boolean} |
| 490 * @private | 470 * @private |
| 491 */ | 471 */ |
| 492 isActiveIcon_: function(iconUrl, profileIconUrl) { | 472 isActiveIcon_: function(iconUrl, profileIconUrl) { |
| 493 return iconUrl == profileIconUrl; | 473 return iconUrl == profileIconUrl; |
| 494 }, | 474 }, |
| 495 | 475 |
| 496 /** | 476 /** |
| 497 * Computed binding determining whether the paper-spinner is active. | 477 * Computed binding determining whether the paper-spinner is active. |
| 498 * @param {boolean} createInProgress Is create in progress? | 478 * @param {boolean} createInProgress Is create in progress? |
| 499 * @param {boolean} loadingSupervisedUsers Are supervised users being loaded? | 479 * @param {boolean} loadingSupervisedUsers Are supervised users being loaded? |
| 500 * @return {boolean} | 480 * @return {boolean} |
| 501 * @private | 481 * @private |
| 502 */ | 482 */ |
| 503 isSpinnerActive_: function(createInProgress, loadingSupervisedUsers) { | 483 isSpinnerActive_: function(createInProgress, loadingSupervisedUsers) { |
| 504 return createInProgress || loadingSupervisedUsers; | 484 return createInProgress || loadingSupervisedUsers; |
| 505 }, | 485 }, |
| 506 | 486 |
| 507 /** | 487 /** |
| 508 * Computed binding determining whether 'Save' button is disabled. | 488 * Computed binding determining whether 'Save' button is disabled. |
| 509 * @param {boolean} createInProgress Is create in progress? | 489 * @param {boolean} createInProgress Is create in progress? |
| 510 * @param {boolean} loadingSupervisedUsers Are supervised users being loaded? | 490 * @param {boolean} loadingSupervisedUsers Are supervised users being loaded? |
| 511 * @param {string} profileName Profile Name. | 491 * @param {string} profileName Profile Name. |
| 512 * @return {boolean} | 492 * @return {boolean} |
| 513 * @private | 493 * @private |
| 514 */ | 494 */ |
| 515 isSaveDisabled_: function(createInProgress, | 495 isSaveDisabled_: function( |
| 516 loadingSupervisedUsers, | 496 createInProgress, loadingSupervisedUsers, profileName) { |
| 517 profileName) { | 497 // TODO(mahmadi): Figure out a way to add 'paper-input-extracted' as a |
| 518 // TODO(mahmadi): Figure out a way to add 'paper-input-extracted' as a | 498 // dependency and cast to PaperInputElement instead. |
| 519 // dependency and cast to PaperInputElement instead. | 499 /** @type {{validate: function():boolean}} */ |
| 520 /** @type {{validate: function():boolean}} */ | 500 var nameInput = this.$.nameInput; |
| 521 var nameInput = this.$.nameInput; | 501 return createInProgress || loadingSupervisedUsers || !profileName || |
| 522 return createInProgress || loadingSupervisedUsers || !profileName || | 502 !nameInput.validate(); |
| 523 !nameInput.validate(); | 503 }, |
| 524 }, | |
| 525 | 504 |
| 526 /** | 505 /** |
| 527 * Returns True if the import existing supervised user link should be hidden. | 506 * Returns True if the import existing supervised user link should be hidden. |
| 528 * @param {boolean} createInProgress True if create/import is in progress. | 507 * @param {boolean} createInProgress True if create/import is in progress. |
| 529 * @param {boolean} loadingSupervisedUsers True if supervised users are being | 508 * @param {boolean} loadingSupervisedUsers True if supervised users are being |
| 530 * loaded. | 509 * loaded. |
| 531 * @param {number} signedInUserIndex Index of the selected signed-in user. | 510 * @param {number} signedInUserIndex Index of the selected signed-in user. |
| 532 * @return {boolean} | 511 * @return {boolean} |
| 533 * @private | 512 * @private |
| 534 */ | 513 */ |
| 535 isImportUserLinkHidden_: function(createInProgress, | 514 isImportUserLinkHidden_: function( |
| 536 loadingSupervisedUsers, | 515 createInProgress, loadingSupervisedUsers, signedInUserIndex) { |
| 537 signedInUserIndex) { | 516 return createInProgress || loadingSupervisedUsers || |
| 538 return createInProgress || loadingSupervisedUsers || | 517 !this.signedInUser_(signedInUserIndex); |
| 539 !this.signedInUser_(signedInUserIndex); | 518 }, |
| 540 }, | |
| 541 | 519 |
| 542 /** | 520 /** |
| 543 * Computed binding that returns True if there are any signed-in users. | 521 * Computed binding that returns True if there are any signed-in users. |
| 544 * @param {!Array<!SignedInUser>} signedInUsers signed-in users. | 522 * @param {!Array<!SignedInUser>} signedInUsers signed-in users. |
| 545 * @return {boolean} | 523 * @return {boolean} |
| 546 * @private | 524 * @private |
| 547 */ | 525 */ |
| 548 isSignedIn_: function(signedInUsers) { | 526 isSignedIn_: function(signedInUsers) { |
| 549 return signedInUsers.length > 0; | 527 return signedInUsers.length > 0; |
| 550 } | 528 } |
| 551 }); | 529 }); |
| 552 }()); | 530 }()); |
| OLD | NEW |