1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
11 #include "base/basictypes.h"
12 #include "base/file_util.h"
13 #include "base/files/file_path.h"
14 #include "base/json/json_reader.h"
15 #include "base/memory/scoped_ptr.h"
16 #include "base/memory/scoped_vector.h"
17 #include "base/prefs/pref_service.h"
18 #include "base/run_loop.h"
19 #include "base/stl_util.h"
20 #include "base/strings/string_util.h"
21 #include "base/strings/utf_string_conversions.h"
22 #include "base/values.h"
23 #include "chrome/browser/browser_process.h"
24 #include "chrome/browser/policy/browser_policy_connector.h"
25 #include "chrome/browser/policy/mock_configuration_policy_provider.h"
26 #include "chrome/browser/policy/policy_map.h"
27 #include "chrome/browser/profiles/profile.h"
28 #include "chrome/browser/search_engines/template_url_service_factory.h"
29 #include "chrome/browser/ui/browser.h"
30 #include "chrome/browser/ui/tabs/tab_strip_model.h"
31 #include "chrome/test/base/in_process_browser_test.h"
32 #include "chrome/test/base/ui_test_utils.h"
33 #include "content/public/browser/web_contents.h"
34 #include "content/public/test/browser_test_utils.h"
35 #include "policy/policy_constants.h"
36 #include "testing/gmock/include/gmock/gmock.h"
37 #include "testing/gtest/include/gtest/gtest.h"
40 using testing::AnyNumber;
41 using testing::Return;
48 const char kMainSettingsPage[] = "chrome://settings-frame";
50 const char kCrosSettingsPrefix[] = "cros.";
52 // Contains the details of a single test case verifying that the controlled
53 // setting indicators for a pref affected by a policy work correctly. This is
54 // part of the data loaded from chrome/test/data/policy/policy_test_cases.json.
55 class IndicatorTestCase {
57 IndicatorTestCase(const base::DictionaryValue& policy,
58 const std::string& value,
60 : policy_(policy.DeepCopy()), value_(value), readonly_(readonly) {}
61 ~IndicatorTestCase() {}
63 const base::DictionaryValue& policy() const { return *policy_; }
65 const std::string& value() const { return value_; }
67 bool readonly() const { return readonly_; }
70 scoped_ptr<base::DictionaryValue> policy_;
74 DISALLOW_COPY_AND_ASSIGN(IndicatorTestCase);
77 // Contains the testing details for a single pref affected by a policy. This is
78 // part of the data loaded from chrome/test/data/policy/policy_test_cases.json.
81 PrefMapping(const std::string& pref,
83 const std::string& indicator_test_setup_js,
84 const std::string& indicator_selector)
86 is_local_state_(is_local_state),
87 indicator_test_setup_js_(indicator_test_setup_js),
88 indicator_selector_(indicator_selector) {
92 const std::string& pref() const { return pref_; }
94 bool is_local_state() const { return is_local_state_; }
96 const std::string& indicator_test_setup_js() const {
97 return indicator_test_setup_js_;
100 const std::string& indicator_selector() const {
101 return indicator_selector_;
104 const ScopedVector<IndicatorTestCase>& indicator_test_cases() const {
105 return indicator_test_cases_;
107 void AddIndicatorTestCase(IndicatorTestCase* test_case) {
108 indicator_test_cases_.push_back(test_case);
113 bool is_local_state_;
114 std::string indicator_test_setup_js_;
115 std::string indicator_selector_;
116 ScopedVector<IndicatorTestCase> indicator_test_cases_;
118 DISALLOW_COPY_AND_ASSIGN(PrefMapping);
121 // Contains the testing details for a single policy. This is part of the data
122 // loaded from chrome/test/data/policy/policy_test_cases.json.
123 class PolicyTestCase {
125 PolicyTestCase(const std::string& name,
126 bool is_official_only,
127 bool can_be_recommended)
129 is_official_only_(is_official_only),
130 can_be_recommended_(can_be_recommended) {}
133 const std::string& name() const { return name_; }
135 bool is_official_only() const { return is_official_only_; }
137 bool can_be_recommended() const { return can_be_recommended_; }
139 bool IsOsSupported() const {
141 const std::string os("win");
142 #elif defined(OS_MACOSX)
143 const std::string os("mac");
144 #elif defined(OS_CHROMEOS)
145 const std::string os("chromeos");
146 #elif defined(OS_LINUX)
147 const std::string os("linux");
149 #error "Unknown platform"
151 return std::find(supported_os_.begin(), supported_os_.end(), os) !=
154 void AddSupportedOs(const std::string& os) { supported_os_.push_back(os); }
156 bool IsSupported() const {
157 #if !defined(OFFICIAL_BUILD)
158 if (is_official_only())
161 return IsOsSupported();
164 const PolicyMap& test_policy() const { return test_policy_; }
165 void SetTestPolicy(const PolicyMap& policy) {
166 test_policy_.CopyFrom(policy);
169 const ScopedVector<PrefMapping>& pref_mappings() const {
170 return pref_mappings_;
172 void AddPrefMapping(PrefMapping* pref_mapping) {
173 pref_mappings_.push_back(pref_mapping);
178 bool is_official_only_;
179 bool can_be_recommended_;
180 std::vector<std::string> supported_os_;
181 PolicyMap test_policy_;
182 ScopedVector<PrefMapping> pref_mappings_;
184 DISALLOW_COPY_AND_ASSIGN(PolicyTestCase);
187 // Parses all policy test cases and makes then available in a map.
188 class PolicyTestCases {
190 typedef std::map<std::string, PolicyTestCase*> PolicyTestCaseMap;
191 typedef PolicyTestCaseMap::const_iterator iterator;
194 policy_test_cases_ = new std::map<std::string, PolicyTestCase*>();
196 base::FilePath path = ui_test_utils::GetTestFilePath(
197 base::FilePath(FILE_PATH_LITERAL("policy")),
198 base::FilePath(FILE_PATH_LITERAL("policy_test_cases.json")));
200 if (!base::ReadFileToString(path, &json)) {
205 std::string error_string;
206 base::DictionaryValue* dict = NULL;
207 scoped_ptr<base::Value> value(base::JSONReader::ReadAndReturnError(
208 json, base::JSON_PARSE_RFC, &error_code, &error_string));
209 if (!value.get() || !value->GetAsDictionary(&dict)) {
210 ADD_FAILURE() << "Error parsing policy_test_cases.json: " << error_string;
213 const PolicyDefinitionList* list = GetChromePolicyDefinitionList();
214 for (const PolicyDefinitionList::Entry* policy = list->begin;
215 policy != list->end; ++policy) {
216 PolicyTestCase* policy_test_case = GetPolicyTestCase(dict, policy->name);
217 if (policy_test_case)
218 (*policy_test_cases_)[policy->name] = policy_test_case;
223 STLDeleteValues(policy_test_cases_);
224 delete policy_test_cases_;
227 const PolicyTestCase* Get(const std::string& name) {
228 iterator it = policy_test_cases_->find(name);
229 return it == end() ? NULL : it->second;
232 const PolicyTestCaseMap& map() const { return *policy_test_cases_; }
233 iterator begin() const { return policy_test_cases_->begin(); }
234 iterator end() const { return policy_test_cases_->end(); }
237 PolicyTestCase* GetPolicyTestCase(const base::DictionaryValue* tests,
238 const std::string& name) {
239 const base::DictionaryValue* policy_test_dict = NULL;
240 if (!tests->GetDictionary(name, &policy_test_dict))
242 bool is_official_only = false;
243 policy_test_dict->GetBoolean("official_only", &is_official_only);
244 bool can_be_recommended = false;
245 policy_test_dict->GetBoolean("can_be_recommended", &can_be_recommended);
246 PolicyTestCase* policy_test_case =
247 new PolicyTestCase(name, is_official_only, can_be_recommended);
248 const base::ListValue* os_list = NULL;
249 if (policy_test_dict->GetList("os", &os_list)) {
250 for (size_t i = 0; i < os_list->GetSize(); ++i) {
252 if (os_list->GetString(i, &os))
253 policy_test_case->AddSupportedOs(os);
256 const base::DictionaryValue* policy_dict = NULL;
257 if (policy_test_dict->GetDictionary("test_policy", &policy_dict)) {
259 policy.LoadFrom(policy_dict, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER);
260 policy_test_case->SetTestPolicy(policy);
262 const base::ListValue* pref_mappings = NULL;
263 if (policy_test_dict->GetList("pref_mappings", &pref_mappings)) {
264 for (size_t i = 0; i < pref_mappings->GetSize(); ++i) {
265 const base::DictionaryValue* pref_mapping_dict = NULL;
267 if (!pref_mappings->GetDictionary(i, &pref_mapping_dict) ||
268 !pref_mapping_dict->GetString("pref", &pref)) {
269 ADD_FAILURE() << "Malformed pref_mappings entry in "
270 << "policy_test_cases.json.";
273 bool is_local_state = false;
274 pref_mapping_dict->GetBoolean("local_state", &is_local_state);
275 std::string indicator_test_setup_js;
276 pref_mapping_dict->GetString("indicator_test_setup_js",
277 &indicator_test_setup_js);
278 std::string indicator_selector;
279 pref_mapping_dict->GetString("indicator_selector", &indicator_selector);
280 PrefMapping* pref_mapping = new PrefMapping(
281 pref, is_local_state, indicator_test_setup_js, indicator_selector);
282 const base::ListValue* indicator_tests = NULL;
283 if (pref_mapping_dict->GetList("indicator_tests", &indicator_tests)) {
284 for (size_t i = 0; i < indicator_tests->GetSize(); ++i) {
285 const base::DictionaryValue* indicator_test_dict = NULL;
286 const base::DictionaryValue* policy = NULL;
287 if (!indicator_tests->GetDictionary(i, &indicator_test_dict) ||
288 !indicator_test_dict->GetDictionary("policy", &policy)) {
289 ADD_FAILURE() << "Malformed indicator_tests entry in "
290 << "policy_test_cases.json.";
294 indicator_test_dict->GetString("value", &value);
295 bool readonly = false;
296 indicator_test_dict->GetBoolean("readonly", &readonly);
297 pref_mapping->AddIndicatorTestCase(
298 new IndicatorTestCase(*policy, value, readonly));
301 policy_test_case->AddPrefMapping(pref_mapping);
304 return policy_test_case;
307 PolicyTestCaseMap* policy_test_cases_;
309 DISALLOW_COPY_AND_ASSIGN(PolicyTestCases);
312 void VerifyControlledSettingIndicators(Browser* browser,
313 const std::string& selector,
314 const std::string& value,
315 const std::string& controlled_by,
317 std::stringstream javascript;
318 javascript << "var nodes = document.querySelectorAll("
319 << " 'span.controlled-setting-indicator"
320 << selector.c_str() << "');"
321 << "var indicators = [];"
322 << "for (var i = 0; i < nodes.length; i++) {"
323 << " var node = nodes[i];"
324 << " var indicator = {};"
325 << " indicator.value = node.value || '';"
326 << " indicator.controlledBy = node.controlledBy || '';"
327 << " indicator.readOnly = node.readOnly || false;"
328 << " indicator.visible ="
329 << " window.getComputedStyle(node).display != 'none';"
330 << " indicators.push(indicator)"
332 << "domAutomationController.send(JSON.stringify(indicators));";
333 content::WebContents* contents =
334 browser->tab_strip_model()->GetActiveWebContents();
336 // Retrieve the state of all controlled setting indicators matching the
337 // |selector| as JSON.
338 ASSERT_TRUE(content::ExecuteScriptAndExtractString(contents, javascript.str(),
340 scoped_ptr<base::Value> value_ptr(base::JSONReader::Read(json));
341 const base::ListValue* indicators = NULL;
342 ASSERT_TRUE(value_ptr.get());
343 ASSERT_TRUE(value_ptr->GetAsList(&indicators));
344 // Verify that controlled setting indicators representing |value| are visible
345 // and have the correct state while those not representing |value| are
347 if (!controlled_by.empty()) {
348 EXPECT_GT(indicators->GetSize(), 0u)
349 << "Expected to find at least one controlled setting indicator.";
351 bool have_visible_indicators = false;
352 for (base::ListValue::const_iterator indicator = indicators->begin();
353 indicator != indicators->end(); ++indicator) {
354 const base::DictionaryValue* properties = NULL;
355 ASSERT_TRUE((*indicator)->GetAsDictionary(&properties));
356 std::string indicator_value;
357 std::string indicator_controlled_by;
358 bool indicator_readonly;
359 bool indicator_visible;
360 EXPECT_TRUE(properties->GetString("value", &indicator_value));
361 EXPECT_TRUE(properties->GetString("controlledBy",
362 &indicator_controlled_by));
363 EXPECT_TRUE(properties->GetBoolean("readOnly", &indicator_readonly));
364 EXPECT_TRUE(properties->GetBoolean("visible", &indicator_visible));
365 if (!controlled_by.empty() && (indicator_value == value)) {
366 EXPECT_EQ(controlled_by, indicator_controlled_by);
367 EXPECT_EQ(readonly, indicator_readonly);
368 EXPECT_TRUE(indicator_visible);
369 have_visible_indicators = true;
371 EXPECT_FALSE(indicator_visible);
374 if (!controlled_by.empty()) {
375 EXPECT_TRUE(have_visible_indicators)
376 << "Expected to find at least one visible controlled setting "
383 // Base class for tests that change policy and are parameterized with a policy
385 class PolicyPrefsTest
386 : public InProcessBrowserTest,
387 public testing::WithParamInterface<PolicyDefinitionList::Entry> {
389 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
390 EXPECT_CALL(provider_, IsInitializationComplete(_))
391 .WillRepeatedly(Return(true));
392 EXPECT_CALL(provider_, RegisterPolicyDomain(_)).Times(AnyNumber());
393 BrowserPolicyConnector::SetPolicyProviderForTesting(&provider_);
396 virtual void SetUpOnMainThread() OVERRIDE {
397 ui_test_utils::WaitForTemplateURLServiceToLoad(
398 TemplateURLServiceFactory::GetForProfile(browser()->profile()));
401 void UpdateProviderPolicy(const PolicyMap& policy) {
402 provider_.UpdateChromePolicy(policy);
407 PolicyTestCases policy_test_cases_;
408 MockConfigurationPolicyProvider provider_;
411 TEST(PolicyPrefsTestCoverageTest, AllPoliciesHaveATestCase) {
412 // Verifies that all known policies have a test case in the JSON file.
413 // This test fails when a policy is added to
414 // chrome/app/policy/policy_templates.json but a test case is not added to
415 // chrome/test/data/policy/policy_test_cases.json.
416 PolicyTestCases policy_test_cases;
417 const PolicyDefinitionList* list = GetChromePolicyDefinitionList();
418 for (const PolicyDefinitionList::Entry* policy = list->begin;
419 policy != list->end; ++policy) {
420 EXPECT_TRUE(ContainsKey(policy_test_cases.map(), policy->name))
421 << "Missing policy test case for: " << policy->name;
425 IN_PROC_BROWSER_TEST_P(PolicyPrefsTest, PolicyToPrefsMapping) {
426 // Verifies that policies make their corresponding preferences become managed,
427 // and that the user can't override that setting.
428 const PolicyTestCase* test_case = policy_test_cases_.Get(GetParam().name);
429 ASSERT_TRUE(test_case) << "PolicyTestCase not found for " << GetParam().name;
430 const ScopedVector<PrefMapping>& pref_mappings = test_case->pref_mappings();
431 if (!test_case->IsSupported() || pref_mappings.empty())
433 LOG(INFO) << "Testing policy: " << test_case->name();
435 for (ScopedVector<PrefMapping>::const_iterator
436 pref_mapping = pref_mappings.begin();
437 pref_mapping != pref_mappings.end();
439 // Skip Chrome OS preferences that use a different backend and cannot be
440 // retrieved through the prefs mechanism.
441 if (StartsWithASCII((*pref_mapping)->pref(), kCrosSettingsPrefix, true))
444 PrefService* local_state = g_browser_process->local_state();
445 PrefService* user_prefs = browser()->profile()->GetPrefs();
446 PrefService* prefs = (*pref_mapping)->is_local_state() ?
447 local_state : user_prefs;
448 // The preference must have been registered.
449 const PrefService::Preference* pref =
450 prefs->FindPreference((*pref_mapping)->pref().c_str());
452 prefs->ClearPref((*pref_mapping)->pref().c_str());
454 // Verify that setting the policy overrides the pref.
455 const PolicyMap kNoPolicies;
456 UpdateProviderPolicy(kNoPolicies);
457 EXPECT_TRUE(pref->IsDefaultValue());
458 EXPECT_TRUE(pref->IsUserModifiable());
459 EXPECT_FALSE(pref->IsUserControlled());
460 EXPECT_FALSE(pref->IsManaged());
462 UpdateProviderPolicy(test_case->test_policy());
463 EXPECT_FALSE(pref->IsDefaultValue());
464 EXPECT_FALSE(pref->IsUserModifiable());
465 EXPECT_FALSE(pref->IsUserControlled());
466 EXPECT_TRUE(pref->IsManaged());
470 IN_PROC_BROWSER_TEST_P(PolicyPrefsTest, CheckPolicyIndicators) {
471 // Verifies that controlled setting indicators correctly show whether a pref's
472 // value is recommended or enforced by a corresponding policy.
473 const PolicyTestCase* policy_test_case =
474 policy_test_cases_.Get(GetParam().name);
475 ASSERT_TRUE(policy_test_case) << "PolicyTestCase not found for "
477 const ScopedVector<PrefMapping>& pref_mappings =
478 policy_test_case->pref_mappings();
479 if (!policy_test_case->IsSupported() || pref_mappings.empty())
481 bool has_indicator_tests = false;
482 for (ScopedVector<PrefMapping>::const_iterator
483 pref_mapping = pref_mappings.begin();
484 pref_mapping != pref_mappings.end();
486 if (!(*pref_mapping)->indicator_test_cases().empty()) {
487 has_indicator_tests = true;
491 if (!has_indicator_tests)
493 LOG(INFO) << "Testing policy: " << policy_test_case->name();
495 for (ScopedVector<PrefMapping>::const_iterator
496 pref_mapping = pref_mappings.begin();
497 pref_mapping != pref_mappings.end();
499 const ScopedVector<IndicatorTestCase>&
500 indicator_test_cases = (*pref_mapping)->indicator_test_cases();
501 if (indicator_test_cases.empty())
504 ui_test_utils::NavigateToURL(browser(), GURL(kMainSettingsPage));
505 if (!(*pref_mapping)->indicator_test_setup_js().empty()) {
506 ASSERT_TRUE(content::ExecuteScript(
507 browser()->tab_strip_model()->GetActiveWebContents(),
508 (*pref_mapping)->indicator_test_setup_js()));
511 std::string indicator_selector = (*pref_mapping)->indicator_selector();
512 if (indicator_selector.empty())
513 indicator_selector = "[pref=\"" + (*pref_mapping)->pref() + "\"]";
514 for (ScopedVector<IndicatorTestCase>::const_iterator
515 indicator_test_case = indicator_test_cases.begin();
516 indicator_test_case != indicator_test_cases.end();
517 ++indicator_test_case) {
518 // Check that no controlled setting indicator is visible when no value is
521 UpdateProviderPolicy(policies);
522 VerifyControlledSettingIndicators(
523 browser(), indicator_selector, std::string(), std::string(), false);
524 // Check that the appropriate controlled setting indicator is shown when a
525 // value is enforced by policy.
526 policies.LoadFrom(&(*indicator_test_case)->policy(),
527 POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER);
528 UpdateProviderPolicy(policies);
529 VerifyControlledSettingIndicators(browser(), indicator_selector,
530 (*indicator_test_case)->value(),
532 (*indicator_test_case)->readonly());
534 if (!policy_test_case->can_be_recommended())
537 PrefService* local_state = g_browser_process->local_state();
538 PrefService* user_prefs = browser()->profile()->GetPrefs();
539 PrefService* prefs = (*pref_mapping)->is_local_state() ?
540 local_state : user_prefs;
541 // The preference must have been registered.
542 const PrefService::Preference* pref =
543 prefs->FindPreference((*pref_mapping)->pref().c_str());
546 // Check that the appropriate controlled setting indicator is shown when a
547 // value is recommended by policy and the user has not overridden the
549 policies.LoadFrom(&(*indicator_test_case)->policy(),
550 POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_USER);
551 UpdateProviderPolicy(policies);
552 VerifyControlledSettingIndicators(browser(), indicator_selector,
553 (*indicator_test_case)->value(),
555 (*indicator_test_case)->readonly());
556 // Check that the appropriate controlled setting indicator is shown when a
557 // value is recommended by policy and the user has overriddent the
559 prefs->Set((*pref_mapping)->pref().c_str(), *pref->GetValue());
560 VerifyControlledSettingIndicators(browser(), indicator_selector,
561 (*indicator_test_case)->value(),
563 (*indicator_test_case)->readonly());
564 prefs->ClearPref((*pref_mapping)->pref().c_str());
569 INSTANTIATE_TEST_CASE_P(
570 PolicyPrefsTestInstance,
572 testing::ValuesIn(GetChromePolicyDefinitionList()->begin,
573 GetChromePolicyDefinitionList()->end));
575 } // namespace policy