Skip to content

Commit

Permalink
Implemented profile-aware owner key loading.
Browse files Browse the repository at this point in the history
BUG=230018
TEST=manual

Review URL: https://codereview.chromium.org/270663002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@271802 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
ygorshenin@chromium.org committed May 21, 2014
1 parent f571bc0 commit 196e53e
Show file tree
Hide file tree
Showing 22 changed files with 462 additions and 57 deletions.
6 changes: 4 additions & 2 deletions chrome/browser/chromeos/login/auth/parallel_authenticator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "chrome/browser/chromeos/login/auth/user_context.h"
#include "chrome/browser/chromeos/login/users/user.h"
#include "chrome/browser/chromeos/login/users/user_manager.h"
#include "chrome/browser/chromeos/ownership/owner_settings_service_factory.h"
#include "chrome/browser/chromeos/settings/cros_settings.h"
#include "chrome/common/chrome_switches.h"
#include "chromeos/cryptohome/async_method_caller.h"
Expand Down Expand Up @@ -488,9 +489,10 @@ bool ParallelAuthenticator::VerifyOwner() {
owner_is_verified_ = true;
return true;
}
// Now we can continue reading the private key.
DeviceSettingsService::Get()->SetUsername(

OwnerSettingsServiceFactory::GetInstance()->SetUsername(
current_state_->user_context.GetUserID());

// This should trigger certificate loading, which is needed in order to
// correctly determine if the current user is the owner.
if (LoginState::IsInitialized()) {
Expand Down
7 changes: 3 additions & 4 deletions chrome/browser/chromeos/login/users/user_manager_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#include "chrome/browser/chromeos/login/wizard_controller.h"
#include "chrome/browser/chromeos/net/network_portal_detector.h"
#include "chrome/browser/chromeos/net/network_portal_detector_strategy.h"
#include "chrome/browser/chromeos/ownership/owner_settings_service_factory.h"
#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
#include "chrome/browser/chromeos/policy/device_local_account.h"
#include "chrome/browser/chromeos/profiles/multiprofiles_session_aborted_dialog.h"
Expand Down Expand Up @@ -1566,10 +1567,8 @@ void UserManagerImpl::NotifyOnLogin() {
// Owner must be first user in session. DeviceSettingsService can't deal with
// multiple user and will mix up ownership, crbug.com/230018.
if (GetLoggedInUsers().size() == 1) {
// Indicate to DeviceSettingsService that the owner key may have become
// available.
DeviceSettingsService::Get()->SetUsername(active_user_->email());

OwnerSettingsServiceFactory::GetInstance()->SetUsername(
active_user_->email());
if (NetworkPortalDetector::IsInitialized()) {
NetworkPortalDetector::Get()->SetStrategy(
PortalDetectorStrategy::STRATEGY_ID_SESSION);
Expand Down
72 changes: 72 additions & 0 deletions chrome/browser/chromeos/ownership/owner_settings_service.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/chromeos/ownership/owner_settings_service.h"

#include <string>

#include "base/bind.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/chromeos/login/users/user.h"
#include "chrome/browser/chromeos/login/users/user_manager.h"
#include "chrome/browser/chromeos/ownership/owner_settings_service_factory.h"
#include "chrome/browser/chromeos/settings/device_settings_service.h"
#include "chrome/browser/profiles/profile.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_source.h"
#include "crypto/nss_util_internal.h"
#include "crypto/scoped_nss_types.h"

using content::BrowserThread;

namespace chromeos {

OwnerSettingsService::OwnerSettingsService(Profile* profile)
: profile_(profile), weak_factory_(this) {
registrar_.Add(this,
chrome::NOTIFICATION_PROFILE_CREATED,
content::Source<Profile>(profile_));
}

OwnerSettingsService::~OwnerSettingsService() {
}

void OwnerSettingsService::Observe(
int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
if (type != chrome::NOTIFICATION_PROFILE_CREATED) {
NOTREACHED();
return;
}

Profile* profile = content::Source<Profile>(source).ptr();
if (profile != profile_) {
NOTREACHED();
return;
}

ReloadOwnerKey();
}

void OwnerSettingsService::ReloadOwnerKey() {
if (!UserManager::IsInitialized())
return;
const User* user = UserManager::Get()->GetUserByProfile(profile_);
if (!user || !user->is_profile_created())
return;
std::string user_id = user->email();
if (user_id != OwnerSettingsServiceFactory::GetInstance()->GetUsername())
return;
BrowserThread::PostTaskAndReplyWithResult(
BrowserThread::IO,
FROM_HERE,
base::Bind(&crypto::GetPublicSlotForChromeOSUser, user->username_hash()),
base::Bind(&DeviceSettingsService::InitOwner,
base::Unretained(DeviceSettingsService::Get()),
user_id));
}

} // namespace chromeos
51 changes: 51 additions & 0 deletions chrome/browser/chromeos/ownership/owner_settings_service.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_CHROMEOS_OWNERSHIP_OWNER_SETTINGS_SERVICE_H_
#define CHROME_BROWSER_CHROMEOS_OWNERSHIP_OWNER_SETTINGS_SERVICE_H_

#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "components/keyed_service/core/keyed_service.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"

class Profile;

namespace chromeos {

// This class reloads owner key from profile NSS slots.
//
// TODO (ygorshenin@): move write path for device settings here
// (crbug.com/230018).
class OwnerSettingsService : public KeyedService,
public content::NotificationObserver {
public:
virtual ~OwnerSettingsService();

// NotificationObserver implementation:
virtual void Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) OVERRIDE;

private:
friend class OwnerSettingsServiceFactory;

explicit OwnerSettingsService(Profile* profile);

void ReloadOwnerKey();

Profile* profile_;

content::NotificationRegistrar registrar_;

base::WeakPtrFactory<OwnerSettingsService> weak_factory_;

DISALLOW_COPY_AND_ASSIGN(OwnerSettingsService);
};

} // namespace chromeos

#endif // CHROME_BROWSER_CHROMEOS_OWNERSHIP_OWNER_SETTINGS_SERVICE_H_
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/chromeos/ownership/owner_settings_service_factory.h"

#include "chrome/browser/chromeos/login/users/user.h"
#include "chrome/browser/chromeos/login/users/user_manager.h"
#include "chrome/browser/chromeos/ownership/owner_settings_service.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/profiles/profile.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"

namespace chromeos {

OwnerSettingsServiceFactory::OwnerSettingsServiceFactory()
: BrowserContextKeyedServiceFactory(
"OwnerSettingsService",
BrowserContextDependencyManager::GetInstance()) {
}

OwnerSettingsServiceFactory::~OwnerSettingsServiceFactory() {
}

// static
OwnerSettingsService* OwnerSettingsServiceFactory::GetForProfile(
Profile* profile) {
return static_cast<OwnerSettingsService*>(
GetInstance()->GetServiceForBrowserContext(profile, true));
}

// static
OwnerSettingsServiceFactory* OwnerSettingsServiceFactory::GetInstance() {
return Singleton<OwnerSettingsServiceFactory>::get();
}

void OwnerSettingsServiceFactory::SetUsername(const std::string& username) {
username_ = username;
if (!UserManager::IsInitialized())
return;
const User* user = UserManager::Get()->FindUser(username_);
if (!user || !user->is_profile_created())
return;
Profile* profile = UserManager::Get()->GetProfileByUser(user);
if (!profile)
return;
OwnerSettingsService* service = GetForProfile(profile);

// It's safe to call ReloadOwnerKey() here, as profile is fully created
// at this time.
if (service)
service->ReloadOwnerKey();
}

std::string OwnerSettingsServiceFactory::GetUsername() const {
return username_;
}

// static
KeyedService* OwnerSettingsServiceFactory::BuildInstanceFor(
content::BrowserContext* browser_context) {
Profile* profile = static_cast<Profile*>(browser_context);
if (profile->IsGuestSession() || ProfileHelper::IsSigninProfile(profile))
return NULL;
return new OwnerSettingsService(profile);
}

bool OwnerSettingsServiceFactory::ServiceIsCreatedWithBrowserContext() const {
return true;
}

KeyedService* OwnerSettingsServiceFactory::BuildServiceInstanceFor(
content::BrowserContext* context) const {
return BuildInstanceFor(context);
}

} // namespace chromeos
60 changes: 60 additions & 0 deletions chrome/browser/chromeos/ownership/owner_settings_service_factory.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_CHROMEOS_OWNERSHIP_OWNER_SETTINGS_SERVICE_FACTORY_H_
#define CHROME_BROWSER_CHROMEOS_OWNERSHIP_OWNER_SETTINGS_SERVICE_FACTORY_H_

#include <string>

#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/singleton.h"
#include "components/keyed_service/content/browser_context_keyed_service_factory.h"

class KeyedService;
class Profile;

namespace chromeos {

class OwnerSettingsService;

class OwnerSettingsServiceFactory : public BrowserContextKeyedServiceFactory {
public:
static OwnerSettingsService* GetForProfile(Profile* profile);

static OwnerSettingsServiceFactory* GetInstance();

// Sets name of the user supposed to be an owner. If profile
// for |username| is ready, request to reload owner key will be
// sent. Otherwise, owner key will be reloaded as soon as profile will
// be ready.
void SetUsername(const std::string& username);

// Returns the name of the user supposed to be an owner.
std::string GetUsername() const;

private:
friend struct DefaultSingletonTraits<OwnerSettingsServiceFactory>;

OwnerSettingsServiceFactory();
virtual ~OwnerSettingsServiceFactory();

static KeyedService* BuildInstanceFor(content::BrowserContext* context);

// BrowserContextKeyedBaseFactory overrides:
virtual bool ServiceIsCreatedWithBrowserContext() const OVERRIDE;

// BrowserContextKeyedServiceFactory implementation:
virtual KeyedService* BuildServiceInstanceFor(
content::BrowserContext* browser_context) const OVERRIDE;

// Name of the user supposed to be an owner.
std::string username_;

DISALLOW_COPY_AND_ASSIGN(OwnerSettingsServiceFactory);
};

} // namespace chromeos

#endif // CHROME_BROWSER_CHROMEOS_OWNERSHIP_OWNER_SETTINGS_SERVICE_FACTORY_H_
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,8 @@ void LoginScreenDefaultPolicyInSessionBrowsertest::SetUpOnMainThread() {
LoginScreenDefaultPolicyBrowsertestBase::SetUpOnMainThread();

// Tell the DeviceSettingsService that there is no local owner.
chromeos::DeviceSettingsService::Get()->SetUsername(std::string());
crypto::ScopedPK11Slot slot;
chromeos::DeviceSettingsService::Get()->InitOwner(std::string(), slot.Pass());
}

void LoginScreenDefaultPolicyInSessionBrowsertest::VerifyPrefFollowsDefault(
Expand Down
3 changes: 2 additions & 1 deletion chrome/browser/chromeos/policy/power_policy_browsertest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,8 @@ void PowerPolicyInSessionBrowserTest::SetUpOnMainThread() {
PowerPolicyBrowserTestBase::SetUpOnMainThread();

// Tell the DeviceSettingsService that there is no local owner.
chromeos::DeviceSettingsService::Get()->SetUsername(std::string());
crypto::ScopedPK11Slot slot;
chromeos::DeviceSettingsService::Get()->InitOwner(std::string(), slot.Pass());
}

// Verifies that device policy is applied on the login screen.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,9 @@ TEST_F(DeviceSettingsProviderTest, SetPrefFailed) {

TEST_F(DeviceSettingsProviderTest, SetPrefSucceed) {
owner_key_util_->SetPrivateKey(device_policy_.GetSigningKey());
device_settings_service_.SetUsername(device_policy_.policy_data().username());
crypto::ScopedPK11Slot slot;
device_settings_service_.InitOwner(device_policy_.policy_data().username(),
slot.Pass());
FlushDeviceSettings();

base::FundamentalValue value(true);
Expand Down Expand Up @@ -167,7 +169,9 @@ TEST_F(DeviceSettingsProviderTest, SetPrefSucceed) {

TEST_F(DeviceSettingsProviderTest, SetPrefTwice) {
owner_key_util_->SetPrivateKey(device_policy_.GetSigningKey());
device_settings_service_.SetUsername(device_policy_.policy_data().username());
crypto::ScopedPK11Slot slot;
device_settings_service_.InitOwner(device_policy_.policy_data().username(),
slot.Pass());
FlushDeviceSettings();

EXPECT_CALL(*this, SettingChanged(_)).Times(AnyNumber());
Expand Down
16 changes: 13 additions & 3 deletions chrome/browser/chromeos/settings/device_settings_service.cc
Original file line number Diff line number Diff line change
Expand Up @@ -232,8 +232,13 @@ void DeviceSettingsService::IsCurrentUserOwnerAsync(
}
}

void DeviceSettingsService::SetUsername(const std::string& username) {
void DeviceSettingsService::InitOwner(const std::string& username,
crypto::ScopedPK11Slot slot) {
if (!username_.empty())
return;

username_ = username;
slot_ = slot.Pass();

// The private key may have become available, so force a key reload.
owner_key_ = NULL;
Expand Down Expand Up @@ -292,14 +297,19 @@ void DeviceSettingsService::EnqueueLoad(bool force_key_load) {
weak_factory_.GetWeakPtr(),
base::Closure()));
operation->set_force_key_load(force_key_load);
operation->set_username(username_);
operation->set_slot(slot_.get());
Enqueue(operation);
}

void DeviceSettingsService::EnsureReload(bool force_key_load) {
if (!pending_operations_.empty())
if (!pending_operations_.empty()) {
pending_operations_.front()->set_username(username_);
pending_operations_.front()->set_slot(slot_.get());
pending_operations_.front()->RestartLoad(force_key_load);
else
} else {
EnqueueLoad(force_key_load);
}
}

void DeviceSettingsService::StartNextOperation() {
Expand Down
Loading

0 comments on commit 196e53e

Please sign in to comment.