diff options
author | gwilson@google.com <gwilson@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-11-25 19:06:28 +0000 |
---|---|---|
committer | gwilson@google.com <gwilson@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-11-25 19:06:28 +0000 |
commit | 64134fec4ed2f78dde84c6533dd2cc962f365ae6 (patch) | |
tree | 5a40bcf928d3476b44722950fe1fb7c131013337 /chrome | |
parent | d1279211a457750c5b8717fe6790a838061632a8 (diff) | |
download | chromium_src-64134fec4ed2f78dde84c6533dd2cc962f365ae6.zip chromium_src-64134fec4ed2f78dde84c6533dd2cc962f365ae6.tar.gz chromium_src-64134fec4ed2f78dde84c6533dd2cc962f365ae6.tar.bz2 |
Adds basic group policy support. Does not wire the settings to the preferences yet, but at least adds support for looking in the right place.
R=cpu,kuchhal
TEST=unit test included
BUG=19374
Review URL: http://codereview.chromium.org/405003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@33093 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/group_policy.cc | 478 | ||||
-rw-r--r-- | chrome/browser/group_policy.h | 157 | ||||
-rw-r--r-- | chrome/browser/group_policy_settings.cc | 22 | ||||
-rw-r--r-- | chrome/browser/group_policy_settings.h | 51 | ||||
-rw-r--r-- | chrome/browser/group_policy_unittest.cc | 152 | ||||
-rwxr-xr-x | chrome/chrome.gyp | 11 |
6 files changed, 871 insertions, 0 deletions
diff --git a/chrome/browser/group_policy.cc b/chrome/browser/group_policy.cc new file mode 100644 index 0000000..1074ce0 --- /dev/null +++ b/chrome/browser/group_policy.cc @@ -0,0 +1,478 @@ +// Copyright (c) 2009 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. +// +// Implementation of group policy lookup code. + +#include "base/logging.h" +#include "base/registry.h" +#include "base/scoped_ptr.h" +#include "base/string_util.h" +#include "base/values.h" +#include "build/build_config.h" +#include "chrome/browser/group_policy.h" +#include "chrome/browser/group_policy_settings.h" +#include "chrome/installer/util/browser_distribution.h" + +namespace group_policy { + +// In GetPolicySettingsRootKey(), this gets appended with: +// [Publisher Name]\\[App name]\\. Thus, this should be +// SOFTWARE\\Policies\\Chromium\\Chromium\\ in the case of Chromium. +#define kPolicyKey L"SOFTWARE\\Policies\\" + +bool g_has_hklm_policies = false; +bool g_has_hkcu_policies = false; +bool g_has_settings_initialized = false; + +// Get the root registry location of group policy settings. +bool GetPolicySettingsRootKey(std::wstring* policy_key) { + BrowserDistribution* dist = BrowserDistribution::GetDistribution(); + std::wstring app_name = dist->GetApplicationName(); + std::wstring publisher_name = dist->GetPublisherName(); + std::wstring separator = std::wstring(L"\\"); + policy_key->append(kPolicyKey); + policy_key->append(app_name); + policy_key->append(separator); + policy_key->append(publisher_name); + policy_key->append(separator); + return true; +} + +// TODO(gwilson): Add a method that will check if group policy settings have +// been updated since we last checked, so as not to require a restart. +bool HasGroupPolicySettings() { + if (g_has_settings_initialized) + return g_has_hkcu_policies || g_has_hklm_policies; + std::wstring policy_key(L""); + GetPolicySettingsRootKey(&policy_key); + RegKey hkcu = RegKey(HKEY_CURRENT_USER, policy_key.c_str(), KEY_QUERY_VALUE); + RegKey hklm = RegKey(HKEY_LOCAL_MACHINE, policy_key.c_str(), KEY_QUERY_VALUE); + g_has_hkcu_policies = hkcu.Valid(); + g_has_hklm_policies = hklm.Valid(); + g_has_settings_initialized = true; + return g_has_hkcu_policies || g_has_hklm_policies; +} + +bool HasHkcuSettings() { + if (!g_has_settings_initialized) + HasGroupPolicySettings(); + return g_has_hkcu_policies; +} + +bool HasHklmSettings() { + if (!g_has_settings_initialized) + HasGroupPolicySettings(); + return g_has_hklm_policies; +} + +// Returns true iff the setting is currently controlled by group policy. +// If anyone adds a policy that can only be present in HKLM or HKCU but +// not both, this code will need to be updated to reflect that. +bool SettingBase::IsPolicyControlled() const { + DCHECK(regvalue_ != NULL && regkey_ != NULL) << + "Setting not initialized - don't call at static init time!"; + + if (!HasGroupPolicySettings()) + return false; + + std::wstring regkey_path(L""); + DCHECK(GetPolicySettingsRootKey(®key_path)); + regkey_path.append(regkey_); + + if (HasHklmSettings()) { + RegKey key; + HRESULT hr; + hr = key.Open(HKEY_LOCAL_MACHINE, regkey_path.c_str(), KEY_QUERY_VALUE); + if (SUCCEEDED(hr) && key.ValueExists(regvalue_)) + return true; + } + + if (HasHkcuSettings()) { + RegKey key; + HRESULT hr; + hr = key.Open(HKEY_CURRENT_USER, regkey_path.c_str(), KEY_QUERY_VALUE); + if (SUCCEEDED(hr) && key.ValueExists(regvalue_)) + return true; + } + + return false; +} + +// Gets the current policy setting as a wstring. +HRESULT SettingBase::GetSetting(std::wstring* value, bool* found) const { + // Default to an empty value. + value->clear(); + + // Failure is perfectly normal here, but continue to check HKCU. + std::wstring hklm_value(L""); + bool hklm_found = false; + if (HasHklmSettings()) + GetSettingFromTree(HKEY_LOCAL_MACHINE, &hklm_value, &hklm_found); + + std::wstring hkcu_value(L""); + bool hkcu_found = false; + if (HasHkcuSettings()) + GetSettingFromTree(HKEY_CURRENT_USER, &hkcu_value, &hkcu_found); + + switch (combine_) { + case POLICYCOMBINE_PREFERMACHINE: + if (hklm_found) { + value->assign(hklm_value); + *found = true; + } else if (hkcu_found) { + value->assign(hkcu_value); + *found = true; + } + break; + + case POLICYCOMBINE_PREFERUSER: + if (hkcu_found) { + value->assign(hkcu_value); + *found = true; + } else if (hklm_found) { + value->assign(hklm_value); + *found = true; + } + break; + + case POLICYCOMBINE_CONCATENATE: + if (hklm_found) { + value->assign(hklm_value); + *found = true; + } + if (hkcu_found) { + value->append(hkcu_value); + *found = true; + } + break; + + default: + DCHECK(FALSE) << "Unimplemented"; + NOTREACHED(); + break; + } + + return S_OK; +} + +// Gets the current policy setting as a ListVale of StringValue objects. +HRESULT SettingBase::GetSetting(ListValue* list, bool* found) const { + if (regvalue_ == NULL || regkey_ == NULL) + return E_UNEXPECTED; + + // Failure is perfectly normal here, but continue to check HKCU. + scoped_ptr<ListValue> hklm_value(new ListValue()); + bool hklm_found = false; + if (HasHklmSettings()) + GetSettingFromTree(HKEY_LOCAL_MACHINE, hklm_value.get(), &hklm_found); + + scoped_ptr<ListValue> hkcu_value(new ListValue()); + bool hkcu_found = false; + if (HasHkcuSettings()) + GetSettingFromTree(HKEY_CURRENT_USER, hkcu_value.get(), &hkcu_found); + + // TODO(gwilson): Optimize / refactor this algorithm so that all of the + // GetSetting() methods only read from the keys they must, rather than + // reading from both HKCU and HKLM now. + switch (combine_) { + case POLICYCOMBINE_PREFERMACHINE: + if (hklm_found) { + AppendAll(list, hklm_value.get()); + *found = true; + } else if (hkcu_found) { + AppendAll(list, hkcu_value.get()); + *found = true; + } + break; + + case POLICYCOMBINE_PREFERUSER: + if (hkcu_found) { + AppendAll(list, hkcu_value.get()); + *found = true; + } else if (hklm_found) { + AppendAll(list, hklm_value.get()); + *found = true; + } + break; + + case POLICYCOMBINE_CONCATENATE: + if (hklm_found) { + AppendAll(list, hklm_value.get()); + *found = true; + } + if (hkcu_found) { + AppendAll(list, hkcu_value.get()); + *found = true; + } + break; + + default: + DCHECK(FALSE) << "Unimplemented"; + NOTREACHED(); + break; + } + + return S_OK; +} + +void AppendAll(ListValue* target, ListValue* source) { + DCHECK(source); + DCHECK(target); + for (size_t i = 0; i < source->GetSize(); ++i) { + // The string must be copied here, since the Value object in the + // source list gets destroyed before we return the target list. + std::string str; + source->GetString(i, &str); + target->Append(Value::CreateStringValue(str)); + } +} + +// Gets the current policy setting as a bool. +HRESULT SettingBase::GetSetting(bool* value, bool* found) const { + // Default to false. + *value = false; + + // Failure is perfectly normal here, but continue to check HKCU. + bool hklm_value = false; + bool hklm_found = false; + if (HasHklmSettings()) + GetSettingFromTree(HKEY_LOCAL_MACHINE, &hklm_value, &hklm_found); + + bool hkcu_value = false; + bool hkcu_found = false; + if (HasHkcuSettings()) + GetSettingFromTree(HKEY_CURRENT_USER, &hkcu_value, &hkcu_found); + + switch (combine_) { + case POLICYCOMBINE_PREFERMACHINE: + if (hklm_found) { + *value = hklm_value; + *found = true; + } else if (hkcu_found) { + *value = hkcu_value; + *found = true; + } + break; + + case POLICYCOMBINE_PREFERUSER: + if (hkcu_found) { + *value = hkcu_value; + *found = true; + } else if (hklm_found) { + *value = hklm_value; + *found = true; + } + break; + + case POLICYCOMBINE_LOGICALOR: + *value = hkcu_value || hklm_value; + *found = hkcu_found || hklm_found; + break; + + default: + DCHECK(FALSE) << "Unimplemented"; + NOTREACHED(); + break; + } + + return S_OK; +} + +// Gets the current policy setting as a DWORD. +HRESULT SettingBase::GetSetting(DWORD* value, bool* found) const { + // Default to zero. + *value = 0; + + // Failure is perfectly normal here, but continue to check HKCU. + DWORD hklm_value = 0; + bool hklm_found = false; + if (HasHklmSettings()) + GetSettingFromTree(HKEY_LOCAL_MACHINE, &hklm_value, &hklm_found); + + DWORD hkcu_value = 0; + bool hkcu_found = false; + if (HasHkcuSettings()) + GetSettingFromTree(HKEY_CURRENT_USER, &hkcu_value, &hkcu_found); + + switch (combine_) { + case POLICYCOMBINE_PREFERMACHINE: + if (hklm_found) { + *value = hklm_value; + *found = true; + } else if (hkcu_found) { + *value = hkcu_value; + *found = true; + } + break; + + case POLICYCOMBINE_PREFERUSER: + if (hkcu_found) { + *value = hkcu_value; + *found = true; + } else if (hklm_found) { + *value = hklm_value; + *found = true; + } + break; + + case POLICYCOMBINE_LOGICALOR: + *value = hkcu_value || hklm_value; + *found = hkcu_found || hklm_found; + break; + + default: + DCHECK(FALSE) << "Unimplemented"; + NOTREACHED(); + break; + } + + return S_OK; +} + +// Gets the current policy setting in the specified tree. +HRESULT SettingBase::GetSettingFromTree(HKEY tree, DWORD* value, + bool* found) const { + *found = false; + + std::wstring reg_value_name(L""); + DCHECK(GetPolicySettingsRootKey(®_value_name)); + reg_value_name.append(regkey_); + + HRESULT hr; + RegKey key; + // Failure is perfectly normal here. + hr = key.Open(tree, reg_value_name.c_str(), KEY_QUERY_VALUE); + + if (FAILED(hr)) + return hr; + + DCHECK(storage_ == POLICYSTORAGE_SINGLEVALUE); + hr = key.ReadValueDW(regvalue_, value); + if (FAILED(hr)) + return hr; + + *found = true; + + return hr; +} + +// Gets the current policy setting in the specified tree. +HRESULT SettingBase::GetSettingFromTree(HKEY tree, ListValue* list, + bool* found) const { + *found = false; + list->Clear(); + + std::wstring reg_value_name(L""); + DCHECK(GetPolicySettingsRootKey(®_value_name)); + reg_value_name.append(regkey_); + + HRESULT hr; + RegKey key; + // Failure is perfectly normal here. + hr = key.Open(tree, + reg_value_name.c_str(), + KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS); + if (FAILED(hr)) + return hr; + + std::wstring reg_value; + switch (storage_) { + case POLICYSTORAGE_SINGLEVALUE: + hr = key.ReadValue(regvalue_, ®_value); + if (FAILED(hr)) + return hr; + list->Append(list->CreateStringValue(reg_value)); + *found = true; + break; + + case POLICYSTORAGE_CONCATSUBKEYS: { + int key_count = key.ValueCount(); + if (key_count == 0) { + hr = E_FAIL; + } else { + // We'll return S_OK if we can succesfully read any of the subkeys. + hr = E_FAIL; + RegistryValueIterator iterator(tree, reg_value_name.c_str()); + for (; iterator.Valid(); ++iterator) { + if (SUCCEEDED(key.ReadValue(iterator.Name(), ®_value))) { + list->Append(Value::CreateStringValue(reg_value.c_str())); + *found = true; + hr = S_OK; + } + } + } + } + break; + } + return hr; +} + +// Gets the current policy setting in the specified tree. +HRESULT SettingBase::GetSettingFromTree(HKEY tree, std::wstring* value, + bool* found) const { + *found = false; + value->clear(); + + std::wstring reg_value_name(L""); + DCHECK(GetPolicySettingsRootKey(®_value_name)); + reg_value_name.append(regkey_); + + HRESULT hr; + RegKey key; + // Failure is perfectly normal here. + hr = key.Open(tree, reg_value_name.c_str(), KEY_QUERY_VALUE); + if (FAILED(hr)) + return hr; + + DCHECK(storage_ == POLICYSTORAGE_SINGLEVALUE); + + hr = key.ReadValue(regvalue_, value); + if (FAILED(hr)) + return hr; + + *found = true; + + return hr; +} + +// Gets the current policy setting in the specified tree. +HRESULT SettingBase::GetSettingFromTree(HKEY tree, bool* value, + bool* found) const { + *found = false; + + std::wstring reg_value_name(L""); + DCHECK(GetPolicySettingsRootKey(®_value_name)); + reg_value_name.append(regkey_); + + HRESULT hr; + RegKey key; + // Failure is perfectly normal here. + hr = key.Open(tree, reg_value_name.c_str(), KEY_QUERY_VALUE); + if (FAILED(hr)) + return hr; + + DCHECK(storage_ == POLICYSTORAGE_SINGLEVALUE); + DWORD full_value; + hr = key.ReadValueDW(regvalue_, &full_value); + if (FAILED(hr)) + return hr; + + *value = (full_value != 0); + *found = true; + + return hr; +} + +bool IsBoolOptionSet(const Setting<bool>& setting) { + bool found = false; + bool set = false; + HRESULT hr = setting.GetSetting(&set, &found); + if (FAILED(hr) || !found) { + set = false; + } + return set; +} + +}; // namespace group_policy + diff --git a/chrome/browser/group_policy.h b/chrome/browser/group_policy.h new file mode 100644 index 0000000..2c06d0a --- /dev/null +++ b/chrome/browser/group_policy.h @@ -0,0 +1,157 @@ +// Copyright (c) 2009 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. +// +// A central repository for definitions relating to Group Policy. + +#ifndef CHROME_BROWSER_GROUP_POLICY_H_ +#define CHROME_BROWSER_GROUP_POLICY_H_ + +#include <windows.h> +#include "base/basictypes.h" +#include "base/logging.h" +#include "base/values.h" +#include "build/build_config.h" + +// Each policy: +// - has a name; this is used to refer to the policy for testing in code. +// - has a type; the type of a policy decides what sort of value a policy +// lookup returns as well as how the policy handles it when it is +// defined both in user and machine policy. +// Policy types include: +// # Flag; a boolean flag, if either machine or user instance +// of the flag is nonzero, then the flag is set. Otherwise, +// whether both or either are nonexistent or zero, the flag +// is unset. +// # Number; a DWORD number. +// # String; a character string. +// # String List; an unordered list of strings. +// - belongs to class; Each policy is either a machine or a user policy +// or both. +// Policies that belong to the user class are stored under HKCU, while +// those of machine class are stored under HKLM. Policies of class both +// belong in both places. For such policies, the meaning of +// conflicting settings is determined by the type of the policy. +// - has a registry key; This is a path from the toplevel key or keys that +// the policy class implies. +// - has a value name; Depending on the type of the policy, this is the name +// of the value or the subkey that contains the policy flag or value. +// - has a display name; this is the name displayed to the administrator in +// the group policy editor. +// - has a help string; this is the help string displayed to the administrator +// in the group policy editor. + +namespace group_policy { + +// Get the root registry location of group policy settings. +bool GetPolicySettingsRootKey(std::wstring* policy_key); + +// Check if the machine has any group policy settings. +bool HasGroupPolicySettings(); + +// True if the machine has group policy settings in HKCU. +bool HasHkcuSettings(); + +// True if the machine has group policy settings in HKLM. +bool HasHklmSettings(); + +// This specifies how to combine the user and machine keys for the +// policy setting; some are only applicable to certain data types +// and/or certain storage types. Add more as needed. +enum PolicyCombine { + POLICYCOMBINE_PREFERMACHINE, // HKLM policy takes priority. + POLICYCOMBINE_PREFERUSER, // HKCU policy takes priority. + POLICYCOMBINE_CONCATENATE, // Concatenate both policies. + POLICYCOMBINE_LOGICALOR, // Logical OR of both keys. +}; + +// This specifies how the policy setting is stored in the registry. +// Add more as needed. +enum PolicyStorage { + POLICYSTORAGE_SINGLEVALUE, // Policy is a single registry value. + POLICYSTORAGE_CONCATSUBKEYS, // Policy is set of subkeys of specified key. +}; + +// Class that represents a group policy setting. Encapsulates the lookup +// from both policy sections of the registry, as well as the method for +// combining values in the two policy sections. +class SettingBase { + public: + SettingBase(const wchar_t* regkey, + const wchar_t* regvalue, + PolicyStorage storage, + PolicyCombine combine) : regkey_(regkey), + regvalue_(regvalue), storage_(storage), + combine_(combine) { + // Both parameters are required. Either can be empty (but not both.) + DCHECK(regkey != NULL); + DCHECK(regvalue != NULL); + DCHECK(regkey[0] != L'\0' || regvalue[0] != L'\0'); + + // If storage is POLICYSTORAGE_CONCATSUBKEYS, regvalue should be empty. + DCHECK((storage != POLICYSTORAGE_CONCATSUBKEYS) || + regvalue[0] == L'\0'); + } + + // Returns whether this setting is controlled by group policy; + // indicates whether this value is set somewhere in the registry. + bool IsPolicyControlled() const; + + protected: + // These accessors are protected and then individually exposed in a + // templated base class. That lets the compiler enforce that the code + // using a policy is using the appropriate data type. + HRESULT GetSetting(std::wstring* value, bool* found) const; + HRESULT GetSetting(ListValue* list, bool* found) const; + HRESULT GetSetting(DWORD* value, bool* found) const; + HRESULT GetSetting(bool* value, bool* found) const; + const wchar_t* regkey_; + const wchar_t* regvalue_; + + private: + // Private helper accessors for pulling individual registry keys + HRESULT GetSettingFromTree(HKEY tree, std::wstring* value, bool* found) const; + HRESULT GetSettingFromTree(HKEY tree, ListValue* value, bool* found) const; + HRESULT GetSettingFromTree(HKEY tree, DWORD* value, bool* found) const; + HRESULT GetSettingFromTree(HKEY tree, bool* value, bool* found) const; + + PolicyStorage storage_; + PolicyCombine combine_; +}; + +// Templated class to provide type-safe access to policy setting. +template <typename T> +class Setting : public SettingBase { + public: + Setting(const wchar_t* regkey, + const wchar_t* regvalue, + PolicyStorage storage, + PolicyCombine combine) : + SettingBase(regkey, regvalue, storage, combine) { + } + + HRESULT GetSetting(T* value, bool* found) const { + DCHECK(found); + DCHECK(value); + DCHECK(regvalue_ != NULL && regkey_ != NULL) << + "Setting not initialized - don't call at static init time!"; + + *found = false; + + if (!HasGroupPolicySettings()) + return S_OK; + + return SettingBase::GetSetting(value, found); + } +}; + +// Is option set, default is 'no'. +bool IsBoolOptionSet(const Setting<bool>& setting); + +// Helper function for appending all of one ListValue to another. +void AppendAll(ListValue* target, ListValue* source); + +} // namespace + +#endif // CHROME_BROWSER_GROUP_POLICY_H_ + diff --git a/chrome/browser/group_policy_settings.cc b/chrome/browser/group_policy_settings.cc new file mode 100644 index 0000000..6bb51d1 --- /dev/null +++ b/chrome/browser/group_policy_settings.cc @@ -0,0 +1,22 @@ +// Copyright (c) 2009 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. +// +// List of Group Policy Settings objects. + +#include "build/build_config.h" +#include "chrome/browser/group_policy_settings.h" + +namespace group_policy { + + // TODO(gwilson): The actual group policy settings need to be finalized. + // Change this testing set to the true supported set. + DEFINE_POLICY_STRING(Homepage, L"Preferences\\", L"Homepage"); + DEFINE_POLICY_BOOL(HomepageIsNewTabPage, + L"Preferences\\", + L"HomepageIsNewTabPage"); + DEFINE_POLICY_STRINGLIST(ChromeFrameDomainWhiteList, + L"ChromeFrameDomainWhiteList"); + +}; // namespace + diff --git a/chrome/browser/group_policy_settings.h b/chrome/browser/group_policy_settings.h new file mode 100644 index 0000000..ba5d9d6 --- /dev/null +++ b/chrome/browser/group_policy_settings.h @@ -0,0 +1,51 @@ +// Copyright (c) 2009 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_GROUP_POLICY_SETTINGS_H_ +#define CHROME_BROWSER_GROUP_POLICY_SETTINGS_H_ + +#include "chrome/browser/group_policy.h" + +#define DECLARE_POLICY(name, type) extern const type gp##name +#define DECLARE_POLICY_DWORD(name) DECLARE_POLICY(name, DWORDSetting) +#define DECLARE_POLICY_BOOL(name) DECLARE_POLICY(name, BoolSetting) +#define DECLARE_POLICY_STRING(name) DECLARE_POLICY(name, StringSetting) +#define DECLARE_POLICY_STRINGLIST(name) DECLARE_POLICY(name, StringListSetting) + +#define DEFINE_POLICY(name, type, key, value, storage, combine) \ + const type gp##name(key, value, storage, combine) +#define DEFINE_POLICY_DWORD(name, key, value) \ + DEFINE_POLICY(name, DWORDSetting, key, \ + value, POLICYSTORAGE_SINGLEVALUE, POLICYCOMBINE_PREFERMACHINE) +#define DEFINE_POLICY_BOOL(name, key, value) \ + DEFINE_POLICY(name, BoolSetting, key, value, \ + POLICYSTORAGE_SINGLEVALUE, POLICYCOMBINE_LOGICALOR) +#define DEFINE_POLICY_STRING(name, key, value) \ + DEFINE_POLICY(name, StringSetting, key, value, \ + POLICYSTORAGE_SINGLEVALUE, POLICYCOMBINE_PREFERMACHINE) +#define DEFINE_POLICY_STRINGLIST(name, key) \ + DEFINE_POLICY(name, StringListSetting, key, L"", \ + POLICYSTORAGE_CONCATSUBKEYS, POLICYCOMBINE_CONCATENATE) + +namespace group_policy { + +typedef Setting<DWORD> DWORDSetting; +typedef Setting<bool> BoolSetting; +typedef Setting<std::wstring> StringSetting; +typedef Setting<ListValue> StringListSetting; + +// Extern declarations of all policy settings. Policies should always +// be accessed via the GroupPolicySetting object rather than directly +// through the registry, to ensure the priorities and combination flags +// are respected. +// TODO(gwilson): The actual group policy settings need to be finalized. +// Change this testing set to the true supported set. +DECLARE_POLICY_STRING(Homepage); +DECLARE_POLICY_BOOL(HomepageIsNewTabPage); +DECLARE_POLICY_STRINGLIST(ChromeFrameDomainWhiteList); + +} // namespace + +#endif // CHROME_BROWSER_GROUP_POLICY_SETTINGS_H_ + diff --git a/chrome/browser/group_policy_unittest.cc b/chrome/browser/group_policy_unittest.cc new file mode 100644 index 0000000..01df0f7 --- /dev/null +++ b/chrome/browser/group_policy_unittest.cc @@ -0,0 +1,152 @@ +// Copyright (c) 2009 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 "app/test/data/resource.h" +#include "base/registry.h" +#include "base/string_util.h" +#include "base/scoped_ptr.h" +#include "base/values.h" +#include "chrome/browser/group_policy.h" +#include "chrome/browser/group_policy_settings.h" +#include "chrome/installer/util/browser_distribution.h" +#include "testing/gtest/include/gtest/gtest.h" + +class GroupPolicyTest : public testing::Test { + protected: + virtual void SetUp() { + std::wstring policy_key(L""); + group_policy::GetPolicySettingsRootKey(&policy_key); + policy_key.append(L"\\Preferences\\"); + RegKey hkcu = RegKey(HKEY_CURRENT_USER, policy_key.c_str(), KEY_WRITE); + RegKey hklm = RegKey(HKEY_LOCAL_MACHINE, policy_key.c_str(), KEY_WRITE); + EXPECT_TRUE(hkcu.Valid()); + EXPECT_TRUE(hklm.Valid()); + EXPECT_TRUE(hkcu.WriteValue(L"Homepage", L"www.google.com/hkcu")); + EXPECT_TRUE(hklm.WriteValue(L"Homepage", L"www.google.com/hklm")); + EXPECT_TRUE(hkcu.WriteValue(L"HomepageIsNewTabPage", (DWORD)0)); + EXPECT_TRUE(hklm.WriteValue(L"HomepageIsNewTabPage", (DWORD)1)); + policy_key.clear(); + group_policy::GetPolicySettingsRootKey(&policy_key); + policy_key.append(L"\\ChromeFrameDomainWhiteList\\"); + RegKey hkcu_list = RegKey(HKEY_CURRENT_USER, + policy_key.c_str(), + KEY_WRITE); + RegKey hklm_list = RegKey(HKEY_LOCAL_MACHINE, + policy_key.c_str(), + KEY_WRITE); + EXPECT_TRUE(hkcu_list.Valid()); + EXPECT_TRUE(hklm_list.Valid()); + EXPECT_TRUE(hkcu_list.WriteValue(L"www.google.com/test1", + L"www.google.com/test1")); + EXPECT_TRUE(hkcu_list.WriteValue(L"www.google.com/test2", + L"www.google.com/test2")); + EXPECT_TRUE(hkcu_list.WriteValue(L"www.google.com/test3", + L"www.google.com/test3")); + EXPECT_TRUE(hklm_list.WriteValue(L"www.google.com/testa", + L"www.google.com/testa")); + EXPECT_TRUE(hklm_list.WriteValue(L"www.google.com/testb", + L"www.google.com/testb")); + EXPECT_TRUE(hklm_list.WriteValue(L"www.google.com/testc", + L"www.google.com/testc")); + } + + virtual void TearDown() { + // Delete the appropriate registry keys. + std::wstring policy_key(L""); + group_policy::GetPolicySettingsRootKey(&policy_key); + policy_key.append(L"\\Preferences\\"); + RegKey hkcu = RegKey(HKEY_CURRENT_USER, policy_key.c_str(), KEY_WRITE); + RegKey hklm = RegKey(HKEY_LOCAL_MACHINE, policy_key.c_str(), KEY_WRITE); + EXPECT_TRUE(hkcu.Valid()); + EXPECT_TRUE(hklm.Valid()); + hkcu.DeleteValue(L"Homepage"); + hklm.DeleteValue(L"Homepage"); + hklm.DeleteValue(L"HomepageIsNewTabPage"); + hkcu.DeleteValue(L"HomepageIsNewTabPage"); + policy_key.clear(); + group_policy::GetPolicySettingsRootKey(&policy_key); + RegKey hkcu_list = RegKey(HKEY_CURRENT_USER, + policy_key.c_str(), + KEY_WRITE); + RegKey hklm_list = RegKey(HKEY_LOCAL_MACHINE, + policy_key.c_str(), + KEY_WRITE); + EXPECT_TRUE(hkcu_list.DeleteKey(L"ChromeFrameDomainWhiteList")); + } +}; + +TEST_F(GroupPolicyTest, TestGetPolicyKey) { + std::wstring mystring(L""); + group_policy::GetPolicySettingsRootKey(&mystring); + BrowserDistribution* dist = BrowserDistribution::GetDistribution(); + std::wstring app_name = dist->GetApplicationName(); + std::wstring publisher_name = dist->GetPublisherName(); + EXPECT_NE(-1, mystring.find(app_name)); + EXPECT_NE(-1, mystring.find(publisher_name)); +} + +TEST_F(GroupPolicyTest, TestGetGroupPolicyString) { + std::wstring setting = std::wstring(L""); + bool found = false; + EXPECT_TRUE(group_policy::gpHomepage.IsPolicyControlled()); + HRESULT hr = group_policy::gpHomepage.GetSetting(&setting, &found); + EXPECT_TRUE(found); + EXPECT_TRUE(SUCCEEDED(hr)); + EXPECT_EQ(0, setting.compare(L"www.google.com/hklm")); +} + +TEST_F(GroupPolicyTest, TestGetGroupPolicyBool) { + bool setting = false; + bool found = false; + EXPECT_TRUE(group_policy::gpHomepageIsNewTabPage.IsPolicyControlled()); + HRESULT hr = group_policy::gpHomepageIsNewTabPage.GetSetting(&setting, + &found); + EXPECT_TRUE(found); + EXPECT_TRUE(SUCCEEDED(hr)); + EXPECT_TRUE(setting); +} + +TEST_F(GroupPolicyTest, TestGetStringList) { + scoped_ptr<ListValue> mixed_list(new ListValue()); + bool found = false; + // Because of the way the lists of strings are appended, + // HKCU appears before HKLM, and they appear in reverse order. + std::string test1 = std::string("www.google.com/testc"); + std::string test2 = std::string("www.google.com/testb"); + std::string test3 = std::string("www.google.com/testa"); + std::string test4 = std::string("www.google.com/test3"); + std::string test5 = std::string("www.google.com/test2"); + std::string test6 = std::string("www.google.com/test1"); + HRESULT hr = \ + group_policy::gpChromeFrameDomainWhiteList.GetSetting(mixed_list.get(), + &found); + EXPECT_TRUE(found); + EXPECT_TRUE(SUCCEEDED(hr)); + EXPECT_EQ(6, mixed_list->GetSize()); + std::string string_value; + EXPECT_TRUE(mixed_list->GetString(0, &string_value)); + EXPECT_EQ(0, string_value.compare(test1)); + EXPECT_EQ(string_value, test1); + + EXPECT_TRUE(mixed_list->GetString(1, &string_value)); + EXPECT_EQ(0, string_value.compare(test2)); + EXPECT_EQ(string_value, test2); + + EXPECT_TRUE(mixed_list->GetString(2, &string_value)); + EXPECT_EQ(0, string_value.compare(test3)); + EXPECT_EQ(string_value, test3); + + EXPECT_TRUE(mixed_list->GetString(3, &string_value)); + EXPECT_EQ(0, string_value.compare(test4)); + EXPECT_EQ(string_value, test4); + + EXPECT_TRUE(mixed_list->GetString(4, &string_value)); + EXPECT_EQ(0, string_value.compare(test5)); + EXPECT_EQ(string_value, test5); + + EXPECT_TRUE(mixed_list->GetString(5, &string_value)); + EXPECT_EQ(0, string_value.compare(test6)); + EXPECT_EQ(string_value, test6); +} + diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index b2ab988..b7755f4 100755 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -1510,6 +1510,10 @@ 'browser/google_url_tracker.h', 'browser/google_util.cc', 'browser/google_util.h', + 'browser/group_policy.h', + 'browser/group_policy.cc', + 'browser/group_policy_settings.h', + 'browser/group_policy_settings.cc', 'browser/gtk/about_chrome_dialog.cc', 'browser/gtk/about_chrome_dialog.h', 'browser/gtk/back_forward_button_gtk.cc', @@ -3112,6 +3116,10 @@ 'browser/ime_input.cc', 'browser/importer/ie_importer.cc', 'browser/jumplist.cc', + 'browser/group_policy.h', + 'browser/group_policy.cc', + 'browser/group_policy_settings.h', + 'browser/group_policy_settings.cc', 'browser/sandbox_policy.cc', ], }], @@ -4673,6 +4681,7 @@ 'browser/global_keyboard_shortcuts_mac_unittest.cc', 'browser/google_url_tracker_unittest.cc', 'browser/google_update_settings_posix_unittest.cc', + 'browser/group_policy_unittest.cc', 'browser/gtk/bookmark_bar_gtk_unittest.cc', 'browser/gtk/bookmark_editor_gtk_unittest.cc', 'browser/gtk/gtk_theme_provider_unittest.cc', @@ -4865,6 +4874,7 @@ ], 'sources!': [ 'browser/views/bookmark_context_menu_test.cc', + 'browser/group_policy_unittest.cc', 'browser/gtk/options/cookies_view_unittest.cc', # Compact Language Detection (cld) is not supported in linux yet. '../third_party/cld/bar/toolbar/cld/i18n/encodings/compact_lang_det/compact_lang_det_unittest_small.cc', @@ -4911,6 +4921,7 @@ 'sources!': [ 'browser/views/bookmark_context_menu_test.cc', 'browser/back_forward_menu_model_unittest.cc', + 'browser/group_policy_unittest.cc', 'browser/gtk/go_button_gtk_unittest.cc', 'browser/gtk/tabs/tab_renderer_gtk_unittest.cc', 'browser/tab_contents/navigation_controller_unittest.cc', |