- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / policy / policy_prefs_browsertest.cc
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 <map>
7 #include <sstream>
8 #include <string>
9 #include <vector>
10
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"
38 #include "url/gurl.h"
39
40 using testing::AnyNumber;
41 using testing::Return;
42 using testing::_;
43
44 namespace policy {
45
46 namespace {
47
48 const char kMainSettingsPage[] = "chrome://settings-frame";
49
50 const char kCrosSettingsPrefix[] = "cros.";
51
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 {
56  public:
57   IndicatorTestCase(const base::DictionaryValue& policy,
58                     const std::string& value,
59                     bool readonly)
60       : policy_(policy.DeepCopy()), value_(value), readonly_(readonly) {}
61   ~IndicatorTestCase() {}
62
63   const base::DictionaryValue& policy() const { return *policy_; }
64
65   const std::string& value() const { return value_; }
66
67   bool readonly() const { return readonly_; }
68
69  private:
70   scoped_ptr<base::DictionaryValue> policy_;
71   std::string value_;
72   bool readonly_;
73
74   DISALLOW_COPY_AND_ASSIGN(IndicatorTestCase);
75 };
76
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.
79 class PrefMapping {
80  public:
81   PrefMapping(const std::string& pref,
82               bool is_local_state,
83               const std::string& indicator_test_setup_js,
84               const std::string& indicator_selector)
85       : pref_(pref),
86         is_local_state_(is_local_state),
87         indicator_test_setup_js_(indicator_test_setup_js),
88         indicator_selector_(indicator_selector) {
89   }
90   ~PrefMapping() {}
91
92   const std::string& pref() const { return pref_; }
93
94   bool is_local_state() const { return is_local_state_; }
95
96   const std::string& indicator_test_setup_js() const {
97     return indicator_test_setup_js_;
98   }
99
100   const std::string& indicator_selector() const {
101     return indicator_selector_;
102   }
103
104   const ScopedVector<IndicatorTestCase>& indicator_test_cases() const {
105     return indicator_test_cases_;
106   }
107   void AddIndicatorTestCase(IndicatorTestCase* test_case) {
108     indicator_test_cases_.push_back(test_case);
109   }
110
111  private:
112   std::string pref_;
113   bool is_local_state_;
114   std::string indicator_test_setup_js_;
115   std::string indicator_selector_;
116   ScopedVector<IndicatorTestCase> indicator_test_cases_;
117
118   DISALLOW_COPY_AND_ASSIGN(PrefMapping);
119 };
120
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 {
124  public:
125   PolicyTestCase(const std::string& name,
126                  bool is_official_only,
127                  bool can_be_recommended)
128       : name_(name),
129         is_official_only_(is_official_only),
130         can_be_recommended_(can_be_recommended) {}
131   ~PolicyTestCase() {}
132
133   const std::string& name() const { return name_; }
134
135   bool is_official_only() const { return is_official_only_; }
136
137   bool can_be_recommended() const { return can_be_recommended_; }
138
139   bool IsOsSupported() const {
140 #if defined(OS_WIN)
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");
148 #else
149 #error "Unknown platform"
150 #endif
151     return std::find(supported_os_.begin(), supported_os_.end(), os) !=
152         supported_os_.end();
153   }
154   void AddSupportedOs(const std::string& os) { supported_os_.push_back(os); }
155
156   bool IsSupported() const {
157 #if !defined(OFFICIAL_BUILD)
158     if (is_official_only())
159       return false;
160 #endif
161     return IsOsSupported();
162   }
163
164   const PolicyMap& test_policy() const { return test_policy_; }
165   void SetTestPolicy(const PolicyMap& policy) {
166     test_policy_.CopyFrom(policy);
167   }
168
169   const ScopedVector<PrefMapping>& pref_mappings() const {
170     return pref_mappings_;
171   }
172   void AddPrefMapping(PrefMapping* pref_mapping) {
173     pref_mappings_.push_back(pref_mapping);
174   }
175
176  private:
177   std::string name_;
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_;
183
184   DISALLOW_COPY_AND_ASSIGN(PolicyTestCase);
185 };
186
187 // Parses all policy test cases and makes then available in a map.
188 class PolicyTestCases {
189  public:
190   typedef std::map<std::string, PolicyTestCase*> PolicyTestCaseMap;
191   typedef PolicyTestCaseMap::const_iterator iterator;
192
193   PolicyTestCases() {
194     policy_test_cases_ = new std::map<std::string, PolicyTestCase*>();
195
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")));
199     std::string json;
200     if (!base::ReadFileToString(path, &json)) {
201       ADD_FAILURE();
202       return;
203     }
204     int error_code = -1;
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;
211       return;
212     }
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;
219     }
220   }
221
222   ~PolicyTestCases() {
223     STLDeleteValues(policy_test_cases_);
224     delete policy_test_cases_;
225   }
226
227   const PolicyTestCase* Get(const std::string& name) {
228     iterator it = policy_test_cases_->find(name);
229     return it == end() ? NULL : it->second;
230   }
231
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(); }
235
236  private:
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))
241       return NULL;
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) {
251         std::string os;
252         if (os_list->GetString(i, &os))
253           policy_test_case->AddSupportedOs(os);
254       }
255     }
256     const base::DictionaryValue* policy_dict = NULL;
257     if (policy_test_dict->GetDictionary("test_policy", &policy_dict)) {
258       PolicyMap policy;
259       policy.LoadFrom(policy_dict, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER);
260       policy_test_case->SetTestPolicy(policy);
261     }
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;
266         std::string pref;
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.";
271           continue;
272         }
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.";
291               continue;
292             }
293             std::string value;
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));
299           }
300         }
301         policy_test_case->AddPrefMapping(pref_mapping);
302       }
303     }
304     return policy_test_case;
305   }
306
307   PolicyTestCaseMap* policy_test_cases_;
308
309   DISALLOW_COPY_AND_ASSIGN(PolicyTestCases);
310 };
311
312 void VerifyControlledSettingIndicators(Browser* browser,
313                                        const std::string& selector,
314                                        const std::string& value,
315                                        const std::string& controlled_by,
316                                        bool readonly) {
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)"
331              << "}"
332              << "domAutomationController.send(JSON.stringify(indicators));";
333   content::WebContents* contents =
334       browser->tab_strip_model()->GetActiveWebContents();
335   std::string json;
336   // Retrieve the state of all controlled setting indicators matching the
337   // |selector| as JSON.
338   ASSERT_TRUE(content::ExecuteScriptAndExtractString(contents, javascript.str(),
339                                                      &json));
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
346   // invisible.
347   if (!controlled_by.empty()) {
348     EXPECT_GT(indicators->GetSize(), 0u)
349         << "Expected to find at least one controlled setting indicator.";
350   }
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;
370     } else {
371       EXPECT_FALSE(indicator_visible);
372     }
373   }
374   if (!controlled_by.empty()) {
375     EXPECT_TRUE(have_visible_indicators)
376         << "Expected to find at least one visible controlled setting "
377         << "indicator.";
378   }
379 }
380
381 }  // namespace
382
383 // Base class for tests that change policy and are parameterized with a policy
384 // definition.
385 class PolicyPrefsTest
386     : public InProcessBrowserTest,
387       public testing::WithParamInterface<PolicyDefinitionList::Entry> {
388  protected:
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_);
394   }
395
396   virtual void SetUpOnMainThread() OVERRIDE {
397     ui_test_utils::WaitForTemplateURLServiceToLoad(
398         TemplateURLServiceFactory::GetForProfile(browser()->profile()));
399   }
400
401   void UpdateProviderPolicy(const PolicyMap& policy) {
402     provider_.UpdateChromePolicy(policy);
403     base::RunLoop loop;
404     loop.RunUntilIdle();
405   }
406
407   PolicyTestCases policy_test_cases_;
408   MockConfigurationPolicyProvider provider_;
409 };
410
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;
422   }
423 }
424
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())
432     return;
433   LOG(INFO) << "Testing policy: " << test_case->name();
434
435   for (ScopedVector<PrefMapping>::const_iterator
436            pref_mapping = pref_mappings.begin();
437        pref_mapping != pref_mappings.end();
438        ++pref_mapping) {
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))
442       continue;
443
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());
451     ASSERT_TRUE(pref);
452     prefs->ClearPref((*pref_mapping)->pref().c_str());
453
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());
461
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());
467   }
468 }
469
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 "
476       << GetParam().name;
477   const ScopedVector<PrefMapping>& pref_mappings =
478       policy_test_case->pref_mappings();
479   if (!policy_test_case->IsSupported() || pref_mappings.empty())
480     return;
481   bool has_indicator_tests = false;
482   for (ScopedVector<PrefMapping>::const_iterator
483            pref_mapping = pref_mappings.begin();
484        pref_mapping != pref_mappings.end();
485        ++pref_mapping) {
486     if (!(*pref_mapping)->indicator_test_cases().empty()) {
487       has_indicator_tests = true;
488       break;
489     }
490   }
491   if (!has_indicator_tests)
492     return;
493   LOG(INFO) << "Testing policy: " << policy_test_case->name();
494
495   for (ScopedVector<PrefMapping>::const_iterator
496            pref_mapping = pref_mappings.begin();
497        pref_mapping != pref_mappings.end();
498        ++pref_mapping) {
499     const ScopedVector<IndicatorTestCase>&
500         indicator_test_cases = (*pref_mapping)->indicator_test_cases();
501     if (indicator_test_cases.empty())
502       continue;
503
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()));
509     }
510
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
519       // set by policy.
520       PolicyMap policies;
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(),
531                                         "policy",
532                                         (*indicator_test_case)->readonly());
533
534       if (!policy_test_case->can_be_recommended())
535         continue;
536
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());
544       ASSERT_TRUE(pref);
545
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
548       // recommendation.
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(),
554                                         "recommended",
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
558       // recommendation.
559       prefs->Set((*pref_mapping)->pref().c_str(), *pref->GetValue());
560       VerifyControlledSettingIndicators(browser(), indicator_selector,
561                                         (*indicator_test_case)->value(),
562                                         "hasRecommendation",
563                                         (*indicator_test_case)->readonly());
564       prefs->ClearPref((*pref_mapping)->pref().c_str());
565     }
566   }
567 }
568
569 INSTANTIATE_TEST_CASE_P(
570     PolicyPrefsTestInstance,
571     PolicyPrefsTest,
572     testing::ValuesIn(GetChromePolicyDefinitionList()->begin,
573                       GetChromePolicyDefinitionList()->end));
574
575 }  // namespace policy