C++程序  |  149行  |  5.88 KB

// Copyright (c) 2011 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_LOGIN_OWNERSHIP_SERVICE_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_OWNERSHIP_SERVICE_H_
#pragma once

#include <string>
#include <vector>

#include "base/callback.h"
#include "base/synchronization/lock.h"
#include "chrome/browser/chromeos/login/owner_key_utils.h"
#include "chrome/browser/chromeos/login/owner_manager.h"
#include "chrome/browser/policy/proto/device_management_backend.pb.h"
#include "content/browser/browser_thread.h"
#include "content/common/notification_observer.h"
#include "content/common/notification_registrar.h"
#include "content/common/notification_service.h"

namespace base {
template <typename T> struct DefaultLazyInstanceTraits;
}

namespace em = enterprise_management;
namespace chromeos {

class OwnershipService : public NotificationObserver {
 public:
  enum Status {
    // Listed in upgrade order.
    OWNERSHIP_UNKNOWN = 0,
    OWNERSHIP_NONE,
    OWNERSHIP_TAKEN
  };

  // Returns the singleton instance of the OwnershipService.
  static OwnershipService* GetSharedInstance();
  virtual ~OwnershipService();

  // Called after FILE thread is created to prefetch ownership status and avoid
  // blocking on UI thread.
  void Prewarm();

  // Owner settings are being re-implemented as a single, signed protobuf
  // that is stored by the session manager.  Thus, to write a setting, you
  // need to have the existing policy, update it, re-sign it, and then have
  // it stored.  This could be done by requesting the policy every time, or
  // by caching it and updating it upon every successful store.
  // Caching is faster and easier, so we'll do that.  These are the
  // getters/setters for the cached policy.
  virtual void set_cached_policy(const em::PolicyData& pol);
  virtual bool has_cached_policy();
  virtual const em::PolicyData& cached_policy();

  // Sets a new owner key. This will _not_ load the key material from disk, but
  // rather update Chrome's in-memory copy of the key. |callback| will be
  // invoked once the operation completes.
  virtual void StartUpdateOwnerKey(const std::vector<uint8>& new_key,
                                   OwnerManager::KeyUpdateDelegate* d);

  // If the device has been owned already, posts a task to the FILE thread to
  // fetch the public key off disk.
  //
  // Sends out a OWNER_KEY_FETCH_ATTEMPT_SUCCESS notification on success,
  // OWNER_KEY_FETCH_ATTEMPT_FAILED on failure.
  virtual void StartLoadOwnerKeyAttempt();

  // Initiate an attempt to sign |data| with |private_key_|.  Will call
  // d->OnKeyOpComplete() when done.  Upon success, the signature will be passed
  // as the |payload| argument to d->OnKeyOpComplete().
  //
  // If you call this on a well-known thread, you'll be called back on that
  // thread.  Otherwise, you'll get called back on the UI thread.
  virtual void StartSigningAttempt(const std::string& data,
                                   OwnerManager::Delegate* d);

  // Initiate an attempt to verify that |signature| is valid over |data| with
  // |public_key_|.  When the attempt is completed, an appropriate KeyOpCode
  // will be passed to d->OnKeyOpComplete().
  //
  // If you call this on a well-known thread, you'll be called back on that
  // thread.  Otherwise, you'll get called back on the UI thread.
  virtual void StartVerifyAttempt(const std::string& data,
                                  const std::vector<uint8>& signature,
                                  OwnerManager::Delegate* d);

  // This method must be run on the FILE thread.
  virtual bool CurrentUserIsOwner();

  // This method should be run on FILE thread.
  // Note: not static, for better mocking.
  virtual bool IsAlreadyOwned();

  // This method can be run either on FILE or UI threads.  If |blocking| flag
  // is specified then it is guaranteed to return either OWNERSHIP_NONE or
  // OWNERSHIP_TAKEN (and not OWNERSHIP_UNKNOWN), however in this case it may
  // occasionally block doing i/o.
  virtual Status GetStatus(bool blocking);

 protected:
  OwnershipService();

  // NotificationObserver implementation.
  virtual void Observe(NotificationType type,
                       const NotificationSource& source,
                       const NotificationDetails& details);

 private:
  friend struct base::DefaultLazyInstanceTraits<OwnershipService>;
  friend class OwnershipServiceTest;

  // Task posted on FILE thread on startup to prefetch ownership status.
  void FetchStatus();

  // Sets ownership status. May be called on either thread.
  void SetStatus(Status new_status);

  static void UpdateOwnerKey(OwnershipService* service,
                             const BrowserThread::ID thread_id,
                             const std::vector<uint8>& new_key,
                             OwnerManager::KeyUpdateDelegate* d);
  static void TryLoadOwnerKeyAttempt(OwnershipService* service);
  static void TrySigningAttempt(OwnershipService* service,
                                const BrowserThread::ID thread_id,
                                const std::string& data,
                                OwnerManager::Delegate* d);
  static void TryVerifyAttempt(OwnershipService* service,
                               const BrowserThread::ID thread_id,
                               const std::string& data,
                               const std::vector<uint8>& signature,
                               OwnerManager::Delegate* d);
  static void FailAttempt(OwnerManager::Delegate* d);

  OwnerManager* manager() { return manager_.get(); }

  scoped_refptr<OwnerManager> manager_;
  scoped_refptr<OwnerKeyUtils> utils_;
  scoped_ptr<em::PolicyData> policy_;
  NotificationRegistrar notification_registrar_;
  volatile Status ownership_status_;
  base::Lock ownership_status_lock_;
};

}  // namespace chromeos

#endif  // CHROME_BROWSER_CHROMEOS_LOGIN_OWNERSHIP_SERVICE_H_