summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/policy/browser_policy_connector.cc8
-rw-r--r--chrome/browser/policy/configuration_policy_provider_mac.h71
-rw-r--r--chrome/browser/policy/configuration_policy_provider_test.cc15
-rw-r--r--chrome/browser/policy/configuration_policy_provider_test.h23
-rw-r--r--chrome/browser/policy/policy_loader_mac.cc181
-rw-r--r--chrome/browser/policy/policy_loader_mac.h65
-rw-r--r--chrome/browser/policy/policy_loader_mac_unittest.cc321
-rw-r--r--chrome/chrome_browser.gypi4
-rw-r--r--chrome/chrome_tests.gypi2
9 files changed, 610 insertions, 80 deletions
diff --git a/chrome/browser/policy/browser_policy_connector.cc b/chrome/browser/policy/browser_policy_connector.cc
index bc2258d..7ae5eaa 100644
--- a/chrome/browser/policy/browser_policy_connector.cc
+++ b/chrome/browser/policy/browser_policy_connector.cc
@@ -10,6 +10,7 @@
#include "base/file_path.h"
#include "base/path_service.h"
#include "chrome/browser/browser_process.h"
+#include "chrome/browser/policy/async_policy_provider.h"
#include "chrome/browser/policy/cloud_policy_client.h"
#include "chrome/browser/policy/cloud_policy_provider.h"
#include "chrome/browser/policy/cloud_policy_service.h"
@@ -34,7 +35,8 @@
#if defined(OS_WIN)
#include "chrome/browser/policy/configuration_policy_provider_win.h"
#elif defined(OS_MACOSX)
-#include "chrome/browser/policy/configuration_policy_provider_mac.h"
+#include "chrome/browser/policy/policy_loader_mac.h"
+#include "chrome/browser/preferences_mac.h"
#elif defined(OS_POSIX)
#include "chrome/browser/policy/config_dir_policy_provider.h"
#endif
@@ -560,7 +562,9 @@ ConfigurationPolicyProvider*
#if defined(OS_WIN)
return new ConfigurationPolicyProviderWin(policy_list);
#elif defined(OS_MACOSX)
- return new ConfigurationPolicyProviderMac(policy_list);
+ scoped_ptr<AsyncPolicyLoader> loader(
+ new PolicyLoaderMac(policy_list, new MacPreferences()));
+ return new AsyncPolicyProvider(policy_list, loader.Pass());
#elif defined(OS_POSIX)
FilePath config_dir_path;
if (PathService::Get(chrome::DIR_POLICY_FILES, &config_dir_path)) {
diff --git a/chrome/browser/policy/configuration_policy_provider_mac.h b/chrome/browser/policy/configuration_policy_provider_mac.h
deleted file mode 100644
index e2bf37a..0000000
--- a/chrome/browser/policy/configuration_policy_provider_mac.h
+++ /dev/null
@@ -1,71 +0,0 @@
-// 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_CONFIGURATION_POLICY_PROVIDER_MAC_H_
-#define CHROME_BROWSER_POLICY_CONFIGURATION_POLICY_PROVIDER_MAC_H_
-#pragma once
-
-#include <CoreFoundation/CoreFoundation.h>
-
-#include "base/memory/scoped_ptr.h"
-#include "chrome/browser/policy/file_based_policy_provider.h"
-
-class MacPreferences;
-
-namespace base {
-class Value;
-}
-
-namespace policy {
-
-// A provider delegate implementation that reads Mac OS X's managed preferences.
-class MacPreferencesPolicyProviderDelegate
- : public FileBasedPolicyProvider::ProviderDelegate {
- public:
- // Takes ownership of |preferences|.
- MacPreferencesPolicyProviderDelegate(
- MacPreferences* preferences,
- const PolicyDefinitionList* policy_list);
- virtual ~MacPreferencesPolicyProviderDelegate();
-
- // FileBasedPolicyLoader::Delegate implementation.
- virtual scoped_ptr<PolicyBundle> Load() OVERRIDE;
- virtual base::Time GetLastModification() OVERRIDE;
-
- // Converts a CFPropertyListRef to the equivalent base::Value. CFDictionary
- // entries whose key is not a CFStringRef are ignored.
- // The returned value is owned by the caller.
- // Returns NULL if an invalid CFType was found, such as CFDate or CFData.
- static base::Value* CreateValueFromProperty(CFPropertyListRef property);
-
- private:
- // In order to access the application preferences API, the names and values of
- // the policies that are recognized must be known to the loader.
- // Unfortunately, we cannot get the policy list at load time from the
- // provider, because the loader may outlive the provider, so we store our own
- // pointer to the list.
- const PolicyDefinitionList* policy_list_;
-
- scoped_ptr<MacPreferences> preferences_;
-
- DISALLOW_COPY_AND_ASSIGN(MacPreferencesPolicyProviderDelegate);
-};
-
-// An implementation of |ConfigurationPolicyProvider| using the mechanism
-// provided by Mac OS X's managed preferences.
-class ConfigurationPolicyProviderMac : public FileBasedPolicyProvider {
- public:
- explicit ConfigurationPolicyProviderMac(
- const PolicyDefinitionList* policy_list);
-
- // For testing; takes ownership of |preferences|.
- ConfigurationPolicyProviderMac(const PolicyDefinitionList* policy_list,
- MacPreferences* preferences);
-
- DISALLOW_COPY_AND_ASSIGN(ConfigurationPolicyProviderMac);
-};
-
-} // namespace policy
-
-#endif // CHROME_BROWSER_POLICY_CONFIGURATION_POLICY_PROVIDER_MAC_H_
diff --git a/chrome/browser/policy/configuration_policy_provider_test.cc b/chrome/browser/policy/configuration_policy_provider_test.cc
index 64a83c0..c6c9ab1 100644
--- a/chrome/browser/policy/configuration_policy_provider_test.cc
+++ b/chrome/browser/policy/configuration_policy_provider_test.cc
@@ -14,6 +14,7 @@
#include "policy/policy_constants.h"
#include "testing/gmock/include/gmock/gmock.h"
+using content::BrowserThread;
using ::testing::Mock;
using ::testing::_;
@@ -41,6 +42,16 @@ const PolicyDefinitionList kList = {
} // namespace test_policy_definitions
+PolicyTestBase::PolicyTestBase()
+ : ui_thread_(BrowserThread::UI, &loop_),
+ file_thread_(BrowserThread::FILE, &loop_) {}
+
+PolicyTestBase::~PolicyTestBase() {}
+
+void PolicyTestBase::TearDown() {
+ loop_.RunAllPending();
+}
+
PolicyProviderTestHarness::PolicyProviderTestHarness(PolicyLevel level,
PolicyScope scope)
: level_(level), scope_(scope) {}
@@ -60,7 +71,7 @@ ConfigurationPolicyProviderTest::ConfigurationPolicyProviderTest() {}
ConfigurationPolicyProviderTest::~ConfigurationPolicyProviderTest() {}
void ConfigurationPolicyProviderTest::SetUp() {
- AsynchronousPolicyTestBase::SetUp();
+ PolicyTestBase::SetUp();
test_harness_.reset((*GetParam())());
test_harness_->SetUp();
@@ -79,7 +90,7 @@ void ConfigurationPolicyProviderTest::TearDown() {
// Give providers the chance to clean up after themselves on the file thread.
provider_.reset();
- AsynchronousPolicyTestBase::TearDown();
+ PolicyTestBase::TearDown();
}
void ConfigurationPolicyProviderTest::CheckValue(
diff --git a/chrome/browser/policy/configuration_policy_provider_test.h b/chrome/browser/policy/configuration_policy_provider_test.h
index 126ca5e..a24519c 100644
--- a/chrome/browser/policy/configuration_policy_provider_test.h
+++ b/chrome/browser/policy/configuration_policy_provider_test.h
@@ -12,7 +12,7 @@
#include "base/callback_forward.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop.h"
-#include "chrome/browser/policy/asynchronous_policy_test_base.h"
+#include "chrome/browser/policy/policy_constants.h"
#include "content/public/test/test_browser_thread.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -43,6 +43,25 @@ extern const PolicyDefinitionList kList;
} // namespace test_policy_definitions
+class PolicyTestBase : public testing::Test {
+ public:
+ PolicyTestBase();
+ virtual ~PolicyTestBase();
+
+ // testing::Test:
+ virtual void TearDown() OVERRIDE;
+
+ protected:
+ // Create an actual IO loop (needed by FilePathWatcher).
+ MessageLoopForIO loop_;
+
+ private:
+ content::TestBrowserThread ui_thread_;
+ content::TestBrowserThread file_thread_;
+
+ DISALLOW_COPY_AND_ASSIGN(PolicyTestBase);
+};
+
// An interface for creating a test policy provider and creating a policy
// provider instance for testing. Used as the parameter to the abstract
// ConfigurationPolicyProviderTest below.
@@ -92,7 +111,7 @@ typedef PolicyProviderTestHarness* (*CreatePolicyProviderTestHarness)();
// policy provider implementation, passing in a suitable harness factory
// function as the test parameter.
class ConfigurationPolicyProviderTest
- : public AsynchronousPolicyTestBase,
+ : public PolicyTestBase,
public testing::WithParamInterface<CreatePolicyProviderTestHarness> {
protected:
ConfigurationPolicyProviderTest();
diff --git a/chrome/browser/policy/policy_loader_mac.cc b/chrome/browser/policy/policy_loader_mac.cc
new file mode 100644
index 0000000..4e6c2f1
--- /dev/null
+++ b/chrome/browser/policy/policy_loader_mac.cc
@@ -0,0 +1,181 @@
+// 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.
+
+#include "chrome/browser/policy/policy_loader_mac.h"
+
+#include <string>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/file_util.h"
+#include "base/mac/foundation_util.h"
+#include "base/mac/scoped_cftyperef.h"
+#include "base/path_service.h"
+#include "base/platform_file.h"
+#include "base/sys_string_conversions.h"
+#include "base/values.h"
+#include "chrome/browser/policy/policy_bundle.h"
+#include "chrome/browser/policy/policy_map.h"
+#include "chrome/browser/preferences_mac.h"
+#include "chrome/common/chrome_paths.h"
+#include "policy/policy_constants.h"
+
+using base::mac::CFCast;
+using base::mac::ScopedCFTypeRef;
+
+namespace policy {
+
+namespace {
+
+FilePath GetManagedPolicyPath() {
+ // This constructs the path to the plist file in which Mac OS X stores the
+ // managed preference for the application. This is undocumented and therefore
+ // fragile, but if it doesn't work out, AsyncPolicyLoader has a task that
+ // polls periodically in order to reload managed preferences later even if we
+ // missed the change.
+ FilePath path;
+ if (!PathService::Get(chrome::DIR_MANAGED_PREFS, &path))
+ return FilePath();
+
+ CFBundleRef bundle(CFBundleGetMainBundle());
+ if (!bundle)
+ return FilePath();
+
+ CFStringRef bundle_id = CFBundleGetIdentifier(bundle);
+ if (!bundle_id)
+ return FilePath();
+
+ return path.Append(base::SysCFStringRefToUTF8(bundle_id) + ".plist");
+}
+
+// Callback function for CFDictionaryApplyFunction. |key| and |value| are an
+// entry of the CFDictionary that should be converted into an equivalent entry
+// in the DictionaryValue in |context|.
+void DictionaryEntryToValue(const void* key, const void* value, void* context) {
+ if (CFStringRef cf_key = CFCast<CFStringRef>(key)) {
+ base::Value* converted =
+ PolicyLoaderMac::CreateValueFromProperty(
+ static_cast<CFPropertyListRef>(value));
+ if (converted) {
+ const std::string string = base::SysCFStringRefToUTF8(cf_key);
+ static_cast<base::DictionaryValue *>(context)->Set(string, converted);
+ }
+ }
+}
+
+// Callback function for CFArrayApplyFunction. |value| is an entry of the
+// CFArray that should be converted into an equivalent entry in the ListValue
+// in |context|.
+void ArrayEntryToValue(const void* value, void* context) {
+ base::Value* converted =
+ PolicyLoaderMac::CreateValueFromProperty(
+ static_cast<CFPropertyListRef>(value));
+ if (converted)
+ static_cast<base::ListValue *>(context)->Append(converted);
+}
+
+} // namespace
+
+PolicyLoaderMac::PolicyLoaderMac(const PolicyDefinitionList* policy_list,
+ MacPreferences* preferences)
+ : policy_list_(policy_list),
+ preferences_(preferences),
+ managed_policy_path_(GetManagedPolicyPath()) {}
+
+PolicyLoaderMac::~PolicyLoaderMac() {}
+
+void PolicyLoaderMac::InitOnFile() {
+ if (!managed_policy_path_.empty()) {
+ watcher_.Watch(
+ managed_policy_path_,
+ base::Bind(&PolicyLoaderMac::OnFileUpdated, base::Unretained(this)));
+ }
+}
+
+scoped_ptr<PolicyBundle> PolicyLoaderMac::Load() {
+ preferences_->AppSynchronize(kCFPreferencesCurrentApplication);
+ scoped_ptr<PolicyBundle> bundle(new PolicyBundle());
+ PolicyMap& chrome_policy = bundle->Get(POLICY_DOMAIN_CHROME, std::string());
+
+ const PolicyDefinitionList::Entry* current;
+ for (current = policy_list_->begin; current != policy_list_->end; ++current) {
+ base::mac::ScopedCFTypeRef<CFStringRef> name(
+ base::SysUTF8ToCFStringRef(current->name));
+ base::mac::ScopedCFTypeRef<CFPropertyListRef> value(
+ preferences_->CopyAppValue(name, kCFPreferencesCurrentApplication));
+ if (!value.get())
+ continue;
+ bool forced =
+ preferences_->AppValueIsForced(name, kCFPreferencesCurrentApplication);
+ PolicyLevel level = forced ? POLICY_LEVEL_MANDATORY :
+ POLICY_LEVEL_RECOMMENDED;
+ // TODO(joaodasilva): figure the policy scope.
+ base::Value* policy = CreateValueFromProperty(value);
+ if (policy)
+ chrome_policy.Set(current->name, level, POLICY_SCOPE_USER, policy);
+ }
+
+ return bundle.Pass();
+}
+
+base::Time PolicyLoaderMac::LastModificationTime() {
+ base::PlatformFileInfo file_info;
+ if (!file_util::GetFileInfo(managed_policy_path_, &file_info) ||
+ file_info.is_directory) {
+ return base::Time();
+ }
+
+ return file_info.last_modified;
+}
+
+// static
+base::Value* PolicyLoaderMac::CreateValueFromProperty(
+ CFPropertyListRef property) {
+ if (CFCast<CFNullRef>(property))
+ return base::Value::CreateNullValue();
+
+ if (CFBooleanRef boolean = CFCast<CFBooleanRef>(property))
+ return base::Value::CreateBooleanValue(CFBooleanGetValue(boolean));
+
+ if (CFNumberRef number = CFCast<CFNumberRef>(property)) {
+ // CFNumberGetValue() converts values implicitly when the conversion is not
+ // lossy. Check the type before trying to convert.
+ if (CFNumberIsFloatType(number)) {
+ double double_value;
+ if (CFNumberGetValue(number, kCFNumberDoubleType, &double_value))
+ return base::Value::CreateDoubleValue(double_value);
+ } else {
+ int int_value;
+ if (CFNumberGetValue(number, kCFNumberIntType, &int_value))
+ return base::Value::CreateIntegerValue(int_value);
+ }
+ }
+
+ if (CFStringRef string = CFCast<CFStringRef>(property))
+ return base::Value::CreateStringValue(base::SysCFStringRefToUTF8(string));
+
+ if (CFDictionaryRef dict = CFCast<CFDictionaryRef>(property)) {
+ base::DictionaryValue* dict_value = new base::DictionaryValue();
+ CFDictionaryApplyFunction(dict, DictionaryEntryToValue, dict_value);
+ return dict_value;
+ }
+
+ if (CFArrayRef array = CFCast<CFArrayRef>(property)) {
+ base::ListValue* list_value = new base::ListValue();
+ CFArrayApplyFunction(array,
+ CFRangeMake(0, CFArrayGetCount(array)),
+ ArrayEntryToValue,
+ list_value);
+ return list_value;
+ }
+
+ return NULL;
+}
+
+void PolicyLoaderMac::OnFileUpdated(const FilePath& path, bool error) {
+ if (!error)
+ Reload(false);
+}
+
+} // namespace policy
diff --git a/chrome/browser/policy/policy_loader_mac.h b/chrome/browser/policy/policy_loader_mac.h
new file mode 100644
index 0000000..e141ee8
--- /dev/null
+++ b/chrome/browser/policy/policy_loader_mac.h
@@ -0,0 +1,65 @@
+// 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_MAC_H_
+#define CHROME_BROWSER_POLICY_POLICY_LOADER_MAC_H_
+#pragma once
+
+#include <CoreFoundation/CoreFoundation.h>
+
+#include "base/file_path.h"
+#include "base/files/file_path_watcher.h"
+#include "chrome/browser/policy/async_policy_loader.h"
+
+class MacPreferences;
+
+namespace base {
+class Value;
+} // namespace base
+
+namespace policy {
+
+struct PolicyDefinitionList;
+
+// A policy loader that loads policies from the Mac preferences system, and
+// watches the managed preferences files for updates.
+class PolicyLoaderMac : public AsyncPolicyLoader {
+ public:
+ PolicyLoaderMac(const PolicyDefinitionList* policy_list,
+ MacPreferences* preferences);
+ virtual ~PolicyLoaderMac();
+
+ // AsyncPolicyLoader implementation.
+ virtual void InitOnFile() OVERRIDE;
+ virtual scoped_ptr<PolicyBundle> Load() OVERRIDE;
+ virtual base::Time LastModificationTime() OVERRIDE;
+
+ // Converts a CFPropertyListRef to the equivalent base::Value. CFDictionary
+ // entries whose key is not a CFStringRef are ignored.
+ // The returned value is owned by the caller.
+ // Returns NULL if an invalid CFType was found, such as CFDate or CFData.
+ static base::Value* CreateValueFromProperty(CFPropertyListRef property);
+
+ private:
+ // Callback for the FilePathWatcher.
+ void OnFileUpdated(const FilePath& path, bool error);
+
+ // List of recognized policies.
+ const PolicyDefinitionList* policy_list_;
+
+ scoped_ptr<MacPreferences> preferences_;
+
+ // Path to the managed preferences file for the current user, if it could
+ // be found. Updates of this file trigger a policy reload.
+ FilePath managed_policy_path_;
+
+ // Watches for events on the |managed_policy_path_|.
+ base::files::FilePathWatcher watcher_;
+
+ DISALLOW_COPY_AND_ASSIGN(PolicyLoaderMac);
+};
+
+} // namespace policy
+
+#endif // CHROME_BROWSER_POLICY_POLICY_LOADER_MAC_H_
diff --git a/chrome/browser/policy/policy_loader_mac_unittest.cc b/chrome/browser/policy/policy_loader_mac_unittest.cc
new file mode 100644
index 0000000..51a31c8
--- /dev/null
+++ b/chrome/browser/policy/policy_loader_mac_unittest.cc
@@ -0,0 +1,321 @@
+// 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.
+
+#include <CoreFoundation/CoreFoundation.h>
+
+#include "base/basictypes.h"
+#include "base/mac/scoped_cftyperef.h"
+#include "base/sys_string_conversions.h"
+#include "base/values.h"
+#include "chrome/browser/policy/async_policy_provider.h"
+#include "chrome/browser/policy/configuration_policy_provider_test.h"
+#include "chrome/browser/policy/policy_bundle.h"
+#include "chrome/browser/policy/policy_loader_mac.h"
+#include "chrome/browser/policy/policy_map.h"
+#include "chrome/browser/preferences_mock_mac.h"
+#include "policy/policy_constants.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using base::mac::ScopedCFTypeRef;
+
+namespace policy {
+
+namespace {
+
+// Converts a base::Value to the equivalent CFPropertyListRef.
+// The returned value is owned by the caller.
+CFPropertyListRef CreatePropertyFromValue(const base::Value* value) {
+ switch (value->GetType()) {
+ case base::Value::TYPE_NULL:
+ return kCFNull;
+
+ case base::Value::TYPE_BOOLEAN: {
+ bool bool_value;
+ if (value->GetAsBoolean(&bool_value))
+ return bool_value ? kCFBooleanTrue : kCFBooleanFalse;
+ break;
+ }
+
+ case base::Value::TYPE_INTEGER: {
+ int int_value;
+ if (value->GetAsInteger(&int_value)) {
+ return CFNumberCreate(
+ kCFAllocatorDefault, kCFNumberIntType, &int_value);
+ }
+ break;
+ }
+
+ case base::Value::TYPE_DOUBLE: {
+ double double_value;
+ if (value->GetAsDouble(&double_value)) {
+ return CFNumberCreate(
+ kCFAllocatorDefault, kCFNumberDoubleType, &double_value);
+ }
+ break;
+ }
+
+ case base::Value::TYPE_STRING: {
+ std::string string_value;
+ if (value->GetAsString(&string_value))
+ return base::SysUTF8ToCFStringRef(string_value);
+ break;
+ }
+
+ case base::Value::TYPE_DICTIONARY: {
+ const base::DictionaryValue* dict_value;
+ if (value->GetAsDictionary(&dict_value)) {
+ // |dict| is owned by the caller.
+ CFMutableDictionaryRef dict =
+ CFDictionaryCreateMutable(kCFAllocatorDefault,
+ dict_value->size(),
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ for (base::DictionaryValue::Iterator iterator(*dict_value);
+ iterator.HasNext(); iterator.Advance()) {
+ // CFDictionaryAddValue() retains both |key| and |value|, so make sure
+ // the references are balanced.
+ ScopedCFTypeRef<CFStringRef> key(
+ base::SysUTF8ToCFStringRef(iterator.key()));
+ ScopedCFTypeRef<CFPropertyListRef> cf_value(
+ CreatePropertyFromValue(&iterator.value()));
+ if (cf_value)
+ CFDictionaryAddValue(dict, key, cf_value);
+ }
+ return dict;
+ }
+ break;
+ }
+
+ case base::Value::TYPE_LIST: {
+ const base::ListValue* list;
+ if (value->GetAsList(&list)) {
+ CFMutableArrayRef array =
+ CFArrayCreateMutable(NULL, list->GetSize(), &kCFTypeArrayCallBacks);
+ for (base::ListValue::const_iterator it(list->begin());
+ it != list->end(); ++it) {
+ // CFArrayAppendValue() retains |value|, so make sure the reference
+ // created by CreatePropertyFromValue() is released.
+ ScopedCFTypeRef<CFPropertyListRef> cf_value(
+ CreatePropertyFromValue(*it));
+ if (cf_value)
+ CFArrayAppendValue(array, cf_value);
+ }
+ return array;
+ }
+ break;
+ }
+
+ case base::Value::TYPE_BINARY:
+ // This type isn't converted (though it can be represented as CFData)
+ // because there's no equivalent JSON type, and policy values can only
+ // take valid JSON values.
+ break;
+ }
+
+ return NULL;
+}
+
+class TestHarness : public PolicyProviderTestHarness {
+ public:
+ TestHarness();
+ virtual ~TestHarness();
+
+ virtual void SetUp() OVERRIDE;
+
+ virtual ConfigurationPolicyProvider* CreateProvider(
+ const PolicyDefinitionList* policy_definition_list) OVERRIDE;
+
+ virtual void InstallEmptyPolicy() OVERRIDE;
+ virtual void InstallStringPolicy(const std::string& policy_name,
+ const std::string& policy_value) OVERRIDE;
+ virtual void InstallIntegerPolicy(const std::string& policy_name,
+ int policy_value) OVERRIDE;
+ virtual void InstallBooleanPolicy(const std::string& policy_name,
+ bool policy_value) OVERRIDE;
+ virtual void InstallStringListPolicy(
+ const std::string& policy_name,
+ const base::ListValue* policy_value) OVERRIDE;
+ virtual void InstallDictionaryPolicy(
+ const std::string& policy_name,
+ const base::DictionaryValue* policy_value) OVERRIDE;
+
+ static PolicyProviderTestHarness* Create();
+
+ private:
+ MockPreferences* prefs_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestHarness);
+};
+
+TestHarness::TestHarness()
+ : PolicyProviderTestHarness(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER) {}
+
+TestHarness::~TestHarness() {}
+
+void TestHarness::SetUp() {}
+
+ConfigurationPolicyProvider* TestHarness::CreateProvider(
+ const PolicyDefinitionList* policy_definition_list) {
+ prefs_ = new MockPreferences();
+ scoped_ptr<AsyncPolicyLoader> loader(
+ new PolicyLoaderMac(policy_definition_list, prefs_));
+ return new AsyncPolicyProvider(policy_definition_list, loader.Pass());
+}
+
+void TestHarness::InstallEmptyPolicy() {}
+
+void TestHarness::InstallStringPolicy(const std::string& policy_name,
+ const std::string& policy_value) {
+ ScopedCFTypeRef<CFStringRef> name(base::SysUTF8ToCFStringRef(policy_name));
+ ScopedCFTypeRef<CFStringRef> value(base::SysUTF8ToCFStringRef(policy_value));
+ prefs_->AddTestItem(name, value, true);
+}
+
+void TestHarness::InstallIntegerPolicy(const std::string& policy_name,
+ int policy_value) {
+ ScopedCFTypeRef<CFStringRef> name(base::SysUTF8ToCFStringRef(policy_name));
+ ScopedCFTypeRef<CFNumberRef> value(
+ CFNumberCreate(NULL, kCFNumberIntType, &policy_value));
+ prefs_->AddTestItem(name, value, true);
+}
+
+void TestHarness::InstallBooleanPolicy(const std::string& policy_name,
+ bool policy_value) {
+ ScopedCFTypeRef<CFStringRef> name(base::SysUTF8ToCFStringRef(policy_name));
+ prefs_->AddTestItem(name,
+ policy_value ? kCFBooleanTrue : kCFBooleanFalse,
+ true);
+}
+
+void TestHarness::InstallStringListPolicy(const std::string& policy_name,
+ const base::ListValue* policy_value) {
+ ScopedCFTypeRef<CFStringRef> name(base::SysUTF8ToCFStringRef(policy_name));
+ ScopedCFTypeRef<CFPropertyListRef> array(
+ CreatePropertyFromValue(policy_value));
+ ASSERT_TRUE(array);
+ prefs_->AddTestItem(name, array, true);
+}
+
+void TestHarness::InstallDictionaryPolicy(
+ const std::string& policy_name,
+ const base::DictionaryValue* policy_value) {
+ ScopedCFTypeRef<CFStringRef> name(base::SysUTF8ToCFStringRef(policy_name));
+ ScopedCFTypeRef<CFPropertyListRef> dict(
+ CreatePropertyFromValue(policy_value));
+ ASSERT_TRUE(dict);
+ prefs_->AddTestItem(name, dict, true);
+}
+
+// static
+PolicyProviderTestHarness* TestHarness::Create() {
+ return new TestHarness();
+}
+
+} // namespace
+
+// Instantiate abstract test case for basic policy reading tests.
+INSTANTIATE_TEST_CASE_P(
+ PolicyProviderMacTest,
+ ConfigurationPolicyProviderTest,
+ testing::Values(TestHarness::Create));
+
+// Special test cases for some mac preferences details.
+class PolicyLoaderMacTest : public PolicyTestBase {
+ protected:
+ PolicyLoaderMacTest()
+ : prefs_(new MockPreferences()),
+ loader_(new PolicyLoaderMac(&test_policy_definitions::kList, prefs_)),
+ provider_(&test_policy_definitions::kList,
+ scoped_ptr<AsyncPolicyLoader>(loader_)) {}
+ virtual ~PolicyLoaderMacTest() {}
+
+ MockPreferences* prefs_;
+ PolicyLoaderMac* loader_;
+ AsyncPolicyProvider provider_;
+};
+
+TEST_F(PolicyLoaderMacTest, Invalid) {
+ ScopedCFTypeRef<CFStringRef> name(
+ base::SysUTF8ToCFStringRef(test_policy_definitions::kKeyString));
+ const char buffer[] = "binary \xde\xad\xbe\xef data";
+ ScopedCFTypeRef<CFDataRef> invalid_data(
+ CFDataCreate(kCFAllocatorDefault,
+ reinterpret_cast<const UInt8 *>(buffer),
+ arraysize(buffer)));
+ ASSERT_TRUE(invalid_data);
+ prefs_->AddTestItem(name, invalid_data.get(), true);
+ prefs_->AddTestItem(name, invalid_data.get(), false);
+
+ // Make the provider read the updated |prefs_|.
+ provider_.RefreshPolicies();
+ loop_.RunAllPending();
+ const PolicyBundle kEmptyBundle;
+ EXPECT_TRUE(provider_.policies().Equals(kEmptyBundle));
+}
+
+TEST_F(PolicyLoaderMacTest, TestNonForcedValue) {
+ ScopedCFTypeRef<CFStringRef> name(
+ base::SysUTF8ToCFStringRef(test_policy_definitions::kKeyString));
+ ScopedCFTypeRef<CFPropertyListRef> test_value(
+ base::SysUTF8ToCFStringRef("string value"));
+ ASSERT_TRUE(test_value.get());
+ prefs_->AddTestItem(name, test_value.get(), false);
+
+ // Make the provider read the updated |prefs_|.
+ provider_.RefreshPolicies();
+ loop_.RunAllPending();
+ PolicyBundle expected_bundle;
+ expected_bundle.Get(POLICY_DOMAIN_CHROME, "")
+ .Set(test_policy_definitions::kKeyString, POLICY_LEVEL_RECOMMENDED,
+ POLICY_SCOPE_USER, base::Value::CreateStringValue("string value"));
+ EXPECT_TRUE(provider_.policies().Equals(expected_bundle));
+}
+
+TEST_F(PolicyLoaderMacTest, TestConversions) {
+ base::DictionaryValue root;
+
+ // base::Value::TYPE_NULL
+ root.Set("null", base::Value::CreateNullValue());
+
+ // base::Value::TYPE_BOOLEAN
+ root.SetBoolean("false", false);
+ root.SetBoolean("true", true);
+
+ // base::Value::TYPE_INTEGER
+ root.SetInteger("int", 123);
+ root.SetInteger("zero", 0);
+
+ // base::Value::TYPE_DOUBLE
+ root.SetDouble("double", 123.456);
+ root.SetDouble("zerod", 0.0);
+
+ // base::Value::TYPE_STRING
+ root.SetString("string", "the fox jumps over something");
+ root.SetString("empty", "");
+
+ // base::Value::TYPE_LIST
+ base::ListValue list;
+ root.Set("emptyl", list.DeepCopy());
+ for (base::DictionaryValue::Iterator it(root); it.HasNext(); it.Advance())
+ list.Append(it.value().DeepCopy());
+ EXPECT_EQ(root.size(), list.GetSize());
+ list.Append(root.DeepCopy());
+ root.Set("list", list.DeepCopy());
+
+ // base::Value::TYPE_DICTIONARY
+ base::DictionaryValue dict;
+ root.Set("emptyd", dict.DeepCopy());
+ // Very meta.
+ root.Set("dict", root.DeepCopy());
+
+ ScopedCFTypeRef<CFPropertyListRef> property(CreatePropertyFromValue(&root));
+ ASSERT_TRUE(property);
+ scoped_ptr<base::Value> value(
+ PolicyLoaderMac::CreateValueFromProperty(property));
+ ASSERT_TRUE(value.get());
+
+ EXPECT_TRUE(root.Equals(value.get()));
+}
+
+} // namespace policy
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 829f52b..4b59bb5 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -1607,8 +1607,6 @@
'browser/policy/configuration_policy_provider.h',
'browser/policy/configuration_policy_provider_delegate_win.cc',
'browser/policy/configuration_policy_provider_delegate_win.h',
- 'browser/policy/configuration_policy_provider_mac.cc',
- 'browser/policy/configuration_policy_provider_mac.h',
'browser/policy/configuration_policy_provider_win.cc',
'browser/policy/configuration_policy_provider_win.h',
'browser/policy/cros_user_policy_cache.cc',
@@ -1638,6 +1636,8 @@
'browser/policy/policy_constants.h',
'browser/policy/policy_error_map.cc',
'browser/policy/policy_error_map.h',
+ 'browser/policy/policy_loader_mac.cc',
+ 'browser/policy/policy_loader_mac.h',
'browser/policy/policy_notifier.cc',
'browser/policy/policy_notifier.h',
'browser/policy/policy_path_parser.h',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 7a7f795..e5c1a62 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -1363,7 +1363,6 @@
'browser/policy/configuration_policy_handler_chromeos_unittest.cc',
'browser/policy/configuration_policy_handler_unittest.cc',
'browser/policy/configuration_policy_pref_store_unittest.cc',
- 'browser/policy/configuration_policy_provider_mac_unittest.cc',
'browser/policy/configuration_policy_provider_test.cc',
'browser/policy/configuration_policy_provider_test.h',
'browser/policy/configuration_policy_provider_win_unittest.cc',
@@ -1387,6 +1386,7 @@
'browser/policy/mock_device_management_service.h',
'browser/policy/network_configuration_updater_unittest.cc',
'browser/policy/policy_bundle_unittest.cc',
+ 'browser/policy/policy_loader_mac_unittest.cc',
'browser/policy/policy_map_unittest.cc',
'browser/policy/policy_path_parser_unittest.cc',
'browser/policy/policy_service_impl_unittest.cc',