summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorgwilson@google.com <gwilson@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-11-25 19:06:28 +0000
committergwilson@google.com <gwilson@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-11-25 19:06:28 +0000
commit64134fec4ed2f78dde84c6533dd2cc962f365ae6 (patch)
tree5a40bcf928d3476b44722950fe1fb7c131013337 /chrome
parentd1279211a457750c5b8717fe6790a838061632a8 (diff)
downloadchromium_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.cc478
-rw-r--r--chrome/browser/group_policy.h157
-rw-r--r--chrome/browser/group_policy_settings.cc22
-rw-r--r--chrome/browser/group_policy_settings.h51
-rw-r--r--chrome/browser/group_policy_unittest.cc152
-rwxr-xr-xchrome/chrome.gyp11
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(&regkey_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(&reg_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(&reg_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_, &reg_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(), &reg_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(&reg_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(&reg_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',