OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 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 #ifndef CHROME_BROWSER_CHROMEOS_LOGIN_USERS_USER_MANAGER_H_ | 5 #ifndef COMPONENTS_USER_MANAGER_USER_MANAGER_H_ |
6 #define CHROME_BROWSER_CHROMEOS_LOGIN_USERS_USER_MANAGER_H_ | 6 #define COMPONENTS_USER_MANAGER_USER_MANAGER_H_ |
7 | 7 |
8 #include <string> | 8 #include <string> |
9 | 9 |
10 #include "chrome/browser/chromeos/login/user_flow.h" | |
11 #include "components/user_manager/user.h" | 10 #include "components/user_manager/user.h" |
12 | 11 #include "components/user_manager/user_manager_export.h" |
13 class PrefRegistrySimple; | |
14 | 12 |
15 namespace chromeos { | 13 namespace chromeos { |
| 14 class ScopedUserManagerEnabler; |
| 15 } |
16 | 16 |
17 class MultiProfileUserController; | 17 namespace user_manager { |
| 18 |
18 class RemoveUserDelegate; | 19 class RemoveUserDelegate; |
19 class UserImageManager; | |
20 class SupervisedUserManager; | |
21 | 20 |
22 // Interface for UserManagerBase - provides a mechanism for discovering users | 21 // Interface for UserManagerBase - that provides base implementation for |
23 // who have logged into this Chrome OS device before and updating that list. | 22 // Chrome OS user management. Typical features: |
24 class UserManager { | 23 // * Get list of all know users (who have logged into this Chrome OS device) |
| 24 // * Keep track for logged in/LRU users, active user in multi-user session. |
| 25 // * Find/modify users, store user meta-data such as display name/email. |
| 26 class USER_MANAGER_EXPORT UserManager { |
25 public: | 27 public: |
26 // Interface that observers of UserManager must implement in order | 28 // Interface that observers of UserManager must implement in order |
27 // to receive notification when local state preferences is changed | 29 // to receive notification when local state preferences is changed |
28 class Observer { | 30 class Observer { |
29 public: | 31 public: |
30 // Called when the local state preferences is changed. | 32 // Called when the local state preferences is changed. |
31 virtual void LocalStateChanged(UserManager* user_manager); | 33 virtual void LocalStateChanged(UserManager* user_manager); |
32 | 34 |
33 protected: | 35 protected: |
34 virtual ~Observer(); | 36 virtual ~Observer(); |
35 }; | 37 }; |
36 | 38 |
37 // TODO(nkostylev): Refactor and move this observer out of UserManager. | 39 // TODO(nkostylev): Refactor and move this observer out of UserManager. |
38 // Observer interface that defines methods used to notify on user session / | 40 // Observer interface that defines methods used to notify on user session / |
39 // active user state changes. Default implementation is empty. | 41 // active user state changes. Default implementation is empty. |
40 class UserSessionStateObserver { | 42 class UserSessionStateObserver { |
41 public: | 43 public: |
42 // Called when active user has changed. | 44 // Called when active user has changed. |
43 virtual void ActiveUserChanged(const user_manager::User* active_user); | 45 virtual void ActiveUserChanged(const User* active_user); |
44 | 46 |
45 // Called when another user got added to the existing session. | 47 // Called when another user got added to the existing session. |
46 virtual void UserAddedToSession(const user_manager::User* added_user); | 48 virtual void UserAddedToSession(const User* added_user); |
47 | 49 |
48 // Called right before notifying on user change so that those who rely | 50 // Called right before notifying on user change so that those who rely |
49 // on user_id hash would be accessing up-to-date value. | 51 // on user_id hash would be accessing up-to-date value. |
50 virtual void ActiveUserHashChanged(const std::string& hash); | 52 virtual void ActiveUserHashChanged(const std::string& hash); |
51 | 53 |
52 protected: | 54 protected: |
53 virtual ~UserSessionStateObserver(); | 55 virtual ~UserSessionStateObserver(); |
54 }; | 56 }; |
55 | 57 |
56 // Data retrieved from user account. | 58 // Data retrieved from user account. |
57 class UserAccountData { | 59 class UserAccountData { |
58 public: | 60 public: |
59 UserAccountData(const base::string16& display_name, | 61 UserAccountData(const base::string16& display_name, |
60 const base::string16& given_name, | 62 const base::string16& given_name, |
61 const std::string& locale); | 63 const std::string& locale); |
62 ~UserAccountData(); | 64 ~UserAccountData(); |
63 const base::string16& display_name() const { return display_name_; } | 65 const base::string16& display_name() const { return display_name_; } |
64 const base::string16& given_name() const { return given_name_; } | 66 const base::string16& given_name() const { return given_name_; } |
65 const std::string& locale() const { return locale_; } | 67 const std::string& locale() const { return locale_; } |
66 | 68 |
67 private: | 69 private: |
68 const base::string16 display_name_; | 70 const base::string16 display_name_; |
69 const base::string16 given_name_; | 71 const base::string16 given_name_; |
70 const std::string locale_; | 72 const std::string locale_; |
71 | 73 |
72 DISALLOW_COPY_AND_ASSIGN(UserAccountData); | 74 DISALLOW_COPY_AND_ASSIGN(UserAccountData); |
73 }; | 75 }; |
74 | 76 |
75 // Creates the singleton instance. This method is not thread-safe and must be | 77 // Initializes UserManager instance to this. Normally should be called right |
76 // called from the main UI thread. | 78 // after creation so that user_manager::UserManager::Get() doesn't fail. |
77 static void Initialize(); | 79 // Tests could call this method if they are replacing existing UserManager |
| 80 // instance with their own test instance. |
| 81 void Initialize(); |
78 | 82 |
79 // Checks whether the singleton instance has been created already. This method | 83 // Checks whether the UserManager instance has been created already. |
80 // is not thread-safe and must be called from the main UI thread. | 84 // This method is not thread-safe and must be called from the main UI thread. |
81 static bool IsInitialized(); | 85 static bool IsInitialized(); |
82 | 86 |
83 // Shuts down the UserManager. After this method has been called, the | 87 // Shuts down the UserManager. After this method has been called, the |
84 // singleton has unregistered itself as an observer but remains available so | 88 // singleton has unregistered itself as an observer but remains available so |
85 // that other classes can access it during their shutdown. This method is not | 89 // that other classes can access it during their shutdown. This method is not |
86 // thread-safe and must be called from the main UI thread. | 90 // thread-safe and must be called from the main UI thread. |
87 virtual void Shutdown() = 0; | 91 virtual void Shutdown() = 0; |
88 | 92 |
89 // Destroys the singleton instance. Always call Shutdown() first. This method | 93 // Sets UserManager instance to NULL. Always call Shutdown() first. |
90 // is not thread-safe and must be called from the main UI thread. | 94 // This method is not thread-safe and must be called from the main UI thread. |
91 static void Destroy(); | 95 void Destroy(); |
92 | 96 |
93 // Returns the singleton instance or |NULL| if the singleton has either not | 97 // Returns UserManager instance or will crash if it is |NULL| (has either not |
94 // been created yet or is already destroyed. This method is not thread-safe | 98 // been created yet or is already destroyed). This method is not thread-safe |
95 // and must be called from the main UI thread. | 99 // and must be called from the main UI thread. |
96 static UserManager* Get(); | 100 static UserManager* Get(); |
97 | 101 |
98 // Registers user manager preferences. | |
99 static void RegisterPrefs(PrefRegistrySimple* registry); | |
100 | |
101 virtual ~UserManager(); | 102 virtual ~UserManager(); |
102 | 103 |
103 virtual MultiProfileUserController* GetMultiProfileUserController() = 0; | |
104 virtual UserImageManager* GetUserImageManager(const std::string& user_id) = 0; | |
105 virtual SupervisedUserManager* GetSupervisedUserManager() = 0; | |
106 | |
107 // Returns a list of users who have logged into this device previously. This | 104 // Returns a list of users who have logged into this device previously. This |
108 // is sorted by last login date with the most recent user at the beginning. | 105 // is sorted by last login date with the most recent user at the beginning. |
109 virtual const user_manager::UserList& GetUsers() const = 0; | 106 virtual const UserList& GetUsers() const = 0; |
110 | 107 |
111 // Returns list of users admitted for logging in into multi-profile session. | 108 // Returns list of users admitted for logging in into multi-profile session. |
112 // Users that have a policy that prevents them from being added to the | 109 // Users that have a policy that prevents them from being added to the |
113 // multi-profile session will still be part of this list as long as they | 110 // multi-profile session will still be part of this list as long as they |
114 // are regular users (i.e. not a public session/supervised etc.). | 111 // are regular users (i.e. not a public session/supervised etc.). |
115 // Returns an empty list in case when primary user is not a regular one or | 112 // Returns an empty list in case when primary user is not a regular one or |
116 // has a policy that prohibids it to be part of multi-profile session. | 113 // has a policy that prohibids it to be part of multi-profile session. |
117 virtual user_manager::UserList GetUsersAdmittedForMultiProfile() const = 0; | 114 virtual UserList GetUsersAdmittedForMultiProfile() const = 0; |
118 | 115 |
119 // Returns a list of users who are currently logged in. | 116 // Returns a list of users who are currently logged in. |
120 virtual const user_manager::UserList& GetLoggedInUsers() const = 0; | 117 virtual const UserList& GetLoggedInUsers() const = 0; |
121 | 118 |
122 // Returns a list of users who are currently logged in in the LRU order - | 119 // Returns a list of users who are currently logged in in the LRU order - |
123 // so the active user is the first one in the list. If there is no user logged | 120 // so the active user is the first one in the list. If there is no user logged |
124 // in, the current user will be returned. | 121 // in, the current user will be returned. |
125 virtual const user_manager::UserList& GetLRULoggedInUsers() const = 0; | 122 virtual const UserList& GetLRULoggedInUsers() const = 0; |
126 | 123 |
127 // Returns a list of users who can unlock the device. | 124 // Returns a list of users who can unlock the device. |
128 // This list is based on policy and whether user is able to do unlock. | 125 // This list is based on policy and whether user is able to do unlock. |
129 // Policy: | 126 // Policy: |
130 // * If user has primary-only policy then it is the only user in unlock users. | 127 // * If user has primary-only policy then it is the only user in unlock users. |
131 // * Otherwise all users with unrestricted policy are added to this list. | 128 // * Otherwise all users with unrestricted policy are added to this list. |
132 // All users that are unable to perform unlock are excluded from this list. | 129 // All users that are unable to perform unlock are excluded from this list. |
133 virtual user_manager::UserList GetUnlockUsers() const = 0; | 130 virtual UserList GetUnlockUsers() const = 0; |
134 | 131 |
135 // Returns the email of the owner user. Returns an empty string if there is | 132 // Returns the email of the owner user. Returns an empty string if there is |
136 // no owner for the device. | 133 // no owner for the device. |
137 virtual const std::string& GetOwnerEmail() const = 0; | 134 virtual const std::string& GetOwnerEmail() const = 0; |
138 | 135 |
139 // Indicates that a user with the given |user_id| has just logged in. The | 136 // Indicates that a user with the given |user_id| has just logged in. The |
140 // persistent list is updated accordingly if the user is not ephemeral. | 137 // persistent list is updated accordingly if the user is not ephemeral. |
141 // |browser_restart| is true when reloading Chrome after crash to distinguish | 138 // |browser_restart| is true when reloading Chrome after crash to distinguish |
142 // from normal sign in flow. | 139 // from normal sign in flow. |
143 // |username_hash| is used to identify homedir mount point. | 140 // |username_hash| is used to identify homedir mount point. |
(...skipping 22 matching lines...) Expand all Loading... |
166 // Removes the user from the persistent list only. Also removes the user's | 163 // Removes the user from the persistent list only. Also removes the user's |
167 // picture. | 164 // picture. |
168 virtual void RemoveUserFromList(const std::string& user_id) = 0; | 165 virtual void RemoveUserFromList(const std::string& user_id) = 0; |
169 | 166 |
170 // Returns true if a user with the given user id is found in the persistent | 167 // Returns true if a user with the given user id is found in the persistent |
171 // list or currently logged in as ephemeral. | 168 // list or currently logged in as ephemeral. |
172 virtual bool IsKnownUser(const std::string& user_id) const = 0; | 169 virtual bool IsKnownUser(const std::string& user_id) const = 0; |
173 | 170 |
174 // Returns the user with the given user id if found in the persistent | 171 // Returns the user with the given user id if found in the persistent |
175 // list or currently logged in as ephemeral. Returns |NULL| otherwise. | 172 // list or currently logged in as ephemeral. Returns |NULL| otherwise. |
176 virtual const user_manager::User* FindUser( | 173 virtual const User* FindUser(const std::string& user_id) const = 0; |
177 const std::string& user_id) const = 0; | |
178 | 174 |
179 // Returns the user with the given user id if found in the persistent | 175 // Returns the user with the given user id if found in the persistent |
180 // list or currently logged in as ephemeral. Returns |NULL| otherwise. | 176 // list or currently logged in as ephemeral. Returns |NULL| otherwise. |
181 // Same as FindUser but returns non-const pointer to User object. | 177 // Same as FindUser but returns non-const pointer to User object. |
182 virtual user_manager::User* FindUserAndModify(const std::string& user_id) = 0; | 178 virtual User* FindUserAndModify(const std::string& user_id) = 0; |
183 | 179 |
184 // Returns the logged-in user. | 180 // Returns the logged-in user. |
185 // TODO(nkostylev): Deprecate this call, move clients to GetActiveUser(). | 181 // TODO(nkostylev): Deprecate this call, move clients to GetActiveUser(). |
186 // http://crbug.com/230852 | 182 // http://crbug.com/230852 |
187 virtual const user_manager::User* GetLoggedInUser() const = 0; | 183 virtual const User* GetLoggedInUser() const = 0; |
188 virtual user_manager::User* GetLoggedInUser() = 0; | 184 virtual User* GetLoggedInUser() = 0; |
189 | 185 |
190 // Returns the logged-in user that is currently active within this session. | 186 // Returns the logged-in user that is currently active within this session. |
191 // There could be multiple users logged in at the the same but for now | 187 // There could be multiple users logged in at the the same but for now |
192 // we support only one of them being active. | 188 // we support only one of them being active. |
193 virtual const user_manager::User* GetActiveUser() const = 0; | 189 virtual const User* GetActiveUser() const = 0; |
194 virtual user_manager::User* GetActiveUser() = 0; | 190 virtual User* GetActiveUser() = 0; |
195 | 191 |
196 // Returns the primary user of the current session. It is recorded for the | 192 // Returns the primary user of the current session. It is recorded for the |
197 // first signed-in user and does not change thereafter. | 193 // first signed-in user and does not change thereafter. |
198 virtual const user_manager::User* GetPrimaryUser() const = 0; | 194 virtual const User* GetPrimaryUser() const = 0; |
199 | 195 |
200 // Saves user's oauth token status in local state preferences. | 196 // Saves user's oauth token status in local state preferences. |
201 virtual void SaveUserOAuthStatus( | 197 virtual void SaveUserOAuthStatus( |
202 const std::string& user_id, | 198 const std::string& user_id, |
203 user_manager::User::OAuthTokenStatus oauth_token_status) = 0; | 199 User::OAuthTokenStatus oauth_token_status) = 0; |
204 | 200 |
205 // Saves a flag indicating whether online authentication against GAIA should | 201 // Saves a flag indicating whether online authentication against GAIA should |
206 // be enforced during the user's next sign-in. | 202 // be enforced during the user's next sign-in. |
207 virtual void SaveForceOnlineSignin(const std::string& user_id, | 203 virtual void SaveForceOnlineSignin(const std::string& user_id, |
208 bool force_online_signin) = 0; | 204 bool force_online_signin) = 0; |
209 | 205 |
210 // Saves user's displayed name in local state preferences. | 206 // Saves user's displayed name in local state preferences. |
211 // Ignored If there is no such user. | 207 // Ignored If there is no such user. |
212 virtual void SaveUserDisplayName(const std::string& user_id, | 208 virtual void SaveUserDisplayName(const std::string& user_id, |
213 const base::string16& display_name) = 0; | 209 const base::string16& display_name) = 0; |
214 | 210 |
215 // Updates data upon User Account download. | 211 // Updates data upon User Account download. |
216 virtual void UpdateUserAccountData(const std::string& user_id, | 212 virtual void UpdateUserAccountData(const std::string& user_id, |
217 const UserAccountData& account_data) = 0; | 213 const UserAccountData& account_data) = 0; |
218 | 214 |
219 // Returns the display name for user |user_id| if it is known (was | 215 // Returns the display name for user |user_id| if it is known (was |
220 // previously set by a |SaveUserDisplayName| call). | 216 // previously set by a |SaveUserDisplayName| call). |
221 // Otherwise, returns an empty string. | 217 // Otherwise, returns an empty string. |
222 virtual base::string16 GetUserDisplayName( | 218 virtual base::string16 GetUserDisplayName( |
223 const std::string& user_id) const = 0; | 219 const std::string& user_id) const = 0; |
224 | 220 |
225 // Saves user's displayed (non-canonical) email in local state preferences. | 221 // Saves user's displayed (non-canonical) email in local state preferences. |
226 // Ignored If there is no such user. | 222 // Ignored If there is no such user. |
227 virtual void SaveUserDisplayEmail(const std::string& user_id, | 223 virtual void SaveUserDisplayEmail(const std::string& user_id, |
228 const std::string& display_email) = 0; | 224 const std::string& display_email) = 0; |
229 | 225 |
230 // Returns the display email for user |user_id| if it is known (was | 226 // Returns the display email for user |user_id| if it is known (was |
231 // previously set by a |SaveUserDisplayEmail| call). | 227 // previously set by a |SaveUserDisplayEmail| call). |
232 // Otherwise, returns |user_id| itself. | 228 // Otherwise, returns |user_id| itself. |
233 virtual std::string GetUserDisplayEmail( | 229 virtual std::string GetUserDisplayEmail(const std::string& user_id) const = 0; |
234 const std::string& user_id) const = 0; | |
235 | 230 |
236 // Returns true if current user is an owner. | 231 // Returns true if current user is an owner. |
237 virtual bool IsCurrentUserOwner() const = 0; | 232 virtual bool IsCurrentUserOwner() const = 0; |
238 | 233 |
239 // Returns true if current user is not existing one (hasn't signed in before). | 234 // Returns true if current user is not existing one (hasn't signed in before). |
240 virtual bool IsCurrentUserNew() const = 0; | 235 virtual bool IsCurrentUserNew() const = 0; |
241 | 236 |
242 // Returns true if data stored or cached for the current user outside that | 237 // Returns true if data stored or cached for the current user outside that |
243 // user's cryptohome (wallpaper, avatar, OAuth token status, display name, | 238 // user's cryptohome (wallpaper, avatar, OAuth token status, display name, |
244 // display email) is ephemeral. | 239 // display email) is ephemeral. |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
276 // browser_creator.LaunchBrowser(...) was called after sign in | 271 // browser_creator.LaunchBrowser(...) was called after sign in |
277 // or restart after crash. | 272 // or restart after crash. |
278 virtual bool IsSessionStarted() const = 0; | 273 virtual bool IsSessionStarted() const = 0; |
279 | 274 |
280 // Returns true if data stored or cached for the user with the given user id | 275 // Returns true if data stored or cached for the user with the given user id |
281 // address outside that user's cryptohome (wallpaper, avatar, OAuth token | 276 // address outside that user's cryptohome (wallpaper, avatar, OAuth token |
282 // status, display name, display email) is to be treated as ephemeral. | 277 // status, display name, display email) is to be treated as ephemeral. |
283 virtual bool IsUserNonCryptohomeDataEphemeral( | 278 virtual bool IsUserNonCryptohomeDataEphemeral( |
284 const std::string& user_id) const = 0; | 279 const std::string& user_id) const = 0; |
285 | 280 |
286 // Method that allows to set |flow| for user identified by |user_id|. | |
287 // Flow should be set before login attempt. | |
288 // Takes ownership of the |flow|, |flow| will be deleted in case of login | |
289 // failure. | |
290 virtual void SetUserFlow(const std::string& user_id, UserFlow* flow) = 0; | |
291 | |
292 // Return user flow for current user. Returns instance of DefaultUserFlow if | |
293 // no flow was defined for current user, or user is not logged in. | |
294 // Returned value should not be cached. | |
295 virtual UserFlow* GetCurrentUserFlow() const = 0; | |
296 | |
297 // Return user flow for user identified by |user_id|. Returns instance of | |
298 // DefaultUserFlow if no flow was defined for user. | |
299 // Returned value should not be cached. | |
300 virtual UserFlow* GetUserFlow(const std::string& user_id) const = 0; | |
301 | |
302 // Resets user flow for user identified by |user_id|. | |
303 virtual void ResetUserFlow(const std::string& user_id) = 0; | |
304 | |
305 virtual void AddObserver(Observer* obs) = 0; | 281 virtual void AddObserver(Observer* obs) = 0; |
306 virtual void RemoveObserver(Observer* obs) = 0; | 282 virtual void RemoveObserver(Observer* obs) = 0; |
307 | 283 |
308 virtual void AddSessionStateObserver(UserSessionStateObserver* obs) = 0; | 284 virtual void AddSessionStateObserver(UserSessionStateObserver* obs) = 0; |
309 virtual void RemoveSessionStateObserver(UserSessionStateObserver* obs) = 0; | 285 virtual void RemoveSessionStateObserver(UserSessionStateObserver* obs) = 0; |
310 | 286 |
311 virtual void NotifyLocalStateChanged() = 0; | 287 virtual void NotifyLocalStateChanged() = 0; |
312 | 288 |
313 // Returns true if supervised users allowed. | 289 // Returns true if supervised users allowed. |
314 virtual bool AreSupervisedUsersAllowed() const = 0; | 290 virtual bool AreSupervisedUsersAllowed() const = 0; |
315 | 291 |
| 292 protected: |
| 293 // Sets UserManager instance. |
| 294 static void SetInstance(UserManager* user_manager); |
| 295 |
| 296 // Pointer to the existing UserManager instance (if any). |
| 297 // Usually is set by calling Initialize(), reset by calling Destroy(). |
| 298 // Not owned since specific implementation of UserManager should decide on its |
| 299 // own appropriate owner. For src/chrome implementation such place is |
| 300 // g_browser_process->platform_part(). |
| 301 static UserManager* instance; |
| 302 |
316 private: | 303 private: |
317 friend class ScopedUserManagerEnabler; | 304 friend class chromeos::ScopedUserManagerEnabler; |
318 | 305 |
319 // Sets the singleton to the given |user_manager|, taking ownership. Returns | 306 // Same as Get() but doesn't won't crash is current instance is NULL. |
320 // the previous value of the singleton, passing ownership. | 307 static UserManager* GetForTesting(); |
| 308 |
| 309 // Sets UserManager instance to the given |user_manager|. |
| 310 // Returns the previous value of the instance. |
321 static UserManager* SetForTesting(UserManager* user_manager); | 311 static UserManager* SetForTesting(UserManager* user_manager); |
322 }; | 312 }; |
323 | 313 |
324 // Helper class for unit tests. Initializes the UserManager singleton to the | 314 } // namespace user_manager |
325 // given |user_manager| and tears it down again on destruction. If the singleton | |
326 // had already been initialized, its previous value is restored after tearing | |
327 // down |user_manager|. | |
328 class ScopedUserManagerEnabler { | |
329 public: | |
330 // Takes ownership of |user_manager|. | |
331 explicit ScopedUserManagerEnabler(UserManager* user_manager); | |
332 ~ScopedUserManagerEnabler(); | |
333 | 315 |
334 private: | 316 #endif // COMPONENTS_USER_MANAGER_USER_MANAGER_H_ |
335 UserManager* previous_user_manager_; | |
336 | |
337 DISALLOW_COPY_AND_ASSIGN(ScopedUserManagerEnabler); | |
338 }; | |
339 | |
340 // Helper class for unit tests. Initializes the UserManager singleton on | |
341 // construction and tears it down again on destruction. | |
342 class ScopedTestUserManager { | |
343 public: | |
344 ScopedTestUserManager(); | |
345 ~ScopedTestUserManager(); | |
346 | |
347 private: | |
348 DISALLOW_COPY_AND_ASSIGN(ScopedTestUserManager); | |
349 }; | |
350 | |
351 } // namespace chromeos | |
352 | |
353 #endif // CHROME_BROWSER_CHROMEOS_LOGIN_USERS_USER_MANAGER_H_ | |
OLD | NEW |