• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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/chromeos/login/user_manager.h"
6 
7 #include "base/command_line.h"
8 #include "base/compiler_specific.h"
9 #include "base/file_path.h"
10 #include "base/file_util.h"
11 #include "base/lazy_instance.h"
12 #include "base/logging.h"
13 #include "base/path_service.h"
14 #include "base/string_util.h"
15 #include "base/stringprintf.h"
16 #include "base/time.h"
17 #include "base/utf_string_conversions.h"
18 #include "base/values.h"
19 #include "crypto/nss_util.h"
20 #include "chrome/browser/browser_process.h"
21 #include "chrome/browser/chromeos/cros/cros_library.h"
22 #include "chrome/browser/chromeos/cros/cryptohome_library.h"
23 #include "chrome/browser/chromeos/cros/input_method_library.h"
24 #include "chrome/browser/chromeos/login/default_user_images.h"
25 #include "chrome/browser/chromeos/login/login_display.h"
26 #include "chrome/browser/chromeos/login/ownership_service.h"
27 #include "chrome/browser/chromeos/user_cros_settings_provider.h"
28 #include "chrome/browser/chromeos/wm_ipc.h"
29 #include "chrome/browser/defaults.h"
30 #include "chrome/browser/prefs/pref_service.h"
31 #include "chrome/browser/prefs/scoped_user_pref_update.h"
32 #include "chrome/common/chrome_paths.h"
33 #include "chrome/common/chrome_switches.h"
34 #include "content/browser/browser_thread.h"
35 #include "content/common/notification_service.h"
36 #include "content/common/notification_type.h"
37 #include "ui/base/resource/resource_bundle.h"
38 #include "ui/gfx/codec/png_codec.h"
39 
40 namespace chromeos {
41 
42 namespace {
43 
44 // A vector pref of the users who have logged into the device.
45 const char kLoggedInUsers[] = "LoggedInUsers";
46 // A dictionary that maps usernames to file paths to their images.
47 const char kUserImages[] = "UserImages";
48 
49 // Incognito user is represented by an empty string (since some code already
50 // depends on that and it's hard to figure out what).
51 const char kGuestUser[] = "";
52 
53 base::LazyInstance<UserManager> g_user_manager(base::LINKER_INITIALIZED);
54 
55 // Stores path to the image in local state. Runs on UI thread.
SavePathToLocalState(const std::string & username,const std::string & image_path)56 void SavePathToLocalState(const std::string& username,
57                           const std::string& image_path) {
58   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
59   PrefService* local_state = g_browser_process->local_state();
60   DictionaryPrefUpdate images_update(local_state, kUserImages);
61   images_update->SetWithoutPathExpansion(username, new StringValue(image_path));
62   DVLOG(1) << "Saving path to user image in Local State.";
63   local_state->SavePersistentPrefs();
64 }
65 
66 // Saves image to file with specified path. Runs on FILE thread.
67 // Posts task for saving image path to local state on UI thread.
SaveImageToFile(const SkBitmap & image,const FilePath & image_path,const std::string & username)68 void SaveImageToFile(const SkBitmap& image,
69                      const FilePath& image_path,
70                      const std::string& username) {
71   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
72   std::vector<unsigned char> encoded_image;
73   if (!gfx::PNGCodec::EncodeBGRASkBitmap(image, true, &encoded_image)) {
74     LOG(ERROR) << "Failed to PNG encode the image.";
75     return;
76   }
77 
78   if (file_util::WriteFile(image_path,
79                            reinterpret_cast<char*>(&encoded_image[0]),
80                            encoded_image.size()) == -1) {
81     LOG(ERROR) << "Failed to save image to file.";
82     return;
83   }
84 
85   BrowserThread::PostTask(
86       BrowserThread::UI,
87       FROM_HERE,
88       NewRunnableFunction(&SavePathToLocalState,
89                           username, image_path.value()));
90 }
91 
92 // Deletes user's image file. Runs on FILE thread.
DeleteUserImage(const FilePath & image_path)93 void DeleteUserImage(const FilePath& image_path) {
94   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
95   if (!file_util::Delete(image_path, false)) {
96     LOG(ERROR) << "Failed to remove user image.";
97     return;
98   }
99 }
100 
101 // Updates current user ownership on UI thread.
UpdateOwnership(bool is_owner)102 void UpdateOwnership(bool is_owner) {
103   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
104 
105   g_user_manager.Get().set_current_user_is_owner(is_owner);
106   NotificationService::current()->Notify(NotificationType::OWNERSHIP_CHECKED,
107                                          NotificationService::AllSources(),
108                                          NotificationService::NoDetails());
109   if (is_owner) {
110     // Also update cached value.
111     UserCrosSettingsProvider::UpdateCachedOwner(
112       g_user_manager.Get().logged_in_user().email());
113   }
114 }
115 
116 // Checks current user's ownership on file thread.
CheckOwnership()117 void CheckOwnership() {
118   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
119   bool is_owner = OwnershipService::GetSharedInstance()->CurrentUserIsOwner();
120   VLOG(1) << "Current user " << (is_owner ? "is owner" : "is not owner");
121 
122   g_user_manager.Get().set_current_user_is_owner(is_owner);
123 
124   // UserManager should be accessed only on UI thread.
125   BrowserThread::PostTask(
126       BrowserThread::UI,
127       FROM_HERE,
128       NewRunnableFunction(&UpdateOwnership, is_owner));
129 }
130 
131 // Used to handle the asynchronous response of deleting a cryptohome directory.
132 class RemoveAttempt : public CryptohomeLibrary::Delegate {
133  public:
134   // Creates new remove attempt for the given user. Note, |delegate| can
135   // be NULL.
RemoveAttempt(const std::string & user_email,chromeos::RemoveUserDelegate * delegate)136   RemoveAttempt(const std::string& user_email,
137                 chromeos::RemoveUserDelegate* delegate)
138       : user_email_(user_email),
139         delegate_(delegate),
140         method_factory_(this) {
141     RemoveUser();
142   }
143 
RemoveUser()144   void RemoveUser() {
145     // Owner is not allowed to be removed from the device.
146     // Must not proceed without signature verification.
147     UserCrosSettingsProvider user_settings;
148     bool trusted_owner_available = user_settings.RequestTrustedOwner(
149         method_factory_.NewRunnableMethod(&RemoveAttempt::RemoveUser));
150     if (!trusted_owner_available) {
151       // Value of owner email is still not verified.
152       // Another attempt will be invoked after verification completion.
153       return;
154     }
155     if (user_email_ == UserCrosSettingsProvider::cached_owner()) {
156       // Owner is not allowed to be removed from the device. Probably on
157       // the stack, so deffer the deletion.
158       MessageLoop::current()->DeleteSoon(FROM_HERE, this);
159       return;
160     }
161 
162     if (delegate_)
163       delegate_->OnBeforeUserRemoved(user_email_);
164 
165     chromeos::UserManager::Get()->RemoveUserFromList(user_email_);
166     RemoveUserCryptohome();
167 
168     if (delegate_)
169       delegate_->OnUserRemoved(user_email_);
170   }
171 
RemoveUserCryptohome()172   void RemoveUserCryptohome() {
173     if (CrosLibrary::Get()->EnsureLoaded()) {
174       CrosLibrary::Get()->GetCryptohomeLibrary()->AsyncRemove(user_email_,
175                                                               this);
176     }
177   }
178 
OnComplete(bool success,int return_code)179   void OnComplete(bool success, int return_code) {
180     // Log the error, but there's not much we can do.
181     if (!success) {
182       VLOG(1) << "Removal of cryptohome for " << user_email_
183               << " failed, return code: " << return_code;
184     }
185     delete this;
186   }
187 
188  private:
189   std::string user_email_;
190   chromeos::RemoveUserDelegate* delegate_;
191 
192   // Factory of callbacks.
193   ScopedRunnableMethodFactory<RemoveAttempt> method_factory_;
194 
195   DISALLOW_COPY_AND_ASSIGN(RemoveAttempt);
196 };
197 
198 }  // namespace
199 
User()200 UserManager::User::User() {
201   image_ = *ResourceBundle::GetSharedInstance().GetBitmapNamed(
202       kDefaultImageResources[0]);
203 }
204 
~User()205 UserManager::User::~User() {}
206 
GetDisplayName() const207 std::string UserManager::User::GetDisplayName() const {
208   size_t i = email_.find('@');
209   if (i == 0 || i == std::string::npos) {
210     return email_;
211   }
212   return email_.substr(0, i);
213 }
214 
GetNameTooltip() const215 std::string UserManager::User::GetNameTooltip() const {
216   const std::string& user_email = email();
217   size_t at_pos = user_email.rfind('@');
218   if (at_pos == std::string::npos) {
219     NOTREACHED();
220     return std::string();
221   }
222   size_t domain_start = at_pos + 1;
223   std::string domain = user_email.substr(domain_start,
224                                          user_email.length() - domain_start);
225   return base::StringPrintf("%s (%s)",
226                             GetDisplayName().c_str(),
227                             domain.c_str());
228 }
229 
230 // static
Get()231 UserManager* UserManager::Get() {
232   // Not thread-safe.
233   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
234   return &g_user_manager.Get();
235 }
236 
237 // static
RegisterPrefs(PrefService * local_state)238 void UserManager::RegisterPrefs(PrefService* local_state) {
239   local_state->RegisterListPref(kLoggedInUsers);
240   local_state->RegisterDictionaryPref(kUserImages);
241 }
242 
GetUsers() const243 std::vector<UserManager::User> UserManager::GetUsers() const {
244   std::vector<User> users;
245   if (!g_browser_process)
246     return users;
247 
248   PrefService* local_state = g_browser_process->local_state();
249   const ListValue* prefs_users = local_state->GetList(kLoggedInUsers);
250   const DictionaryValue* prefs_images = local_state->GetDictionary(kUserImages);
251 
252   if (prefs_users) {
253     for (ListValue::const_iterator it = prefs_users->begin();
254          it != prefs_users->end();
255          ++it) {
256       std::string email;
257       if ((*it)->GetAsString(&email)) {
258         User user;
259         user.set_email(email);
260         UserImages::const_iterator image_it = user_images_.find(email);
261         std::string image_path;
262         if (image_it == user_images_.end()) {
263           if (prefs_images &&
264               prefs_images->GetStringWithoutPathExpansion(email, &image_path)) {
265             int default_image_id = kDefaultImagesCount;
266             if (IsDefaultImagePath(image_path, &default_image_id)) {
267               DCHECK(default_image_id < kDefaultImagesCount);
268               int resource_id = kDefaultImageResources[default_image_id];
269               user.set_image(
270                   *ResourceBundle::GetSharedInstance().GetBitmapNamed(
271                       resource_id));
272               user_images_[email] = user.image();
273             } else {
274               // Insert the default image so we don't send another request if
275               // GetUsers is called twice.
276               user_images_[email] = user.image();
277               image_loader_->Start(email, image_path, false);
278             }
279           }
280         } else {
281           user.set_image(image_it->second);
282         }
283         users.push_back(user);
284       }
285     }
286   }
287   return users;
288 }
289 
OffTheRecordUserLoggedIn()290 void UserManager::OffTheRecordUserLoggedIn() {
291   user_is_logged_in_ = true;
292   logged_in_user_ = User();
293   logged_in_user_.set_email(kGuestUser);
294   NotifyOnLogin();
295 }
296 
UserLoggedIn(const std::string & email)297 void UserManager::UserLoggedIn(const std::string& email) {
298   if (email == kGuestUser) {
299     OffTheRecordUserLoggedIn();
300     return;
301   }
302 
303   if (!IsKnownUser(email)) {
304     current_user_is_new_ = true;
305     browser_defaults::skip_restore = true;
306   }
307 
308   // Get a copy of the current users.
309   std::vector<User> users = GetUsers();
310 
311   // Clear the prefs view of the users.
312   PrefService* prefs = g_browser_process->local_state();
313   ListPrefUpdate prefs_users_update(prefs, kLoggedInUsers);
314   prefs_users_update->Clear();
315 
316   user_is_logged_in_ = true;
317   logged_in_user_ = User();
318   logged_in_user_.set_email(email);
319 
320   // Make sure this user is first.
321   prefs_users_update->Append(Value::CreateStringValue(email));
322   for (std::vector<User>::iterator it = users.begin();
323        it != users.end();
324        ++it) {
325     std::string user_email = it->email();
326     // Skip the most recent user.
327     if (email != user_email) {
328       prefs_users_update->Append(Value::CreateStringValue(user_email));
329     } else {
330       logged_in_user_ = *it;
331     }
332   }
333   prefs->SavePersistentPrefs();
334   NotifyOnLogin();
335   if (current_user_is_new_)
336     SetDefaultUserImage(email);
337 }
338 
RemoveUser(const std::string & email,RemoveUserDelegate * delegate)339 void UserManager::RemoveUser(const std::string& email,
340                              RemoveUserDelegate* delegate) {
341   // Get a copy of the current users.
342   std::vector<User> users = GetUsers();
343 
344   // Sanity check: we must not remove single user. This check may seem
345   // redundant at a first sight because this single user must be an owner and
346   // we perform special check later in order not to remove an owner.  However
347   // due to non-instant nature of ownership assignment this later check may
348   // sometimes fail. See http://crosbug.com/12723
349   if (users.size() < 2)
350     return;
351 
352   bool user_found = false;
353   for (size_t i = 0; !user_found && i < users.size(); ++i)
354     user_found = (email == users[i].email());
355   if (!user_found)
356     return;
357 
358   // |RemoveAttempt| deletes itself when done.
359   new RemoveAttempt(email, delegate);
360 }
361 
RemoveUserFromList(const std::string & email)362 void UserManager::RemoveUserFromList(const std::string& email) {
363   // Get a copy of the current users.
364   std::vector<User> users = GetUsers();
365 
366   // Clear the prefs view of the users.
367   PrefService* prefs = g_browser_process->local_state();
368   ListPrefUpdate prefs_users_update(prefs, kLoggedInUsers);
369   prefs_users_update->Clear();
370 
371   for (std::vector<User>::iterator it = users.begin();
372        it != users.end();
373        ++it) {
374     std::string user_email = it->email();
375     // Skip user that we would like to delete.
376     if (email != user_email)
377       prefs_users_update->Append(Value::CreateStringValue(user_email));
378   }
379 
380   DictionaryPrefUpdate prefs_images_update(prefs, kUserImages);
381   std::string image_path_string;
382   prefs_images_update->GetStringWithoutPathExpansion(email, &image_path_string);
383   prefs_images_update->RemoveWithoutPathExpansion(email, NULL);
384 
385   prefs->SavePersistentPrefs();
386 
387   int default_image_id = kDefaultImagesCount;
388   if (!IsDefaultImagePath(image_path_string, &default_image_id)) {
389     FilePath image_path(image_path_string);
390     BrowserThread::PostTask(
391         BrowserThread::FILE,
392         FROM_HERE,
393         NewRunnableFunction(&DeleteUserImage,
394                             image_path));
395   }
396 }
397 
IsKnownUser(const std::string & email)398 bool UserManager::IsKnownUser(const std::string& email) {
399   std::vector<User> users = GetUsers();
400   for (std::vector<User>::iterator it = users.begin();
401        it < users.end();
402        ++it) {
403     if (it->email() == email)
404       return true;
405   }
406 
407   return false;
408 }
409 
logged_in_user() const410 const UserManager::User& UserManager::logged_in_user() const {
411   return logged_in_user_;
412 }
413 
SetLoggedInUserImage(const SkBitmap & image)414 void UserManager::SetLoggedInUserImage(const SkBitmap& image) {
415   if (logged_in_user_.email().empty())
416     return;
417   OnImageLoaded(logged_in_user_.email(), image, false);
418 }
419 
LoadLoggedInUserImage(const FilePath & path)420 void UserManager::LoadLoggedInUserImage(const FilePath& path) {
421   if (logged_in_user_.email().empty())
422     return;
423   image_loader_->Start(logged_in_user_.email(), path.value(), true);
424 }
425 
SaveUserImage(const std::string & username,const SkBitmap & image)426 void UserManager::SaveUserImage(const std::string& username,
427                                 const SkBitmap& image) {
428   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
429   FilePath image_path = GetImagePathForUser(username);
430   DVLOG(1) << "Saving user image to " << image_path.value();
431 
432   BrowserThread::PostTask(
433       BrowserThread::FILE,
434       FROM_HERE,
435       NewRunnableFunction(&SaveImageToFile,
436                           image, image_path, username));
437 }
438 
SaveUserImagePath(const std::string & username,const std::string & image_path)439 void UserManager::SaveUserImagePath(const std::string& username,
440                                     const std::string& image_path) {
441   SavePathToLocalState(username, image_path);
442 }
443 
SetDefaultUserImage(const std::string & username)444 void UserManager::SetDefaultUserImage(const std::string& username) {
445   if (!g_browser_process)
446     return;
447 
448   PrefService* local_state = g_browser_process->local_state();
449   DCHECK(local_state);
450   const ListValue* prefs_users = local_state->GetList(kLoggedInUsers);
451   DCHECK(prefs_users);
452   const DictionaryValue* prefs_images =
453       local_state->GetDictionary(kUserImages);
454   DCHECK(prefs_images);
455 
456   // We want to distribute default images between users uniformly so that if
457   // there're more users with red image, we won't add red one for sure.
458   // Thus we count how many default images of each color are used and choose
459   // the first color with minimal usage.
460   std::vector<int> colors_count(kDefaultImagesCount, 0);
461   for (ListValue::const_iterator it = prefs_users->begin();
462        it != prefs_users->end();
463        ++it) {
464     std::string email;
465     if ((*it)->GetAsString(&email)) {
466       std::string image_path;
467       int default_image_id = kDefaultImagesCount;
468       if (prefs_images->GetStringWithoutPathExpansion(email, &image_path) &&
469           IsDefaultImagePath(image_path, &default_image_id)) {
470         DCHECK(default_image_id < kDefaultImagesCount);
471         ++colors_count[default_image_id];
472       }
473     }
474   }
475   std::vector<int>::const_iterator min_it =
476       std::min_element(colors_count.begin(), colors_count.end());
477   int selected_id = min_it - colors_count.begin();
478   std::string user_image_path =
479       GetDefaultImagePath(selected_id);
480   int resource_id = kDefaultImageResources[selected_id];
481   SkBitmap user_image = *ResourceBundle::GetSharedInstance().GetBitmapNamed(
482       resource_id);
483 
484   SavePathToLocalState(username, user_image_path);
485   SetLoggedInUserImage(user_image);
486 }
487 
GetUserDefaultImageIndex(const std::string & username)488 int UserManager::GetUserDefaultImageIndex(const std::string& username) {
489   if (!g_browser_process)
490     return -1;
491 
492   PrefService* local_state = g_browser_process->local_state();
493   const DictionaryValue* prefs_images = local_state->GetDictionary(kUserImages);
494 
495   if (!prefs_images)
496     return -1;
497 
498   std::string image_path;
499   if (!prefs_images->GetStringWithoutPathExpansion(username, &image_path))
500     return -1;
501 
502   int image_id = kDefaultImagesCount;
503   if (!IsDefaultImagePath(image_path, &image_id))
504     return -1;
505   return image_id;
506 }
507 
OnImageLoaded(const std::string & username,const SkBitmap & image,bool should_save_image)508 void UserManager::OnImageLoaded(const std::string& username,
509                                 const SkBitmap& image,
510                                 bool should_save_image) {
511   DVLOG(1) << "Loaded image for " << username;
512   user_images_[username] = image;
513   User user;
514   user.set_email(username);
515   user.set_image(image);
516   if (logged_in_user_.email() == username)
517     logged_in_user_.set_image(image);
518   if (should_save_image)
519     SaveUserImage(username, image);
520   NotificationService::current()->Notify(
521       NotificationType::LOGIN_USER_IMAGE_CHANGED,
522       Source<UserManager>(this),
523       Details<const User>(&user));
524 }
525 
IsLoggedInAsGuest() const526 bool UserManager::IsLoggedInAsGuest() const {
527   return logged_in_user().email() == kGuestUser;
528 }
529 
530 // Private constructor and destructor. Do nothing.
UserManager()531 UserManager::UserManager()
532     : ALLOW_THIS_IN_INITIALIZER_LIST(image_loader_(new UserImageLoader(this))),
533       current_user_is_owner_(false),
534       current_user_is_new_(false),
535       user_is_logged_in_(false) {
536   registrar_.Add(this, NotificationType::OWNER_KEY_FETCH_ATTEMPT_SUCCEEDED,
537       NotificationService::AllSources());
538 }
539 
~UserManager()540 UserManager::~UserManager() {
541   image_loader_->set_delegate(NULL);
542 }
543 
GetImagePathForUser(const std::string & username)544 FilePath UserManager::GetImagePathForUser(const std::string& username) {
545   std::string filename = username + ".png";
546   FilePath user_data_dir;
547   PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
548   return user_data_dir.AppendASCII(filename);
549 }
550 
551 class RealTPMTokenInfoDelegate : public crypto::TPMTokenInfoDelegate {
552  public:
553   RealTPMTokenInfoDelegate();
554   virtual ~RealTPMTokenInfoDelegate();
555   virtual bool IsTokenReady() const;
556   virtual void GetTokenInfo(std::string* token_name,
557                             std::string* user_pin) const;
558 };
559 
RealTPMTokenInfoDelegate()560 RealTPMTokenInfoDelegate::RealTPMTokenInfoDelegate() {}
~RealTPMTokenInfoDelegate()561 RealTPMTokenInfoDelegate::~RealTPMTokenInfoDelegate() {}
562 
IsTokenReady() const563 bool RealTPMTokenInfoDelegate::IsTokenReady() const {
564   return CrosLibrary::Get()->GetCryptohomeLibrary()->Pkcs11IsTpmTokenReady();
565 }
566 
GetTokenInfo(std::string * token_name,std::string * user_pin) const567 void RealTPMTokenInfoDelegate::GetTokenInfo(std::string* token_name,
568                                             std::string* user_pin) const {
569   std::string local_token_name;
570   std::string local_user_pin;
571   CrosLibrary::Get()->GetCryptohomeLibrary()->Pkcs11GetTpmTokenInfo(
572       &local_token_name, &local_user_pin);
573   if (token_name)
574     *token_name = local_token_name;
575   if (user_pin)
576     *user_pin = local_user_pin;
577 }
578 
NotifyOnLogin()579 void UserManager::NotifyOnLogin() {
580   NotificationService::current()->Notify(
581       NotificationType::LOGIN_USER_CHANGED,
582       Source<UserManager>(this),
583       Details<const User>(&logged_in_user_));
584 
585   chromeos::CrosLibrary::Get()->GetInputMethodLibrary()->
586       SetDeferImeStartup(false);
587   // Shut down the IME so that it will reload the user's settings.
588   chromeos::CrosLibrary::Get()->GetInputMethodLibrary()->
589       StopInputMethodDaemon();
590   // Let the window manager know that we're logged in now.
591   WmIpc::instance()->SetLoggedInProperty(true);
592   // Ensure we've opened the real user's key/certificate database.
593   crypto::OpenPersistentNSSDB();
594 
595   // Only load the Opencryptoki library into NSS if we have this switch.
596   // TODO(gspencer): Remove this switch once cryptohomed work is finished:
597   // http://crosbug.com/12295 and http://crosbug.com/12304
598   if (CommandLine::ForCurrentProcess()->HasSwitch(
599           switches::kLoadOpencryptoki)) {
600     crypto::EnableTPMTokenForNSS(new RealTPMTokenInfoDelegate());
601   }
602 
603   // Schedules current user ownership check on file thread.
604   BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
605       NewRunnableFunction(&CheckOwnership));
606 }
607 
Observe(NotificationType type,const NotificationSource & source,const NotificationDetails & details)608 void UserManager::Observe(NotificationType type,
609                           const NotificationSource& source,
610                           const NotificationDetails& details) {
611   if (type == NotificationType::OWNER_KEY_FETCH_ATTEMPT_SUCCEEDED) {
612     BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
613         NewRunnableFunction(&CheckOwnership));
614   }
615 }
616 
current_user_is_owner() const617 bool UserManager::current_user_is_owner() const {
618   base::AutoLock lk(current_user_is_owner_lock_);
619   return current_user_is_owner_;
620 }
621 
set_current_user_is_owner(bool current_user_is_owner)622 void UserManager::set_current_user_is_owner(bool current_user_is_owner) {
623   base::AutoLock lk(current_user_is_owner_lock_);
624   current_user_is_owner_ = current_user_is_owner;
625 }
626 
627 }  // namespace chromeos
628