Home | History | Annotate | Download | only in login
      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.
     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.
     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.
     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.
    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.
    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.
    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 
    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 
    172   void RemoveUserCryptohome() {
    173     if (CrosLibrary::Get()->EnsureLoaded()) {
    174       CrosLibrary::Get()->GetCryptohomeLibrary()->AsyncRemove(user_email_,
    175                                                               this);
    176     }
    177   }
    178 
    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 
    200 UserManager::User::User() {
    201   image_ = *ResourceBundle::GetSharedInstance().GetBitmapNamed(
    202       kDefaultImageResources[0]);
    203 }
    204 
    205 UserManager::User::~User() {}
    206 
    207 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 
    215 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
    231 UserManager* UserManager::Get() {
    232   // Not thread-safe.
    233   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    234   return &g_user_manager.Get();
    235 }
    236 
    237 // static
    238 void UserManager::RegisterPrefs(PrefService* local_state) {
    239   local_state->RegisterListPref(kLoggedInUsers);
    240   local_state->RegisterDictionaryPref(kUserImages);
    241 }
    242 
    243 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 
    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 
    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 
    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 
    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 
    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 
    410 const UserManager::User& UserManager::logged_in_user() const {
    411   return logged_in_user_;
    412 }
    413 
    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 
    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 
    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 
    439 void UserManager::SaveUserImagePath(const std::string& username,
    440                                     const std::string& image_path) {
    441   SavePathToLocalState(username, image_path);
    442 }
    443 
    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 
    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 
    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 
    526 bool UserManager::IsLoggedInAsGuest() const {
    527   return logged_in_user().email() == kGuestUser;
    528 }
    529 
    530 // Private constructor and destructor. Do nothing.
    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 
    540 UserManager::~UserManager() {
    541   image_loader_->set_delegate(NULL);
    542 }
    543 
    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 
    560 RealTPMTokenInfoDelegate::RealTPMTokenInfoDelegate() {}
    561 RealTPMTokenInfoDelegate::~RealTPMTokenInfoDelegate() {}
    562 
    563 bool RealTPMTokenInfoDelegate::IsTokenReady() const {
    564   return CrosLibrary::Get()->GetCryptohomeLibrary()->Pkcs11IsTpmTokenReady();
    565 }
    566 
    567 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 
    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 
    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 
    617 bool UserManager::current_user_is_owner() const {
    618   base::AutoLock lk(current_user_is_owner_lock_);
    619   return current_user_is_owner_;
    620 }
    621 
    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