Home | History | Annotate | Download | only in options
      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 "chrome/browser/ui/webui/options/preferences_browsertest.h"
      6 
      7 #include <iostream>
      8 #include <sstream>
      9 
     10 #include "base/callback.h"
     11 #include "base/json/json_reader.h"
     12 #include "base/json/json_writer.h"
     13 #include "base/memory/scoped_ptr.h"
     14 #include "base/prefs/pref_service.h"
     15 #include "base/stl_util.h"
     16 #include "base/values.h"
     17 #include "chrome/browser/chrome_notification_types.h"
     18 #include "chrome/browser/policy/browser_policy_connector.h"
     19 #include "chrome/browser/profiles/profile.h"
     20 #include "chrome/browser/ui/browser.h"
     21 #include "chrome/browser/ui/tabs/tab_strip_model.h"
     22 #include "chrome/common/pref_names.h"
     23 #include "chrome/common/url_constants.h"
     24 #include "chrome/test/base/ui_test_utils.h"
     25 #include "components/policy/core/common/external_data_fetcher.h"
     26 #include "components/policy/core/common/policy_map.h"
     27 #include "components/policy/core/common/policy_types.h"
     28 #include "content/public/browser/notification_details.h"
     29 #include "content/public/browser/notification_source.h"
     30 #include "content/public/browser/render_view_host.h"
     31 #include "content/public/browser/web_contents.h"
     32 #include "content/public/test/browser_test_utils.h"
     33 #include "policy/policy_constants.h"
     34 #include "testing/gtest/include/gtest/gtest.h"
     35 #include "url/gurl.h"
     36 
     37 #if defined(OS_CHROMEOS)
     38 #include "base/strings/stringprintf.h"
     39 #include "chrome/browser/browser_process.h"
     40 #include "chrome/browser/chromeos/net/proxy_config_handler.h"
     41 #include "chrome/browser/chromeos/proxy_cros_settings_parser.h"
     42 #include "chrome/browser/chromeos/settings/cros_settings.h"
     43 #include "chrome/browser/prefs/proxy_config_dictionary.h"
     44 #include "chromeos/dbus/dbus_thread_manager.h"
     45 #include "chromeos/dbus/shill_profile_client.h"
     46 #include "chromeos/dbus/shill_service_client.h"
     47 #include "chromeos/network/favorite_state.h"
     48 #include "chromeos/network/network_state.h"
     49 #include "chromeos/network/network_state_handler.h"
     50 #include "chromeos/settings/cros_settings_names.h"
     51 #include "content/public/test/test_utils.h"
     52 #include "third_party/cros_system_api/dbus/service_constants.h"
     53 #endif
     54 
     55 using testing::AllOf;
     56 using testing::Mock;
     57 using testing::Property;
     58 using testing::Return;
     59 using testing::_;
     60 
     61 namespace base {
     62 
     63 // Helper for using EXPECT_EQ() with base::Value.
     64 bool operator==(const Value& first, const Value& second) {
     65   return first.Equals(&second);
     66 }
     67 
     68 // Helper for pretty-printing the contents of base::Value in case of failures.
     69 void PrintTo(const Value& value, std::ostream* stream) {
     70   std::string json;
     71   JSONWriter::Write(&value, &json);
     72   *stream << json;
     73 }
     74 
     75 }  // namespace base
     76 
     77 // Googlemock matcher for base::Value.
     78 MATCHER_P(EqualsValue, expected, "") {
     79   return arg && arg->Equals(expected);
     80 }
     81 
     82 PreferencesBrowserTest::PreferencesBrowserTest() {
     83 }
     84 
     85 PreferencesBrowserTest::~PreferencesBrowserTest() {
     86 }
     87 
     88 // Navigates to the settings page, causing the JavaScript pref handling code to
     89 // load and injects JavaScript testing code.
     90 void PreferencesBrowserTest::SetUpOnMainThread() {
     91   ui_test_utils::NavigateToURL(browser(),
     92                                GURL(chrome::kChromeUISettingsFrameURL));
     93   SetUpPrefs();
     94 }
     95 
     96 void PreferencesBrowserTest::SetUpPrefs() {
     97   content::WebContents* web_contents =
     98       browser()->tab_strip_model()->GetActiveWebContents();
     99   ASSERT_TRUE(web_contents);
    100   render_view_host_ = web_contents->GetRenderViewHost();
    101   ASSERT_TRUE(render_view_host_);
    102   pref_service_ = browser()->profile()->GetPrefs();
    103   pref_change_registrar_.Init(pref_service_);
    104   ASSERT_TRUE(content::ExecuteScript(render_view_host_,
    105       "function TestEnv() {"
    106       "  this.sentinelName_ = 'download.prompt_for_download';"
    107       "  this.prefs_ = [];"
    108       "  TestEnv.instance_ = this;"
    109       "}"
    110       ""
    111       "TestEnv.handleEvent = function(event) {"
    112       "  var env = TestEnv.instance_;"
    113       "  var name = event.type;"
    114       "  env.removePrefListener_(name);"
    115       "  if (name == TestEnv.sentinelName_)"
    116       "    env.sentinelValue_ = event.value.value;"
    117       "  else"
    118       "    env.reply_[name] = event.value;"
    119       "  if (env.fetching_ && !--env.fetching_ ||"
    120       "      !env.fetching_ && name == env.sentinelName_) {"
    121       "    env.removePrefListeners_();"
    122       "    window.domAutomationController.send(JSON.stringify(env.reply_));"
    123       "    delete env.reply_;"
    124       "  }"
    125       "};"
    126       ""
    127       "TestEnv.prototype = {"
    128       "  addPrefListener_: function(name) {"
    129       "    Preferences.getInstance().addEventListener(name,"
    130       "                                               TestEnv.handleEvent);"
    131       "  },"
    132       ""
    133       "  addPrefListeners_: function() {"
    134       "    for (var i in this.prefs_)"
    135       "      this.addPrefListener_(this.prefs_[i]);"
    136       "  },"
    137       ""
    138       "  removePrefListener_: function(name) {"
    139       "    Preferences.getInstance().removeEventListener(name,"
    140       "                                                  TestEnv.handleEvent);"
    141       "  },"
    142       ""
    143       "  removePrefListeners_: function() {"
    144       "    for (var i in this.prefs_)"
    145       "      this.removePrefListener_(this.prefs_[i]);"
    146       "  },"
    147       ""
    148       ""
    149       "  addPref: function(name) {"
    150       "    this.prefs_.push(name);"
    151       "  },"
    152       ""
    153       "  setupAndReply: function() {"
    154       "    this.reply_ = {};"
    155       "    Preferences.instance_ = new Preferences();"
    156       "    this.addPref(this.sentinelName_);"
    157       "    this.fetching_ = this.prefs_.length;"
    158       "    this.addPrefListeners_();"
    159       "    Preferences.getInstance().initialize();"
    160       "  },"
    161       ""
    162       "  runAndReply: function(test) {"
    163       "    this.reply_ = {};"
    164       "    this.addPrefListeners_();"
    165       "    test();"
    166       "    this.sentinelValue_ = !this.sentinelValue_;"
    167       "    Preferences.setBooleanPref(this.sentinelName_, this.sentinelValue_,"
    168       "                               true);"
    169       "  },"
    170       ""
    171       "  startObserving: function() {"
    172       "    this.reply_ = {};"
    173       "    this.addPrefListeners_();"
    174       "  },"
    175       ""
    176       "  finishObservingAndReply: function() {"
    177       "    this.sentinelValue_ = !this.sentinelValue_;"
    178       "    Preferences.setBooleanPref(this.sentinelName_, this.sentinelValue_,"
    179       "                               true);"
    180       "  }"
    181       "};"));
    182 }
    183 
    184 // Forwards notifications received when pref values change in the backend.
    185 void PreferencesBrowserTest::OnPreferenceChanged(const std::string& pref_name) {
    186   OnCommit(pref_service_->FindPreference(pref_name.c_str()));
    187 }
    188 
    189 void PreferencesBrowserTest::SetUpInProcessBrowserTestFixture() {
    190   // Sets up a mock policy provider for user and device policies.
    191   EXPECT_CALL(policy_provider_, IsInitializationComplete(_))
    192       .WillRepeatedly(Return(true));
    193   policy::BrowserPolicyConnector::SetPolicyProviderForTesting(
    194       &policy_provider_);
    195 };
    196 
    197 void PreferencesBrowserTest::TearDownInProcessBrowserTestFixture() {
    198   STLDeleteElements(&default_values_);
    199   STLDeleteElements(&non_default_values_);
    200 }
    201 
    202 void PreferencesBrowserTest::SetUserPolicies(
    203     const std::vector<std::string>& names,
    204     const std::vector<base::Value*>& values,
    205     policy::PolicyLevel level) {
    206   policy::PolicyMap map;
    207   for (size_t i = 0; i < names.size(); ++i) {
    208     map.Set(names[i], level, policy::POLICY_SCOPE_USER,
    209             values[i]->DeepCopy(), NULL);
    210   }
    211   policy_provider_.UpdateChromePolicy(map);
    212 }
    213 
    214 void PreferencesBrowserTest::ClearUserPolicies() {
    215   policy::PolicyMap empty_policy_map;
    216   policy_provider_.UpdateChromePolicy(empty_policy_map);
    217 }
    218 
    219 void PreferencesBrowserTest::SetUserValues(
    220     const std::vector<std::string>& names,
    221     const std::vector<base::Value*>& values) {
    222   for (size_t i = 0; i < names.size(); ++i)
    223     pref_service_->Set(names[i].c_str(), *values[i]);
    224 }
    225 
    226 void PreferencesBrowserTest::VerifyKeyValue(const base::DictionaryValue& dict,
    227                                             const std::string& key,
    228                                             const base::Value& expected) {
    229   const base::Value* actual = NULL;
    230   EXPECT_TRUE(dict.Get(key, &actual)) << "Was checking key: " << key;
    231   if (actual)
    232     EXPECT_EQ(expected, *actual) << "Was checking key: " << key;
    233 }
    234 
    235 void PreferencesBrowserTest::VerifyPref(const base::DictionaryValue* prefs,
    236                                         const std::string& name,
    237                                         const base::Value* value,
    238                                         const std::string& controlledBy,
    239                                         bool disabled,
    240                                         bool uncommitted) {
    241   const base::Value* pref = NULL;
    242   const base::DictionaryValue* dict = NULL;
    243   ASSERT_TRUE(prefs->GetWithoutPathExpansion(name, &pref));
    244   ASSERT_TRUE(pref->GetAsDictionary(&dict));
    245   VerifyKeyValue(*dict, "value", *value);
    246   if (!controlledBy.empty())
    247     VerifyKeyValue(*dict, "controlledBy", base::StringValue(controlledBy));
    248   else
    249     EXPECT_FALSE(dict->HasKey("controlledBy"));
    250 
    251   if (disabled)
    252     VerifyKeyValue(*dict, "disabled", base::FundamentalValue(true));
    253   else if (dict->HasKey("disabled"))
    254     VerifyKeyValue(*dict, "disabled", base::FundamentalValue(false));
    255 
    256   if (uncommitted)
    257     VerifyKeyValue(*dict, "uncommitted", base::FundamentalValue(true));
    258   else if (dict->HasKey("uncommitted"))
    259     VerifyKeyValue(*dict, "uncommitted", base::FundamentalValue(false));
    260 }
    261 
    262 void PreferencesBrowserTest::VerifyObservedPref(const std::string& json,
    263                                                 const std::string& name,
    264                                                 const base::Value* value,
    265                                                 const std::string& controlledBy,
    266                                                 bool disabled,
    267                                                 bool uncommitted) {
    268   scoped_ptr<base::Value> observed_value_ptr(base::JSONReader::Read(json));
    269   const base::DictionaryValue* observed_dict;
    270   ASSERT_TRUE(observed_value_ptr.get());
    271   ASSERT_TRUE(observed_value_ptr->GetAsDictionary(&observed_dict));
    272   VerifyPref(observed_dict, name, value, controlledBy, disabled, uncommitted);
    273 }
    274 
    275 void PreferencesBrowserTest::VerifyObservedPrefs(
    276     const std::string& json,
    277     const std::vector<std::string>& names,
    278     const std::vector<base::Value*>& values,
    279     const std::string& controlledBy,
    280     bool disabled,
    281     bool uncommitted) {
    282   scoped_ptr<base::Value> observed_value_ptr(base::JSONReader::Read(json));
    283   const base::DictionaryValue* observed_dict;
    284   ASSERT_TRUE(observed_value_ptr.get());
    285   ASSERT_TRUE(observed_value_ptr->GetAsDictionary(&observed_dict));
    286   for (size_t i = 0; i < names.size(); ++i)
    287     VerifyPref(observed_dict, names[i], values[i], controlledBy, disabled,
    288                uncommitted);
    289 }
    290 
    291 void PreferencesBrowserTest::ExpectNoCommit(const std::string& name) {
    292   pref_change_registrar_.Add(
    293       name.c_str(),
    294       base::Bind(&PreferencesBrowserTest::OnPreferenceChanged,
    295                  base::Unretained(this)));
    296   EXPECT_CALL(*this, OnCommit(Property(&PrefService::Preference::name, name)))
    297       .Times(0);
    298 }
    299 
    300 void PreferencesBrowserTest::ExpectSetCommit(const std::string& name,
    301                                              const base::Value* value) {
    302   pref_change_registrar_.Add(
    303       name.c_str(),
    304       base::Bind(&PreferencesBrowserTest::OnPreferenceChanged,
    305                  base::Unretained(this)));
    306   EXPECT_CALL(*this, OnCommit(AllOf(
    307       Property(&PrefService::Preference::name, name),
    308       Property(&PrefService::Preference::IsUserControlled, true),
    309       Property(&PrefService::Preference::GetValue, EqualsValue(value)))));
    310 }
    311 
    312 void PreferencesBrowserTest::ExpectClearCommit(const std::string& name) {
    313   pref_change_registrar_.Add(
    314       name.c_str(),
    315       base::Bind(&PreferencesBrowserTest::OnPreferenceChanged,
    316                  base::Unretained(this)));
    317   EXPECT_CALL(*this, OnCommit(AllOf(
    318       Property(&PrefService::Preference::name, name),
    319       Property(&PrefService::Preference::IsUserControlled, false))));
    320 }
    321 
    322 void PreferencesBrowserTest::VerifyAndClearExpectations() {
    323   Mock::VerifyAndClearExpectations(this);
    324   pref_change_registrar_.RemoveAll();
    325 }
    326 
    327 void PreferencesBrowserTest::SetupJavaScriptTestEnvironment(
    328     const std::vector<std::string>& pref_names,
    329     std::string* observed_json) const {
    330   std::stringstream javascript;
    331   javascript << "var testEnv = new TestEnv();";
    332   for (std::vector<std::string>::const_iterator name = pref_names.begin();
    333        name != pref_names.end(); ++name)
    334     javascript << "testEnv.addPref('" << name->c_str() << "');";
    335   javascript << "testEnv.setupAndReply();";
    336   std::string temp_observed_json;
    337   if (!observed_json)
    338     observed_json = &temp_observed_json;
    339   ASSERT_TRUE(content::ExecuteScriptAndExtractString(
    340       render_view_host_, javascript.str(), observed_json));
    341 }
    342 
    343 void PreferencesBrowserTest::SetPref(const std::string& name,
    344                                      const std::string& type,
    345                                      const base::Value* value,
    346                                      bool commit,
    347                                      std::string* observed_json) {
    348   scoped_ptr<base::Value> commit_ptr(new base::FundamentalValue(commit));
    349   std::stringstream javascript;
    350   javascript << "testEnv.runAndReply(function() {"
    351              << "  Preferences.set" << type << "Pref("
    352              << "      '" << name << "',"
    353              << "      " << *value << ","
    354              << "      " << *commit_ptr << ");"
    355              << "});";
    356   ASSERT_TRUE(content::ExecuteScriptAndExtractString(
    357       render_view_host_, javascript.str(), observed_json));
    358 }
    359 
    360 void PreferencesBrowserTest::VerifySetPref(const std::string& name,
    361                                            const std::string& type,
    362                                            const base::Value* value,
    363                                            bool commit) {
    364   if (commit)
    365     ExpectSetCommit(name, value);
    366   else
    367     ExpectNoCommit(name);
    368   std::string observed_json;
    369   SetPref(name, type, value, commit, &observed_json);
    370   VerifyObservedPref(observed_json, name, value, std::string(), false, !commit);
    371   VerifyAndClearExpectations();
    372 }
    373 
    374 void PreferencesBrowserTest::VerifyClearPref(const std::string& name,
    375                                              const base::Value* value,
    376                                              bool commit) {
    377   if (commit)
    378     ExpectClearCommit(name);
    379   else
    380     ExpectNoCommit(name);
    381   scoped_ptr<base::Value> commit_ptr(new base::FundamentalValue(commit));
    382   std::string commit_json;
    383   base::JSONWriter::Write(commit_ptr.get(), &commit_json);
    384   std::stringstream javascript;
    385   javascript << "testEnv.runAndReply(function() {"
    386              << "    Preferences.clearPref("
    387              << "      '" << name.c_str() << "',"
    388              << "      " << commit_json.c_str() << ");});";
    389   std::string observed_json;
    390   ASSERT_TRUE(content::ExecuteScriptAndExtractString(
    391       render_view_host_, javascript.str(), &observed_json));
    392   VerifyObservedPref(observed_json, name, value, "recommended", false, !commit);
    393   VerifyAndClearExpectations();
    394 }
    395 
    396 void PreferencesBrowserTest::VerifyCommit(const std::string& name,
    397                                           const base::Value* value,
    398                                           const std::string& controlledBy) {
    399   std::stringstream javascript;
    400   javascript << "testEnv.runAndReply(function() {"
    401              << "    Preferences.getInstance().commitPref("
    402              << "        '" << name.c_str() << "');});";
    403   std::string observed_json;
    404   ASSERT_TRUE(content::ExecuteScriptAndExtractString(
    405       render_view_host_, javascript.str(), &observed_json));
    406   VerifyObservedPref(observed_json, name, value, controlledBy, false, false);
    407 }
    408 
    409 void PreferencesBrowserTest::VerifySetCommit(const std::string& name,
    410                                              const base::Value* value) {
    411   ExpectSetCommit(name, value);
    412   VerifyCommit(name, value, std::string());
    413   VerifyAndClearExpectations();
    414 }
    415 
    416 void PreferencesBrowserTest::VerifyClearCommit(const std::string& name,
    417                                                const base::Value* value) {
    418   ExpectClearCommit(name);
    419   VerifyCommit(name, value, "recommended");
    420   VerifyAndClearExpectations();
    421 }
    422 
    423 void PreferencesBrowserTest::VerifyRollback(const std::string& name,
    424                                             const base::Value* value,
    425                                             const std::string& controlledBy) {
    426   ExpectNoCommit(name);
    427   std::stringstream javascript;
    428   javascript << "testEnv.runAndReply(function() {"
    429              << "    Preferences.getInstance().rollbackPref("
    430              << "        '" << name.c_str() << "');});";
    431   std::string observed_json;
    432   ASSERT_TRUE(content::ExecuteScriptAndExtractString(
    433       render_view_host_, javascript.str(), &observed_json));
    434   VerifyObservedPref(observed_json, name, value, controlledBy, false, true);
    435   VerifyAndClearExpectations();
    436 }
    437 
    438 void PreferencesBrowserTest::StartObserving() {
    439   ASSERT_TRUE(content::ExecuteScript(
    440       render_view_host_, "testEnv.startObserving();"));
    441 }
    442 
    443 void PreferencesBrowserTest::FinishObserving(std::string* observed_json) {
    444   ASSERT_TRUE(content::ExecuteScriptAndExtractString(
    445       render_view_host_,
    446       "testEnv.finishObservingAndReply();",
    447       observed_json));
    448 }
    449 
    450 void PreferencesBrowserTest::UseDefaultTestPrefs(bool includeListPref) {
    451   // Boolean pref.
    452   types_.push_back("Boolean");
    453   pref_names_.push_back(prefs::kAlternateErrorPagesEnabled);
    454   policy_names_.push_back(policy::key::kAlternateErrorPagesEnabled);
    455   non_default_values_.push_back(new base::FundamentalValue(false));
    456 
    457   // Integer pref.
    458   types_.push_back("Integer");
    459   pref_names_.push_back(prefs::kRestoreOnStartup);
    460   policy_names_.push_back(policy::key::kRestoreOnStartup);
    461   non_default_values_.push_back(new base::FundamentalValue(4));
    462 
    463   // List pref.
    464   if (includeListPref) {
    465     types_.push_back("List");
    466     pref_names_.push_back(prefs::kURLsToRestoreOnStartup);
    467     policy_names_.push_back(policy::key::kRestoreOnStartupURLs);
    468     base::ListValue* list = new base::ListValue;
    469     list->Append(new base::StringValue("http://www.google.com"));
    470     list->Append(new base::StringValue("http://example.com"));
    471     non_default_values_.push_back(list);
    472   }
    473 
    474   // Retrieve default values.
    475   for (std::vector<std::string>::const_iterator name = pref_names_.begin();
    476         name != pref_names_.end(); ++name) {
    477     default_values_.push_back(
    478         pref_service_->GetDefaultPrefValue(name->c_str())->DeepCopy());
    479   }
    480 }
    481 
    482 // Verifies that initializing the JavaScript Preferences class fires the correct
    483 // notifications in JavaScript.
    484 IN_PROC_BROWSER_TEST_F(PreferencesBrowserTest, FetchPrefs) {
    485   UseDefaultTestPrefs(true);
    486   std::string observed_json;
    487 
    488   // Verify notifications when default values are in effect.
    489   SetupJavaScriptTestEnvironment(pref_names_, &observed_json);
    490   VerifyObservedPrefs(
    491       observed_json, pref_names_, default_values_, std::string(), false, false);
    492 
    493   // Verify notifications when recommended values are in effect.
    494   SetUserPolicies(policy_names_, non_default_values_,
    495                   policy::POLICY_LEVEL_RECOMMENDED);
    496   SetupJavaScriptTestEnvironment(pref_names_, &observed_json);
    497   VerifyObservedPrefs(observed_json, pref_names_, non_default_values_,
    498                       "recommended", false, false);
    499 
    500   // Verify notifications when mandatory values are in effect.
    501   SetUserPolicies(policy_names_, non_default_values_,
    502                   policy::POLICY_LEVEL_MANDATORY);
    503   SetupJavaScriptTestEnvironment(pref_names_, &observed_json);
    504   VerifyObservedPrefs(observed_json, pref_names_, non_default_values_,
    505                       "policy", true, false);
    506 
    507   // Verify notifications when user-modified values are in effect.
    508   ClearUserPolicies();
    509   SetUserValues(pref_names_, non_default_values_);
    510   SetupJavaScriptTestEnvironment(pref_names_, &observed_json);
    511   VerifyObservedPrefs(observed_json,
    512                       pref_names_,
    513                       non_default_values_,
    514                       std::string(),
    515                       false,
    516                       false);
    517 }
    518 
    519 // Verifies that setting a user-modified pref value through the JavaScript
    520 // Preferences class fires the correct notification in JavaScript and causes the
    521 // change to be committed to the C++ backend.
    522 IN_PROC_BROWSER_TEST_F(PreferencesBrowserTest, SetPrefs) {
    523   UseDefaultTestPrefs(false);
    524 
    525   ASSERT_NO_FATAL_FAILURE(SetupJavaScriptTestEnvironment(pref_names_, NULL));
    526   for (size_t i = 0; i < pref_names_.size(); ++i)
    527     VerifySetPref(pref_names_[i], types_[i], non_default_values_[i], true);
    528 }
    529 
    530 // Verifies that clearing a user-modified pref value through the JavaScript
    531 // Preferences class fires the correct notification in JavaScript and causes the
    532 // change to be committed to the C++ backend.
    533 IN_PROC_BROWSER_TEST_F(PreferencesBrowserTest, ClearPrefs) {
    534   UseDefaultTestPrefs(false);
    535 
    536   SetUserPolicies(policy_names_, default_values_,
    537                   policy::POLICY_LEVEL_RECOMMENDED);
    538   SetUserValues(pref_names_, non_default_values_);
    539   ASSERT_NO_FATAL_FAILURE(SetupJavaScriptTestEnvironment(pref_names_, NULL));
    540   for (size_t i = 0; i < pref_names_.size(); ++i)
    541     VerifyClearPref(pref_names_[i], default_values_[i], true);
    542 }
    543 
    544 // Verifies that when the user-modified value of a dialog pref is set and the
    545 // change then committed through the JavaScript Preferences class, the correct
    546 // notifications fire and a commit to the C++ backend occurs in the latter step
    547 // only.
    548 IN_PROC_BROWSER_TEST_F(PreferencesBrowserTest, DialogPrefsSetCommit) {
    549   UseDefaultTestPrefs(false);
    550 
    551   ASSERT_NO_FATAL_FAILURE(SetupJavaScriptTestEnvironment(pref_names_, NULL));
    552   for (size_t i = 0; i < pref_names_.size(); ++i) {
    553     VerifySetPref(pref_names_[i], types_[i], non_default_values_[i], false);
    554     VerifySetCommit(pref_names_[i], non_default_values_[i]);
    555   }
    556 }
    557 
    558 // Verifies that when the user-modified value of a dialog pref is set and the
    559 // change then rolled back through the JavaScript Preferences class, the correct
    560 // notifications fire and no commit to the C++ backend occurs.
    561 IN_PROC_BROWSER_TEST_F(PreferencesBrowserTest, DialogPrefsSetRollback) {
    562   UseDefaultTestPrefs(false);
    563 
    564   // Verify behavior when default values are in effect.
    565   ASSERT_NO_FATAL_FAILURE(SetupJavaScriptTestEnvironment(pref_names_, NULL));
    566   for (size_t i = 0; i < pref_names_.size(); ++i) {
    567     VerifySetPref(pref_names_[i], types_[i], non_default_values_[i], false);
    568     VerifyRollback(pref_names_[i], default_values_[i], std::string());
    569   }
    570 
    571   // Verify behavior when recommended values are in effect.
    572   SetUserPolicies(policy_names_, default_values_,
    573                   policy::POLICY_LEVEL_RECOMMENDED);
    574   ASSERT_NO_FATAL_FAILURE(SetupJavaScriptTestEnvironment(pref_names_, NULL));
    575   for (size_t i = 0; i < pref_names_.size(); ++i) {
    576     VerifySetPref(pref_names_[i], types_[i], non_default_values_[i], false);
    577     VerifyRollback(pref_names_[i], default_values_[i], "recommended");
    578   }
    579 }
    580 
    581 // Verifies that when the user-modified value of a dialog pref is cleared and
    582 // the change then committed through the JavaScript Preferences class, the
    583 // correct notifications fire and a commit to the C++ backend occurs in the
    584 // latter step only.
    585 IN_PROC_BROWSER_TEST_F(PreferencesBrowserTest, DialogPrefsClearCommit) {
    586   UseDefaultTestPrefs(false);
    587 
    588   SetUserPolicies(policy_names_, default_values_,
    589                   policy::POLICY_LEVEL_RECOMMENDED);
    590   SetUserValues(pref_names_, non_default_values_);
    591   ASSERT_NO_FATAL_FAILURE(SetupJavaScriptTestEnvironment(pref_names_, NULL));
    592   for (size_t i = 0; i < pref_names_.size(); ++i) {
    593     VerifyClearPref(pref_names_[i], default_values_[i], false);
    594     VerifyClearCommit(pref_names_[i], default_values_[i]);
    595   }
    596 }
    597 
    598 // Verifies that when the user-modified value of a dialog pref is cleared and
    599 // the change then rolled back through the JavaScript Preferences class, the
    600 // correct notifications fire and no commit to the C++ backend occurs.
    601 IN_PROC_BROWSER_TEST_F(PreferencesBrowserTest, DialogPrefsClearRollback) {
    602   UseDefaultTestPrefs(false);
    603 
    604   SetUserPolicies(policy_names_, default_values_,
    605                   policy::POLICY_LEVEL_RECOMMENDED);
    606   SetUserValues(pref_names_, non_default_values_);
    607   ASSERT_NO_FATAL_FAILURE(SetupJavaScriptTestEnvironment(pref_names_, NULL));
    608   for (size_t i = 0; i < pref_names_.size(); ++i) {
    609     VerifyClearPref(pref_names_[i], default_values_[i], false);
    610     VerifyRollback(pref_names_[i], non_default_values_[i], std::string());
    611   }
    612 }
    613 
    614 // Verifies that when preference values change in the C++ backend, the correct
    615 // notifications fire in JavaScript.
    616 IN_PROC_BROWSER_TEST_F(PreferencesBrowserTest, NotificationsOnBackendChanges) {
    617   UseDefaultTestPrefs(false);
    618   std::string observed_json;
    619 
    620   ASSERT_NO_FATAL_FAILURE(SetupJavaScriptTestEnvironment(pref_names_, NULL));
    621 
    622   // Verify notifications when recommended values come into effect.
    623   StartObserving();
    624   SetUserPolicies(policy_names_, non_default_values_,
    625                   policy::POLICY_LEVEL_RECOMMENDED);
    626   FinishObserving(&observed_json);
    627   VerifyObservedPrefs(observed_json, pref_names_, non_default_values_,
    628                       "recommended", false, false);
    629 
    630   // Verify notifications when mandatory values come into effect.
    631   StartObserving();
    632   SetUserPolicies(policy_names_, non_default_values_,
    633                   policy::POLICY_LEVEL_MANDATORY);
    634   FinishObserving(&observed_json);
    635   VerifyObservedPrefs(observed_json, pref_names_, non_default_values_,
    636                       "policy", true, false);
    637 
    638   // Verify notifications when default values come into effect.
    639   StartObserving();
    640   ClearUserPolicies();
    641   FinishObserving(&observed_json);
    642   VerifyObservedPrefs(
    643       observed_json, pref_names_, default_values_, std::string(), false, false);
    644 
    645   // Verify notifications when user-modified values come into effect.
    646   StartObserving();
    647   SetUserValues(pref_names_, non_default_values_);
    648   FinishObserving(&observed_json);
    649   VerifyObservedPrefs(observed_json,
    650                       pref_names_,
    651                       non_default_values_,
    652                       std::string(),
    653                       false,
    654                       false);
    655 }
    656 
    657 #if defined(OS_CHROMEOS)
    658 
    659 // Verifies that initializing the JavaScript Preferences class fires the correct
    660 // notifications in JavaScript for pref values handled by the
    661 // CoreChromeOSOptionsHandler class.
    662 IN_PROC_BROWSER_TEST_F(PreferencesBrowserTest, ChromeOSDeviceFetchPrefs) {
    663   std::vector<base::Value*> decorated_non_default_values;
    664   std::string observed_json;
    665 
    666   // Boolean pref.
    667   pref_names_.push_back(chromeos::kAccountsPrefAllowGuest);
    668   default_values_.push_back(new base::FundamentalValue(true));
    669   non_default_values_.push_back(new base::FundamentalValue(false));
    670   decorated_non_default_values.push_back(
    671       non_default_values_.back()->DeepCopy());
    672 
    673   // String pref.
    674   pref_names_.push_back(chromeos::kReleaseChannel);
    675   default_values_.push_back(new base::StringValue(""));
    676   non_default_values_.push_back(new base::StringValue("stable-channel"));
    677   decorated_non_default_values.push_back(
    678       non_default_values_.back()->DeepCopy());
    679 
    680   // List pref.
    681   pref_names_.push_back(chromeos::kAccountsPrefUsers);
    682   default_values_.push_back(new base::ListValue);
    683   base::ListValue* list = new base::ListValue;
    684   list->Append(new base::StringValue("me (at) google.com"));
    685   list->Append(new base::StringValue("you (at) google.com"));
    686   non_default_values_.push_back(list);
    687   list = new base::ListValue;
    688   base::DictionaryValue* dict = new base::DictionaryValue;
    689   dict->SetString("username", "me (at) google.com");
    690   dict->SetString("name", "me (at) google.com");
    691   dict->SetString("email", "");
    692   dict->SetBoolean("owner", false);
    693   list->Append(dict);
    694   dict = new base::DictionaryValue;
    695   dict->SetString("username", "you (at) google.com");
    696   dict->SetString("name", "you (at) google.com");
    697   dict->SetString("email", "");
    698   dict->SetBoolean("owner", false);
    699   list->Append(dict);
    700   decorated_non_default_values.push_back(list);
    701 
    702   // Verify notifications when default values are in effect.
    703   SetupJavaScriptTestEnvironment(pref_names_, &observed_json);
    704   VerifyObservedPrefs(observed_json, pref_names_, default_values_,
    705                       "owner", true, false);
    706 
    707   // Verify notifications when mandatory values are in effect.
    708   chromeos::CrosSettings* cros_settings = chromeos::CrosSettings::Get();
    709   for (size_t i = 0; i < pref_names_.size(); ++i)
    710     cros_settings->Set(pref_names_[i], *non_default_values_[i]);
    711   // FIXME(bartfab): Find a way to simulate enterprise enrollment in browser
    712   // tests. Only if Chrome thinks that it is enrolled will the device prefs be
    713   // decorated with "controlledBy: policy".
    714   SetupJavaScriptTestEnvironment(pref_names_, &observed_json);
    715   VerifyObservedPrefs(observed_json, pref_names_, decorated_non_default_values,
    716                       "owner", true, false);
    717 
    718   STLDeleteElements(&decorated_non_default_values);
    719 }
    720 
    721 namespace {
    722 
    723 const char* kUserProfilePath = "user_profile";
    724 
    725 }  // namespace
    726 
    727 class ProxyPreferencesBrowserTest : public PreferencesBrowserTest {
    728  public:
    729   virtual void SetUpOnMainThread() OVERRIDE {
    730     SetupNetworkEnvironment();
    731     content::RunAllPendingInMessageLoop();
    732 
    733     scoped_ptr<base::DictionaryValue> proxy_config_dict(
    734         ProxyConfigDictionary::CreateFixedServers("127.0.0.1:8080",
    735                                                   "*.google.com, 1.2.3.4:22"));
    736 
    737     ProxyConfigDictionary proxy_config(proxy_config_dict.get());
    738 
    739     const chromeos::FavoriteState* network = GetDefaultFavoriteNetwork();
    740     ASSERT_TRUE(network);
    741     chromeos::proxy_config::SetProxyConfigForFavoriteNetwork(proxy_config,
    742                                                              *network);
    743 
    744     std::string url = base::StringPrintf("%s?network=%s",
    745                                          chrome::kChromeUIProxySettingsURL,
    746                                          network->path().c_str());
    747 
    748     ui_test_utils::NavigateToURL(browser(), GURL(url));
    749     SetUpPrefs();
    750   }
    751 
    752  protected:
    753   void SetupNetworkEnvironment() {
    754     chromeos::ShillProfileClient::TestInterface* profile_test =
    755         chromeos::DBusThreadManager::Get()->GetShillProfileClient()
    756             ->GetTestInterface();
    757     chromeos::ShillServiceClient::TestInterface* service_test =
    758         chromeos::DBusThreadManager::Get()->GetShillServiceClient()
    759             ->GetTestInterface();
    760 
    761     profile_test->AddProfile(kUserProfilePath, "user");
    762 
    763     service_test->ClearServices();
    764     service_test->AddService("stub_ethernet",
    765                              "eth0",
    766                              shill::kTypeEthernet,
    767                              shill::kStateOnline,
    768                              true,   // add to visible
    769                              true);  // add to watchlist
    770     service_test->SetServiceProperty("stub_ethernet",
    771                                      shill::kGuidProperty,
    772                                      base::StringValue("stub_ethernet"));
    773     service_test->SetServiceProperty("stub_ethernet",
    774                                      shill::kProfileProperty,
    775                                      base::StringValue(kUserProfilePath));
    776     profile_test->AddService(kUserProfilePath, "stub_wifi2");
    777   }
    778 
    779   void SetONCPolicy(const char* policy_name, policy::PolicyScope scope) {
    780     std::string onc_policy =
    781         "{ \"NetworkConfigurations\": ["
    782         "    { \"GUID\": \"stub_ethernet\","
    783         "      \"Type\": \"Ethernet\","
    784         "      \"Name\": \"My Ethernet\","
    785         "      \"Ethernet\": {"
    786         "        \"Authentication\": \"None\" },"
    787         "      \"ProxySettings\": {"
    788         "        \"PAC\": \"http://domain.com/x\","
    789         "        \"Type\": \"PAC\" }"
    790         "    }"
    791         "  ],"
    792         "  \"Type\": \"UnencryptedConfiguration\""
    793         "}";
    794 
    795     policy::PolicyMap map;
    796     map.Set(policy_name,
    797             policy::POLICY_LEVEL_MANDATORY,
    798             scope,
    799             new base::StringValue(onc_policy),
    800             NULL);
    801     policy_provider_.UpdateChromePolicy(map);
    802 
    803     content::RunAllPendingInMessageLoop();
    804   }
    805 
    806   const chromeos::FavoriteState* GetDefaultFavoriteNetwork() {
    807     chromeos::NetworkStateHandler* handler =
    808         chromeos::NetworkHandler::Get()->network_state_handler();
    809     return handler->DefaultFavoriteNetwork();
    810   }
    811 
    812   void SetProxyPref(const std::string& name, const base::Value& value) {
    813     std::string type;
    814     switch (value.GetType()) {
    815       case base::Value::TYPE_BOOLEAN:
    816         type = "Boolean";
    817         break;
    818       case base::Value::TYPE_INTEGER:
    819         type = "Integer";
    820         break;
    821       case base::Value::TYPE_STRING:
    822         type = "String";
    823         break;
    824       default:
    825         ASSERT_TRUE(false);
    826     }
    827 
    828     std::string observed_json;
    829     SetPref(name, type, &value, true, &observed_json);
    830   }
    831 
    832   void VerifyCurrentProxyServer(const std::string& expected_server,
    833                                 onc::ONCSource expected_source) {
    834     const chromeos::FavoriteState* network = GetDefaultFavoriteNetwork();
    835     ASSERT_TRUE(network);
    836     onc::ONCSource actual_source;
    837     scoped_ptr<ProxyConfigDictionary> proxy_dict =
    838         chromeos::proxy_config::GetProxyConfigForFavoriteNetwork(
    839             pref_service_,
    840             g_browser_process->local_state(),
    841             *network,
    842             &actual_source);
    843     ASSERT_TRUE(proxy_dict);
    844     std::string actual_proxy_server;
    845     EXPECT_TRUE(proxy_dict->GetProxyServer(&actual_proxy_server));
    846     EXPECT_EQ(expected_server, actual_proxy_server);
    847     EXPECT_EQ(expected_source, actual_source);
    848   }
    849 };
    850 
    851 // Verifies that proxy settings are correctly pushed to JavaScript during
    852 // initialization of the proxy settings page.
    853 IN_PROC_BROWSER_TEST_F(ProxyPreferencesBrowserTest, ChromeOSInitializeProxy) {
    854   // Boolean pref.
    855   pref_names_.push_back(chromeos::kProxySingle);
    856   non_default_values_.push_back(new base::FundamentalValue(true));
    857 
    858   // Integer prefs.
    859   pref_names_.push_back(chromeos::kProxySingleHttpPort);
    860   non_default_values_.push_back(new base::FundamentalValue(8080));
    861 
    862   // String pref.
    863   pref_names_.push_back(chromeos::kProxySingleHttp);
    864   non_default_values_.push_back(new base::StringValue("127.0.0.1"));
    865 
    866   // List pref.
    867   pref_names_.push_back(chromeos::kProxyIgnoreList);
    868   base::ListValue* list = new base::ListValue();
    869   list->Append(new base::StringValue("*.google.com"));
    870   list->Append(new base::StringValue("1.2.3.4:22"));
    871   non_default_values_.push_back(list);
    872 
    873   // Verify that no policy is presented to the UI. This must be verified on the
    874   // kProxyType and the kUseSharedProxies prefs.
    875   pref_names_.push_back(chromeos::kProxyType);
    876   non_default_values_.push_back(new base::FundamentalValue(2));
    877 
    878   pref_names_.push_back(prefs::kUseSharedProxies);
    879   non_default_values_.push_back(new base::FundamentalValue(false));
    880 
    881   std::string observed_json;
    882   SetupJavaScriptTestEnvironment(pref_names_, &observed_json);
    883   VerifyObservedPrefs(
    884       observed_json, pref_names_, non_default_values_, "", false, false);
    885 }
    886 
    887 IN_PROC_BROWSER_TEST_F(ProxyPreferencesBrowserTest, ONCPolicy) {
    888   SetONCPolicy(policy::key::kOpenNetworkConfiguration,
    889                policy::POLICY_SCOPE_USER);
    890 
    891   // Verify that per-network policy is presented to the UI. This must be
    892   // verified on the kProxyType.
    893   pref_names_.push_back(chromeos::kProxyType);
    894   non_default_values_.push_back(new base::FundamentalValue(3));
    895 
    896   std::string observed_json;
    897   SetupJavaScriptTestEnvironment(pref_names_, &observed_json);
    898   VerifyObservedPrefs(
    899       observed_json, pref_names_, non_default_values_, "policy", true, false);
    900 
    901   // Verify that 'use-shared-proxies' is not affected by per-network policy.
    902   pref_names_.clear();
    903   STLDeleteElements(&non_default_values_);
    904   pref_names_.push_back(prefs::kUseSharedProxies);
    905   non_default_values_.push_back(new base::FundamentalValue(false));
    906 
    907   SetupJavaScriptTestEnvironment(pref_names_, &observed_json);
    908   VerifyObservedPrefs(
    909       observed_json, pref_names_, non_default_values_, "", false, false);
    910 }
    911 
    912 IN_PROC_BROWSER_TEST_F(ProxyPreferencesBrowserTest, DeviceONCPolicy) {
    913   SetONCPolicy(policy::key::kDeviceOpenNetworkConfiguration,
    914                policy::POLICY_SCOPE_MACHINE);
    915 
    916   // Verify that the policy is presented to the UI. This verification must be
    917   // done on the kProxyType pref.
    918   pref_names_.push_back(chromeos::kProxyType);
    919   non_default_values_.push_back(new base::FundamentalValue(3));
    920 
    921   std::string observed_json;
    922   SetupJavaScriptTestEnvironment(pref_names_, &observed_json);
    923   VerifyObservedPrefs(
    924       observed_json, pref_names_, non_default_values_, "policy", true, false);
    925 
    926   // Verify that 'use-shared-proxies' is not affected by per-network policy.
    927   pref_names_.clear();
    928   STLDeleteElements(&non_default_values_);
    929   pref_names_.push_back(prefs::kUseSharedProxies);
    930   non_default_values_.push_back(new base::FundamentalValue(false));
    931 
    932   SetupJavaScriptTestEnvironment(pref_names_, &observed_json);
    933   VerifyObservedPrefs(
    934       observed_json, pref_names_, non_default_values_, "", false, false);
    935 }
    936 
    937 IN_PROC_BROWSER_TEST_F(ProxyPreferencesBrowserTest, UserProxyPolicy) {
    938   policy_names_.push_back(policy::key::kProxyMode);
    939   default_values_.push_back(
    940       new base::StringValue(ProxyPrefs::kAutoDetectProxyModeName));
    941   SetUserPolicies(
    942       policy_names_, default_values_, policy::POLICY_LEVEL_MANDATORY);
    943   content::RunAllPendingInMessageLoop();
    944 
    945   // Verify that the policy is presented to the UI. This verification must be
    946   // done on the kProxyType pref.
    947   pref_names_.push_back(chromeos::kProxyType);
    948   non_default_values_.push_back(new base::FundamentalValue(3));
    949 
    950   // Verify that 'use-shared-proxies' is controlled by the policy.
    951   pref_names_.push_back(prefs::kUseSharedProxies);
    952   non_default_values_.push_back(new base::FundamentalValue(false));
    953 
    954   std::string observed_json;
    955   SetupJavaScriptTestEnvironment(pref_names_, &observed_json);
    956   VerifyObservedPrefs(
    957       observed_json, pref_names_, non_default_values_, "policy", true, false);
    958 }
    959 
    960 // Verifies that modifications to the proxy settings are correctly pushed from
    961 // JavaScript to the ProxyConfig property stored in the network configuration.
    962 IN_PROC_BROWSER_TEST_F(ProxyPreferencesBrowserTest, ChromeOSSetProxy) {
    963   ASSERT_NO_FATAL_FAILURE(SetupJavaScriptTestEnvironment(pref_names_, NULL));
    964 
    965   SetProxyPref(chromeos::kProxySingleHttpPort, base::FundamentalValue(123));
    966   SetProxyPref(chromeos::kProxySingleHttp, base::StringValue("www.adomain.xy"));
    967 
    968   VerifyCurrentProxyServer("www.adomain.xy:123",
    969                            onc::ONC_SOURCE_NONE);
    970 }
    971 
    972 // Verify that default proxy ports are used and that ports can be updated
    973 // without affecting the previously set hosts.
    974 IN_PROC_BROWSER_TEST_F(ProxyPreferencesBrowserTest, ChromeOSProxyDefaultPorts) {
    975   ASSERT_NO_FATAL_FAILURE(SetupJavaScriptTestEnvironment(pref_names_, NULL));
    976 
    977   // Set to manual, per scheme proxy.
    978   SetProxyPref(chromeos::kProxySingle, base::FundamentalValue(false));
    979 
    980   // Set hosts but no ports.
    981   SetProxyPref(chromeos::kProxyHttpUrl, base::StringValue("a.com"));
    982   SetProxyPref(chromeos::kProxyHttpsUrl, base::StringValue("4.3.2.1"));
    983   SetProxyPref(chromeos::kProxyFtpUrl, base::StringValue("c.com"));
    984   SetProxyPref(chromeos::kProxySocks, base::StringValue("d.com"));
    985 
    986   // Verify default ports.
    987   VerifyCurrentProxyServer(
    988       "http=a.com:80;https=4.3.2.1:80;ftp=c.com:80;socks=socks4://d.com:1080",
    989       onc::ONC_SOURCE_NONE);
    990 
    991   // Set and verify the ports.
    992   SetProxyPref(chromeos::kProxyHttpPort, base::FundamentalValue(1));
    993   SetProxyPref(chromeos::kProxyHttpsPort, base::FundamentalValue(2));
    994   SetProxyPref(chromeos::kProxyFtpPort, base::FundamentalValue(3));
    995   SetProxyPref(chromeos::kProxySocksPort, base::FundamentalValue(4));
    996 
    997   VerifyCurrentProxyServer(
    998       "http=a.com:1;https=4.3.2.1:2;ftp=c.com:3;socks=socks4://d.com:4",
    999       onc::ONC_SOURCE_NONE);
   1000 }
   1001 
   1002 #endif
   1003