// Copyright (c) 2012 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_POLICY_POLICY_LOADER_WIN_H_
#define CHROME_BROWSER_POLICY_POLICY_LOADER_WIN_H_

#include <userenv.h>
#include <windows.h>

#include "base/basictypes.h"
#include "base/files/file_path.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/string16.h"
#include "base/synchronization/waitable_event.h"
#include "base/values.h"
#include "base/win/object_watcher.h"
#include "chrome/browser/policy/async_policy_loader.h"
#include "components/policy/core/common/policy_types.h"

namespace base {
class SequencedTaskRunner;
}

namespace policy {

class AppliedGPOListProvider;
class PolicyLoadStatusSample;
class PolicyMap;
class RegistryDict;

// Interface for mocking out GPO enumeration in tests.
class AppliedGPOListProvider {
 public:
  virtual ~AppliedGPOListProvider() {}
  virtual DWORD GetAppliedGPOList(DWORD flags,
                                  LPCTSTR machine_name,
                                  PSID sid_user,
                                  GUID* extension_guid,
                                  PGROUP_POLICY_OBJECT* gpo_list) = 0;
  virtual BOOL FreeGPOList(PGROUP_POLICY_OBJECT gpo_list) = 0;
};

// Loads policies from the Windows registry, and watches for Group Policy
// notifications to trigger reloads.
class PolicyLoaderWin : public AsyncPolicyLoader,
                        public base::win::ObjectWatcher::Delegate {
 public:
  // The PReg file name used by GPO.
  static const base::FilePath::CharType kPRegFileName[];

  PolicyLoaderWin(scoped_refptr<base::SequencedTaskRunner> task_runner,
                  const string16& chrome_policy_key,
                  AppliedGPOListProvider* gpo_provider);
  virtual ~PolicyLoaderWin();

  // Creates a policy loader that uses the Win API to access GPO.
  static scoped_ptr<PolicyLoaderWin> Create(
      scoped_refptr<base::SequencedTaskRunner> task_runner,
      const string16& chrome_policy_key);

  // AsyncPolicyLoader implementation.
  virtual void InitOnBackgroundThread() OVERRIDE;
  virtual scoped_ptr<PolicyBundle> Load() OVERRIDE;

 private:
  // Builds the Chrome policy schema in |chrome_policy_schema_|.
  void BuildChromePolicySchema();

  // Reads Chrome Policy from a PReg file at the given path and stores the
  // result in |policy|.
  bool ReadPRegFile(const base::FilePath& preg_file,
                    RegistryDict* policy,
                    PolicyLoadStatusSample *status);

  // Loads and parses GPO policy in |policy_object_list| for scope |scope|. If
  // successful, stores the result in |policy| and returns true. Returns false
  // on failure reading the policy, indicating that policy loading should fall
  // back to reading the registry.
  bool LoadGPOPolicy(PolicyScope scope,
                     PGROUP_POLICY_OBJECT policy_object_list,
                     RegistryDict* policy,
                     PolicyLoadStatusSample *status);

  // Queries Windows for applied group policy and writes the result to |policy|.
  // This is the preferred way to obtain GPO data, there are reports of abuse
  // of the registry GPO keys by 3rd-party software.
  bool ReadPolicyFromGPO(PolicyScope scope,
                         RegistryDict* policy,
                         PolicyLoadStatusSample *status);

  // Parses Chrome policy from |gpo_dict| for the given |scope| and |level| and
  // merges it into |chrome_policy_map|.
  void LoadChromePolicy(const RegistryDict* gpo_dict,
                        PolicyLevel level,
                        PolicyScope scope,
                        PolicyMap* chrome_policy_map);

  // Loads 3rd-party policy from |gpo_dict| and merges it into |bundle|.
  void Load3rdPartyPolicy(const RegistryDict* gpo_dict,
                          PolicyScope scope,
                          PolicyBundle* bundle);

  // Installs the watchers for the Group Policy update events.
  void SetupWatches();

  // ObjectWatcher::Delegate overrides:
  virtual void OnObjectSignaled(HANDLE object) OVERRIDE;

  bool is_initialized_;
  const string16 chrome_policy_key_;
  class AppliedGPOListProvider* gpo_provider_;
  base::DictionaryValue chrome_policy_schema_;

  base::WaitableEvent user_policy_changed_event_;
  base::WaitableEvent machine_policy_changed_event_;
  base::win::ObjectWatcher user_policy_watcher_;
  base::win::ObjectWatcher machine_policy_watcher_;
  bool user_policy_watcher_failed_;
  bool machine_policy_watcher_failed_;

  DISALLOW_COPY_AND_ASSIGN(PolicyLoaderWin);
};

}  // namespace policy

#endif  // CHROME_BROWSER_POLICY_POLICY_LOADER_WIN_H_
