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.
4
5#include <algorithm>
6#include <cstdlib>
7#include <map>
8#include <sstream>
9#include <string>
10#include <vector>
11
12#include "base/basictypes.h"
13#include "base/files/file_path.h"
14#include "base/files/file_util.h"
15#include "base/json/json_reader.h"
16#include "base/logging.h"
17#include "base/memory/scoped_ptr.h"
18#include "base/memory/scoped_vector.h"
19#include "base/memory/weak_ptr.h"
20#include "base/prefs/pref_service.h"
21#include "base/run_loop.h"
22#include "base/stl_util.h"
23#include "base/strings/string_util.h"
24#include "base/strings/utf_string_conversions.h"
25#include "base/values.h"
26#include "chrome/browser/browser_process.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 "components/policy/core/browser/browser_policy_connector.h"
34#include "components/policy/core/common/external_data_fetcher.h"
35#include "components/policy/core/common/external_data_manager.h"
36#include "components/policy/core/common/mock_configuration_policy_provider.h"
37#include "components/policy/core/common/policy_details.h"
38#include "components/policy/core/common/policy_map.h"
39#include "components/policy/core/common/schema.h"
40#include "content/public/browser/web_contents.h"
41#include "content/public/test/browser_test_utils.h"
42#include "policy/policy_constants.h"
43#include "testing/gmock/include/gmock/gmock.h"
44#include "testing/gtest/include/gtest/gtest.h"
45#include "url/gurl.h"
46
47using testing::Return;
48using testing::_;
49
50namespace policy {
51
52namespace {
53
54const char kMainSettingsPage[] = "chrome://settings-frame";
55
56const char kCrosSettingsPrefix[] = "cros.";
57
58std::string GetPolicyName(const std::string& policy_name_decorated) {
59  const size_t offset = policy_name_decorated.find('.');
60  if (offset != std::string::npos)
61    return policy_name_decorated.substr(0, offset);
62  return policy_name_decorated;
63}
64
65// Contains the details of a single test case verifying that the controlled
66// setting indicators for a pref affected by a policy work correctly. This is
67// part of the data loaded from chrome/test/data/policy/policy_test_cases.json.
68class IndicatorTestCase {
69 public:
70  IndicatorTestCase(const base::DictionaryValue& policy,
71                    const std::string& value,
72                    bool readonly)
73      : policy_(policy.DeepCopy()), value_(value), readonly_(readonly) {}
74  ~IndicatorTestCase() {}
75
76  const base::DictionaryValue& policy() const { return *policy_; }
77
78  const std::string& value() const { return value_; }
79
80  bool readonly() const { return readonly_; }
81
82 private:
83  scoped_ptr<base::DictionaryValue> policy_;
84  std::string value_;
85  bool readonly_;
86
87  DISALLOW_COPY_AND_ASSIGN(IndicatorTestCase);
88};
89
90// Contains the testing details for a single pref affected by a policy. This is
91// part of the data loaded from chrome/test/data/policy/policy_test_cases.json.
92class PrefMapping {
93 public:
94  PrefMapping(const std::string& pref,
95              bool is_local_state,
96              bool check_for_mandatory,
97              bool check_for_recommended,
98              const std::string& indicator_test_setup_js,
99              const std::string& indicator_selector)
100      : pref_(pref),
101        is_local_state_(is_local_state),
102        check_for_mandatory_(check_for_mandatory),
103        check_for_recommended_(check_for_recommended),
104        indicator_test_setup_js_(indicator_test_setup_js),
105        indicator_selector_(indicator_selector) {}
106  ~PrefMapping() {}
107
108  const std::string& pref() const { return pref_; }
109
110  bool is_local_state() const { return is_local_state_; }
111
112  bool check_for_mandatory() const { return check_for_mandatory_; }
113
114  bool check_for_recommended() const { return check_for_recommended_; }
115
116  const std::string& indicator_test_setup_js() const {
117    return indicator_test_setup_js_;
118  }
119
120  const std::string& indicator_selector() const {
121    return indicator_selector_;
122  }
123
124  const ScopedVector<IndicatorTestCase>& indicator_test_cases() const {
125    return indicator_test_cases_;
126  }
127  void AddIndicatorTestCase(IndicatorTestCase* test_case) {
128    indicator_test_cases_.push_back(test_case);
129  }
130
131 private:
132  const std::string pref_;
133  const bool is_local_state_;
134  const bool check_for_mandatory_;
135  const bool check_for_recommended_;
136  const std::string indicator_test_setup_js_;
137  const std::string indicator_selector_;
138  ScopedVector<IndicatorTestCase> indicator_test_cases_;
139
140  DISALLOW_COPY_AND_ASSIGN(PrefMapping);
141};
142
143// Contains the testing details for a single policy. This is part of the data
144// loaded from chrome/test/data/policy/policy_test_cases.json.
145class PolicyTestCase {
146 public:
147  PolicyTestCase(const std::string& name,
148                 bool is_official_only,
149                 bool can_be_recommended,
150                 const std::string& indicator_selector)
151      : name_(name),
152        is_official_only_(is_official_only),
153        can_be_recommended_(can_be_recommended),
154        indicator_selector_(indicator_selector) {}
155  ~PolicyTestCase() {}
156
157  const std::string& name() const { return name_; }
158
159  bool is_official_only() const { return is_official_only_; }
160
161  bool can_be_recommended() const { return can_be_recommended_; }
162
163  bool IsOsSupported() const {
164#if defined(OS_WIN)
165    const std::string os("win");
166#elif defined(OS_MACOSX)
167    const std::string os("mac");
168#elif defined(OS_CHROMEOS)
169    const std::string os("chromeos");
170#elif defined(OS_LINUX)
171    const std::string os("linux");
172#else
173#error "Unknown platform"
174#endif
175    return std::find(supported_os_.begin(), supported_os_.end(), os) !=
176        supported_os_.end();
177  }
178  void AddSupportedOs(const std::string& os) { supported_os_.push_back(os); }
179
180  bool IsSupported() const {
181#if !defined(GOOGLE_CHROME_BUILD)
182    if (is_official_only())
183      return false;
184#endif
185    return IsOsSupported();
186  }
187
188  const base::DictionaryValue& test_policy() const { return test_policy_; }
189  void SetTestPolicy(const base::DictionaryValue& policy) {
190    test_policy_.Clear();
191    test_policy_.MergeDictionary(&policy);
192  }
193
194  const ScopedVector<PrefMapping>& pref_mappings() const {
195    return pref_mappings_;
196  }
197  void AddPrefMapping(PrefMapping* pref_mapping) {
198    pref_mappings_.push_back(pref_mapping);
199  }
200
201  const std::string& indicator_selector() const { return indicator_selector_; }
202
203 private:
204  std::string name_;
205  bool is_official_only_;
206  bool can_be_recommended_;
207  std::vector<std::string> supported_os_;
208  base::DictionaryValue test_policy_;
209  ScopedVector<PrefMapping> pref_mappings_;
210  std::string indicator_selector_;
211
212  DISALLOW_COPY_AND_ASSIGN(PolicyTestCase);
213};
214
215// Parses all policy test cases and makes then available in a map.
216class PolicyTestCases {
217 public:
218  typedef std::vector<PolicyTestCase*> PolicyTestCaseVector;
219  typedef std::map<std::string, PolicyTestCaseVector> PolicyTestCaseMap;
220  typedef PolicyTestCaseMap::const_iterator iterator;
221
222  PolicyTestCases() {
223    base::FilePath path = ui_test_utils::GetTestFilePath(
224        base::FilePath(FILE_PATH_LITERAL("policy")),
225        base::FilePath(FILE_PATH_LITERAL("policy_test_cases.json")));
226    std::string json;
227    if (!base::ReadFileToString(path, &json)) {
228      ADD_FAILURE();
229      return;
230    }
231    int error_code = -1;
232    std::string error_string;
233    base::DictionaryValue* dict = NULL;
234    scoped_ptr<base::Value> value(base::JSONReader::ReadAndReturnError(
235        json, base::JSON_PARSE_RFC, &error_code, &error_string));
236    if (!value.get() || !value->GetAsDictionary(&dict)) {
237      ADD_FAILURE() << "Error parsing policy_test_cases.json: " << error_string;
238      return;
239    }
240    Schema chrome_schema = Schema::Wrap(GetChromeSchemaData());
241    if (!chrome_schema.valid()) {
242      ADD_FAILURE();
243      return;
244    }
245    for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd();
246         it.Advance()) {
247      const std::string policy_name = GetPolicyName(it.key());
248      if (!chrome_schema.GetKnownProperty(policy_name).valid())
249        continue;
250      PolicyTestCase* policy_test_case = GetPolicyTestCase(dict, it.key());
251      if (policy_test_case)
252        policy_test_cases_[policy_name].push_back(policy_test_case);
253    }
254  }
255
256  ~PolicyTestCases() {
257    for (iterator policy = policy_test_cases_.begin();
258         policy != policy_test_cases_.end();
259         ++policy) {
260      for (PolicyTestCaseVector::const_iterator test_case =
261               policy->second.begin();
262           test_case != policy->second.end();
263           ++test_case) {
264        delete *test_case;
265      }
266    }
267  }
268
269  const PolicyTestCaseVector* Get(const std::string& name) const {
270    const iterator it = policy_test_cases_.find(name);
271    return it == end() ? NULL : &it->second;
272  }
273
274  const PolicyTestCaseMap& map() const { return policy_test_cases_; }
275  iterator begin() const { return policy_test_cases_.begin(); }
276  iterator end() const { return policy_test_cases_.end(); }
277
278 private:
279  PolicyTestCase* GetPolicyTestCase(const base::DictionaryValue* tests,
280                                    const std::string& name) {
281    const base::DictionaryValue* policy_test_dict = NULL;
282    if (!tests->GetDictionaryWithoutPathExpansion(name, &policy_test_dict))
283      return NULL;
284    bool is_official_only = false;
285    policy_test_dict->GetBoolean("official_only", &is_official_only);
286    bool can_be_recommended = false;
287    policy_test_dict->GetBoolean("can_be_recommended", &can_be_recommended);
288    std::string indicator_selector;
289    policy_test_dict->GetString("indicator_selector", &indicator_selector);
290    PolicyTestCase* policy_test_case = new PolicyTestCase(name,
291                                                          is_official_only,
292                                                          can_be_recommended,
293                                                          indicator_selector);
294    const base::ListValue* os_list = NULL;
295    if (policy_test_dict->GetList("os", &os_list)) {
296      for (size_t i = 0; i < os_list->GetSize(); ++i) {
297        std::string os;
298        if (os_list->GetString(i, &os))
299          policy_test_case->AddSupportedOs(os);
300      }
301    }
302    const base::DictionaryValue* policy = NULL;
303    if (policy_test_dict->GetDictionary("test_policy", &policy))
304      policy_test_case->SetTestPolicy(*policy);
305    const base::ListValue* pref_mappings = NULL;
306    if (policy_test_dict->GetList("pref_mappings", &pref_mappings)) {
307      for (size_t i = 0; i < pref_mappings->GetSize(); ++i) {
308        const base::DictionaryValue* pref_mapping_dict = NULL;
309        std::string pref;
310        if (!pref_mappings->GetDictionary(i, &pref_mapping_dict) ||
311            !pref_mapping_dict->GetString("pref", &pref)) {
312          ADD_FAILURE() << "Malformed pref_mappings entry in "
313                        << "policy_test_cases.json.";
314          continue;
315        }
316        bool is_local_state = false;
317        pref_mapping_dict->GetBoolean("local_state", &is_local_state);
318        bool check_for_mandatory = true;
319        pref_mapping_dict->GetBoolean("check_for_mandatory",
320                                      &check_for_mandatory);
321        bool check_for_recommended = true;
322        pref_mapping_dict->GetBoolean("check_for_recommended",
323                                      &check_for_recommended);
324        std::string indicator_test_setup_js;
325        pref_mapping_dict->GetString("indicator_test_setup_js",
326                                     &indicator_test_setup_js);
327        std::string indicator_selector;
328        pref_mapping_dict->GetString("indicator_selector", &indicator_selector);
329        PrefMapping* pref_mapping = new PrefMapping(pref,
330                                                    is_local_state,
331                                                    check_for_mandatory,
332                                                    check_for_recommended,
333                                                    indicator_test_setup_js,
334                                                    indicator_selector);
335        const base::ListValue* indicator_tests = NULL;
336        if (pref_mapping_dict->GetList("indicator_tests", &indicator_tests)) {
337          for (size_t i = 0; i < indicator_tests->GetSize(); ++i) {
338            const base::DictionaryValue* indicator_test_dict = NULL;
339            const base::DictionaryValue* policy = NULL;
340            if (!indicator_tests->GetDictionary(i, &indicator_test_dict) ||
341                !indicator_test_dict->GetDictionary("policy", &policy)) {
342              ADD_FAILURE() << "Malformed indicator_tests entry in "
343                            << "policy_test_cases.json.";
344              continue;
345            }
346            std::string value;
347            indicator_test_dict->GetString("value", &value);
348            bool readonly = false;
349            indicator_test_dict->GetBoolean("readonly", &readonly);
350            pref_mapping->AddIndicatorTestCase(
351                new IndicatorTestCase(*policy, value, readonly));
352          }
353        }
354        policy_test_case->AddPrefMapping(pref_mapping);
355      }
356    }
357    return policy_test_case;
358  }
359
360  PolicyTestCaseMap policy_test_cases_;
361
362  DISALLOW_COPY_AND_ASSIGN(PolicyTestCases);
363};
364
365// Returns a pseudo-random integer distributed in [0, range).
366int GetRandomNumber(int range) {
367  return rand() % range;
368}
369
370// Splits all known policies into subsets of the given |chunk_size|. The
371// policies are shuffled so that there is no correlation between their initial
372// alphabetic ordering and the assignment to chunks. This ensures that the
373// expected number of policies with long-running test cases is equal for each
374// subset. The shuffle algorithm uses a fixed seed, ensuring that no randomness
375// is introduced into the testing process.
376std::vector<std::vector<std::string> > SplitPoliciesIntoChunks(int chunk_size) {
377  Schema chrome_schema = Schema::Wrap(GetChromeSchemaData());
378  if (!chrome_schema.valid())
379    ADD_FAILURE();
380
381  std::vector<std::string> policies;
382  for (Schema::Iterator it = chrome_schema.GetPropertiesIterator();
383       !it.IsAtEnd(); it.Advance()) {
384    policies.push_back(it.key());
385  }
386
387  // Use a fixed random seed to obtain a reproducible shuffle.
388  srand(1);
389  std::random_shuffle(policies.begin(), policies.end(), GetRandomNumber);
390
391  std::vector<std::vector<std::string> > chunks;
392  std::vector<std::string>::const_iterator it = policies.begin();
393  const std::vector<std::string>::const_iterator end = policies.end();
394  for ( ; end - it >= chunk_size; it += chunk_size)
395    chunks.push_back(std::vector<std::string>(it, it + chunk_size));
396  if (it != end)
397    chunks.push_back(std::vector<std::string>(it, end));
398  return chunks;
399}
400
401void VerifyControlledSettingIndicators(Browser* browser,
402                                       const std::string& selector,
403                                       const std::string& value,
404                                       const std::string& controlled_by,
405                                       bool readonly) {
406  std::stringstream javascript;
407  javascript << "var nodes = document.querySelectorAll("
408             << "    'span.controlled-setting-indicator"
409             <<          selector.c_str() << "');"
410             << "var indicators = [];"
411             << "for (var i = 0; i < nodes.length; i++) {"
412             << "  var node = nodes[i];"
413             << "  var indicator = {};"
414             << "  indicator.value = node.value || '';"
415             << "  indicator.controlledBy = node.controlledBy || '';"
416             << "  indicator.readOnly = node.readOnly || false;"
417             << "  indicator.visible ="
418             << "      window.getComputedStyle(node).display != 'none';"
419             << "  indicators.push(indicator)"
420             << "}"
421             << "domAutomationController.send(JSON.stringify(indicators));";
422  content::WebContents* contents =
423      browser->tab_strip_model()->GetActiveWebContents();
424  std::string json;
425  // Retrieve the state of all controlled setting indicators matching the
426  // |selector| as JSON.
427  ASSERT_TRUE(content::ExecuteScriptAndExtractString(contents, javascript.str(),
428                                                     &json));
429  scoped_ptr<base::Value> value_ptr(base::JSONReader::Read(json));
430  const base::ListValue* indicators = NULL;
431  ASSERT_TRUE(value_ptr.get());
432  ASSERT_TRUE(value_ptr->GetAsList(&indicators));
433  // Verify that controlled setting indicators representing |value| are visible
434  // and have the correct state while those not representing |value| are
435  // invisible.
436  if (!controlled_by.empty()) {
437    EXPECT_GT(indicators->GetSize(), 0u)
438        << "Expected to find at least one controlled setting indicator.";
439  }
440  bool have_visible_indicators = false;
441  for (base::ListValue::const_iterator indicator = indicators->begin();
442       indicator != indicators->end(); ++indicator) {
443    const base::DictionaryValue* properties = NULL;
444    ASSERT_TRUE((*indicator)->GetAsDictionary(&properties));
445    std::string indicator_value;
446    std::string indicator_controlled_by;
447    bool indicator_readonly;
448    bool indicator_visible;
449    EXPECT_TRUE(properties->GetString("value", &indicator_value));
450    EXPECT_TRUE(properties->GetString("controlledBy",
451                                      &indicator_controlled_by));
452    EXPECT_TRUE(properties->GetBoolean("readOnly", &indicator_readonly));
453    EXPECT_TRUE(properties->GetBoolean("visible", &indicator_visible));
454    if (!controlled_by.empty() && (indicator_value == value)) {
455      EXPECT_EQ(controlled_by, indicator_controlled_by);
456      EXPECT_EQ(readonly, indicator_readonly);
457      EXPECT_TRUE(indicator_visible);
458      have_visible_indicators = true;
459    } else {
460      EXPECT_FALSE(indicator_visible);
461    }
462  }
463  if (!controlled_by.empty()) {
464    EXPECT_TRUE(have_visible_indicators)
465        << "Expected to find at least one visible controlled setting "
466        << "indicator.";
467  }
468}
469
470}  // namespace
471
472typedef InProcessBrowserTest PolicyPrefsTestCoverageTest;
473
474IN_PROC_BROWSER_TEST_F(PolicyPrefsTestCoverageTest, AllPoliciesHaveATestCase) {
475  // Verifies that all known policies have a test case in the JSON file.
476  // This test fails when a policy is added to
477  // components/policy/resources/policy_templates.json but a test case is not
478  // added to chrome/test/data/policy/policy_test_cases.json.
479  Schema chrome_schema = Schema::Wrap(GetChromeSchemaData());
480  ASSERT_TRUE(chrome_schema.valid());
481
482  PolicyTestCases policy_test_cases;
483  for (Schema::Iterator it = chrome_schema.GetPropertiesIterator();
484       !it.IsAtEnd(); it.Advance()) {
485    EXPECT_TRUE(ContainsKey(policy_test_cases.map(), it.key()))
486        << "Missing policy test case for: " << it.key();
487  }
488}
489
490// Base class for tests that change policy.
491class PolicyPrefsTest : public InProcessBrowserTest {
492 protected:
493  virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
494    EXPECT_CALL(provider_, IsInitializationComplete(_))
495        .WillRepeatedly(Return(true));
496    BrowserPolicyConnector::SetPolicyProviderForTesting(&provider_);
497  }
498
499  virtual void SetUpOnMainThread() OVERRIDE {
500    ui_test_utils::WaitForTemplateURLServiceToLoad(
501        TemplateURLServiceFactory::GetForProfile(browser()->profile()));
502  }
503
504  virtual void TearDownOnMainThread() OVERRIDE {
505    ClearProviderPolicy();
506  }
507
508  void ClearProviderPolicy() {
509    provider_.UpdateChromePolicy(PolicyMap());
510    base::RunLoop().RunUntilIdle();
511  }
512
513  void SetProviderPolicy(const base::DictionaryValue& policies,
514                         PolicyLevel level) {
515    PolicyMap policy_map;
516    for (base::DictionaryValue::Iterator it(policies);
517         !it.IsAtEnd(); it.Advance()) {
518      const PolicyDetails* policy_details = GetChromePolicyDetails(it.key());
519      ASSERT_TRUE(policy_details);
520      policy_map.Set(
521          it.key(),
522          level,
523          POLICY_SCOPE_USER,
524          it.value().DeepCopy(),
525          policy_details->max_external_data_size ?
526              new ExternalDataFetcher(base::WeakPtr<ExternalDataManager>(),
527                                      it.key()) :
528              NULL);
529    }
530    provider_.UpdateChromePolicy(policy_map);
531    base::RunLoop().RunUntilIdle();
532  }
533
534  MockConfigurationPolicyProvider provider_;
535};
536
537// Verifies that policies make their corresponding preferences become managed,
538// and that the user can't override that setting.
539IN_PROC_BROWSER_TEST_F(PolicyPrefsTest, PolicyToPrefsMapping) {
540  PrefService* local_state = g_browser_process->local_state();
541  PrefService* user_prefs = browser()->profile()->GetPrefs();
542
543  const PolicyTestCases test_cases;
544  for (PolicyTestCases::iterator policy = test_cases.begin();
545       policy != test_cases.end();
546       ++policy) {
547    for (PolicyTestCases::PolicyTestCaseVector::const_iterator test_case =
548             policy->second.begin();
549         test_case != policy->second.end();
550         ++test_case) {
551      const ScopedVector<PrefMapping>& pref_mappings =
552          (*test_case)->pref_mappings();
553      if (!(*test_case)->IsSupported() || pref_mappings.empty())
554        continue;
555
556      LOG(INFO) << "Testing policy: " << policy->first;
557
558      for (ScopedVector<PrefMapping>::const_iterator pref_mapping =
559               pref_mappings.begin();
560           pref_mapping != pref_mappings.end();
561           ++pref_mapping) {
562        // Skip Chrome OS preferences that use a different backend and cannot be
563        // retrieved through the prefs mechanism.
564        if (StartsWithASCII((*pref_mapping)->pref(), kCrosSettingsPrefix, true))
565          continue;
566
567        // Skip preferences that should not be checked when the policy is set to
568        // a mandatory value.
569        if (!(*pref_mapping)->check_for_mandatory())
570          continue;
571
572        PrefService* prefs =
573            (*pref_mapping)->is_local_state() ? local_state : user_prefs;
574        // The preference must have been registered.
575        const PrefService::Preference* pref =
576            prefs->FindPreference((*pref_mapping)->pref().c_str());
577        ASSERT_TRUE(pref);
578
579        // Verify that setting the policy overrides the pref.
580        ClearProviderPolicy();
581        prefs->ClearPref((*pref_mapping)->pref().c_str());
582        EXPECT_TRUE(pref->IsDefaultValue());
583        EXPECT_TRUE(pref->IsUserModifiable());
584        EXPECT_FALSE(pref->IsUserControlled());
585        EXPECT_FALSE(pref->IsManaged());
586
587        SetProviderPolicy((*test_case)->test_policy(), POLICY_LEVEL_MANDATORY);
588        EXPECT_FALSE(pref->IsDefaultValue());
589        EXPECT_FALSE(pref->IsUserModifiable());
590        EXPECT_FALSE(pref->IsUserControlled());
591        EXPECT_TRUE(pref->IsManaged());
592      }
593    }
594  }
595}
596
597class PolicyPrefIndicatorTest
598    : public PolicyPrefsTest,
599      public testing::WithParamInterface<std::vector<std::string> > {
600};
601
602// Verifies that controlled setting indicators correctly show whether a pref's
603// value is recommended or enforced by a corresponding policy.
604IN_PROC_BROWSER_TEST_P(PolicyPrefIndicatorTest, CheckPolicyIndicators) {
605  const PolicyTestCases test_cases;
606  PrefService* local_state = g_browser_process->local_state();
607  PrefService* user_prefs = browser()->profile()->GetPrefs();
608
609  ui_test_utils::NavigateToURL(browser(), GURL(kMainSettingsPage));
610
611  for (std::vector<std::string>::const_iterator policy = GetParam().begin();
612       policy != GetParam().end();
613       ++policy) {
614    const std::vector<PolicyTestCase*>* policy_test_cases =
615        test_cases.Get(*policy);
616    ASSERT_TRUE(policy_test_cases) << "PolicyTestCase not found for "
617                                   << *policy;
618    for (std::vector<PolicyTestCase*>::const_iterator test_case =
619             policy_test_cases->begin();
620         test_case != policy_test_cases->end();
621         ++test_case) {
622      PolicyTestCase* policy_test_case = *test_case;
623      if (!policy_test_case->IsSupported())
624        continue;
625      const ScopedVector<PrefMapping>& pref_mappings =
626          policy_test_case->pref_mappings();
627      if (policy_test_case->indicator_selector().empty()) {
628        bool has_pref_indicator_tests = false;
629        for (ScopedVector<PrefMapping>::const_iterator pref_mapping =
630                 pref_mappings.begin();
631             pref_mapping != pref_mappings.end();
632             ++pref_mapping) {
633          if (!(*pref_mapping)->indicator_test_cases().empty()) {
634            has_pref_indicator_tests = true;
635            break;
636          }
637        }
638        if (!has_pref_indicator_tests)
639          continue;
640      }
641
642      LOG(INFO) << "Testing policy: " << *policy;
643
644      if (!policy_test_case->indicator_selector().empty()) {
645        // Check that no controlled setting indicator is visible when no value
646        // is set by policy.
647        ClearProviderPolicy();
648        VerifyControlledSettingIndicators(
649            browser(),
650            policy_test_case->indicator_selector(),
651            std::string(),
652            std::string(),
653            false);
654        // Check that the appropriate controlled setting indicator is shown when
655        // a value is enforced by policy.
656        SetProviderPolicy(policy_test_case->test_policy(),
657                          POLICY_LEVEL_MANDATORY);
658        VerifyControlledSettingIndicators(
659            browser(),
660            policy_test_case->indicator_selector(),
661            std::string(),
662            "policy",
663            false);
664      }
665
666      for (ScopedVector<PrefMapping>::const_iterator
667               pref_mapping = pref_mappings.begin();
668           pref_mapping != pref_mappings.end();
669           ++pref_mapping) {
670        const ScopedVector<IndicatorTestCase>& indicator_test_cases =
671            (*pref_mapping)->indicator_test_cases();
672        if (indicator_test_cases.empty())
673          continue;
674
675        if (!(*pref_mapping)->indicator_test_setup_js().empty()) {
676          ASSERT_TRUE(content::ExecuteScript(
677              browser()->tab_strip_model()->GetActiveWebContents(),
678              (*pref_mapping)->indicator_test_setup_js()));
679        }
680
681        std::string indicator_selector = (*pref_mapping)->indicator_selector();
682        if (indicator_selector.empty())
683          indicator_selector = "[pref=\"" + (*pref_mapping)->pref() + "\"]";
684        for (ScopedVector<IndicatorTestCase>::const_iterator
685                 indicator_test_case = indicator_test_cases.begin();
686             indicator_test_case != indicator_test_cases.end();
687             ++indicator_test_case) {
688          // Check that no controlled setting indicator is visible when no value
689          // is set by policy.
690          ClearProviderPolicy();
691          VerifyControlledSettingIndicators(browser(),
692                                            indicator_selector,
693                                            std::string(),
694                                            std::string(),
695                                            false);
696
697          if ((*pref_mapping)->check_for_mandatory()) {
698            // Check that the appropriate controlled setting indicator is shown
699            // when a value is enforced by policy.
700            SetProviderPolicy((*indicator_test_case)->policy(),
701                              POLICY_LEVEL_MANDATORY);
702
703            VerifyControlledSettingIndicators(
704                browser(),
705                indicator_selector,
706                (*indicator_test_case)->value(),
707                "policy",
708                (*indicator_test_case)->readonly());
709          }
710
711          if (!policy_test_case->can_be_recommended() ||
712              !(*pref_mapping)->check_for_recommended()) {
713            continue;
714          }
715
716          PrefService* prefs =
717              (*pref_mapping)->is_local_state() ? local_state : user_prefs;
718          // The preference must have been registered.
719          const PrefService::Preference* pref =
720              prefs->FindPreference((*pref_mapping)->pref().c_str());
721          ASSERT_TRUE(pref);
722
723          // Check that the appropriate controlled setting indicator is shown
724          // when a value is recommended by policy and the user has not
725          // overridden the recommendation.
726          SetProviderPolicy((*indicator_test_case)->policy(),
727                            POLICY_LEVEL_RECOMMENDED);
728          VerifyControlledSettingIndicators(browser(),
729                                            indicator_selector,
730                                            (*indicator_test_case)->value(),
731                                            "recommended",
732                                            (*indicator_test_case)->readonly());
733          // Check that the appropriate controlled setting indicator is shown
734          // when a value is recommended by policy and the user has overridden
735          // the recommendation.
736          prefs->Set((*pref_mapping)->pref().c_str(), *pref->GetValue());
737          VerifyControlledSettingIndicators(browser(),
738                                            indicator_selector,
739                                            (*indicator_test_case)->value(),
740                                            "hasRecommendation",
741                                            (*indicator_test_case)->readonly());
742          prefs->ClearPref((*pref_mapping)->pref().c_str());
743        }
744      }
745    }
746  }
747}
748
749INSTANTIATE_TEST_CASE_P(PolicyPrefIndicatorTestInstance,
750                        PolicyPrefIndicatorTest,
751                        testing::ValuesIn(SplitPoliciesIntoChunks(10)));
752
753}  // namespace policy
754