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/policy/external_data_fetcher.h"
     20 #include "chrome/browser/policy/policy_map.h"
     21 #include "chrome/browser/policy/policy_types.h"
     22 #include "chrome/browser/profiles/profile.h"
     23 #include "chrome/browser/ui/browser.h"
     24 #include "chrome/browser/ui/tabs/tab_strip_model.h"
     25 #include "chrome/common/pref_names.h"
     26 #include "chrome/common/url_constants.h"
     27 #include "chrome/test/base/ui_test_utils.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/chromeos/settings/cros_settings_names.h"
     44 #include "chrome/browser/prefs/proxy_config_dictionary.h"
     45 #include "chromeos/dbus/dbus_thread_manager.h"
     46 #include "chromeos/dbus/shill_profile_client.h"
     47 #include "chromeos/dbus/shill_service_client.h"
     48 #include "chromeos/network/network_state.h"
     49 #include "chromeos/network/network_state_handler.h"
     50 #include "content/public/test/test_utils.h"
     51 #include "third_party/cros_system_api/dbus/service_constants.h"
     52 #endif
     53 
     54 using testing::AllOf;
     55 using testing::AnyNumber;
     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   EXPECT_CALL(policy_provider_, RegisterPolicyDomain(_))
    194       .Times(AnyNumber());
    195   policy::BrowserPolicyConnector::SetPolicyProviderForTesting(
    196       &policy_provider_);
    197 };
    198 
    199 void PreferencesBrowserTest::TearDownInProcessBrowserTestFixture() {
    200   STLDeleteElements(&default_values_);
    201   STLDeleteElements(&non_default_values_);
    202 }
    203 
    204 void PreferencesBrowserTest::SetUserPolicies(
    205     const std::vector<std::string>& names,
    206     const std::vector<base::Value*>& values,
    207     policy::PolicyLevel level) {
    208   policy::PolicyMap map;
    209   for (size_t i = 0; i < names.size(); ++i) {
    210     map.Set(names[i], level, policy::POLICY_SCOPE_USER,
    211             values[i]->DeepCopy(), NULL);
    212   }
    213   policy_provider_.UpdateChromePolicy(map);
    214 }
    215 
    216 void PreferencesBrowserTest::ClearUserPolicies() {
    217   policy::PolicyMap empty_policy_map;
    218   policy_provider_.UpdateChromePolicy(empty_policy_map);
    219 }
    220 
    221 void PreferencesBrowserTest::SetUserValues(
    222     const std::vector<std::string>& names,
    223     const std::vector<base::Value*>& values) {
    224   for (size_t i = 0; i < names.size(); ++i)
    225     pref_service_->Set(names[i].c_str(), *values[i]);
    226 }
    227 
    228 void PreferencesBrowserTest::VerifyKeyValue(const base::DictionaryValue& dict,
    229                                             const std::string& key,
    230                                             const base::Value& expected) {
    231   const base::Value* actual = NULL;
    232   EXPECT_TRUE(dict.Get(key, &actual)) << "Was checking key: " << key;
    233   EXPECT_EQ(expected, *actual) << "Was checking key: " << key;
    234 }
    235 
    236 void PreferencesBrowserTest::VerifyPref(const base::DictionaryValue* prefs,
    237                                         const std::string& name,
    238                                         const base::Value* value,
    239                                         const std::string& controlledBy,
    240                                         bool disabled,
    241                                         bool uncommitted) {
    242   const base::Value* pref;
    243   const base::DictionaryValue* dict;
    244   ASSERT_TRUE(prefs->GetWithoutPathExpansion(name, &pref));
    245   ASSERT_TRUE(pref->GetAsDictionary(&dict));
    246   VerifyKeyValue(*dict, "value", *value);
    247   if (!controlledBy.empty()) {
    248     VerifyKeyValue(*dict, "controlledBy", base::StringValue(controlledBy));
    249   } else {
    250     EXPECT_FALSE(dict->HasKey("controlledBy"));
    251   }
    252   if (disabled)
    253     VerifyKeyValue(*dict, "disabled", base::FundamentalValue(true));
    254   else if (dict->HasKey("disabled"))
    255     VerifyKeyValue(*dict, "disabled", base::FundamentalValue(false));
    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                       "", 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                       "", 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::NetworkState* network = GetDefaultNetwork();
    740     chromeos::proxy_config::SetProxyConfigForNetwork(proxy_config, *network);
    741 
    742     std::string url = base::StringPrintf("%s?network=%s",
    743                                          chrome::kChromeUIProxySettingsURL,
    744                                          network->path().c_str());
    745 
    746     ui_test_utils::NavigateToURL(browser(), GURL(url));
    747     SetUpPrefs();
    748   }
    749 
    750  protected:
    751   void SetupNetworkEnvironment() {
    752     chromeos::ShillProfileClient::TestInterface* profile_test =
    753         chromeos::DBusThreadManager::Get()->GetShillProfileClient()
    754             ->GetTestInterface();
    755     chromeos::ShillServiceClient::TestInterface* service_test =
    756         chromeos::DBusThreadManager::Get()->GetShillServiceClient()
    757             ->GetTestInterface();
    758 
    759     profile_test->AddProfile(kUserProfilePath, "user");
    760 
    761     service_test->ClearServices();
    762     service_test->AddService("stub_ethernet",
    763                              "eth0",
    764                              flimflam::kTypeEthernet,
    765                              flimflam::kStateOnline,
    766                              true,   // add to visible
    767                              true);  // add to watchlist
    768     service_test->SetServiceProperty("stub_ethernet",
    769                                      flimflam::kGuidProperty,
    770                                      base::StringValue("stub_ethernet"));
    771     service_test->SetServiceProperty("stub_ethernet",
    772                                      flimflam::kProfileProperty,
    773                                      base::StringValue(kUserProfilePath));
    774     profile_test->AddService(kUserProfilePath, "stub_wifi2");
    775   }
    776 
    777   void SetONCPolicy(const char* policy_name, policy::PolicyScope scope) {
    778     std::string onc_policy =
    779         "{ \"NetworkConfigurations\": ["
    780         "    { \"GUID\": \"stub_ethernet\","
    781         "      \"Type\": \"Ethernet\","
    782         "      \"Name\": \"My Ethernet\","
    783         "      \"Ethernet\": {"
    784         "        \"Authentication\": \"None\" },"
    785         "      \"ProxySettings\": {"
    786         "        \"PAC\": \"http://domain.com/x\","
    787         "        \"Type\": \"PAC\" }"
    788         "    }"
    789         "  ],"
    790         "  \"Type\": \"UnencryptedConfiguration\""
    791         "}";
    792 
    793     policy::PolicyMap map;
    794     map.Set(policy_name,
    795             policy::POLICY_LEVEL_MANDATORY,
    796             scope,
    797             new base::StringValue(onc_policy),
    798             NULL);
    799     policy_provider_.UpdateChromePolicy(map);
    800 
    801     content::RunAllPendingInMessageLoop();
    802   }
    803 
    804   const chromeos::NetworkState* GetDefaultNetwork() {
    805     return chromeos::NetworkHandler::Get()->network_state_handler()
    806         ->DefaultNetwork();
    807   }
    808 
    809   void SetProxyPref(const std::string& name, const base::Value& value) {
    810     std::string type;
    811     switch (value.GetType()) {
    812       case base::Value::TYPE_BOOLEAN:
    813         type = "Boolean";
    814         break;
    815       case base::Value::TYPE_INTEGER:
    816         type = "Integer";
    817         break;
    818       case base::Value::TYPE_STRING:
    819         type = "String";
    820         break;
    821       default:
    822         ASSERT_TRUE(false);
    823     }
    824 
    825     std::string observed_json;
    826     SetPref(name, type, &value, true, &observed_json);
    827   }
    828 
    829   void VerifyCurrentProxyServer(const std::string& expected_server,
    830                                 chromeos::onc::ONCSource expected_source) {
    831     chromeos::onc::ONCSource actual_source;
    832     scoped_ptr<ProxyConfigDictionary> proxy_dict =
    833         chromeos::proxy_config::GetProxyConfigForNetwork(
    834             pref_service_,
    835             g_browser_process->local_state(),
    836             *GetDefaultNetwork(),
    837             &actual_source);
    838     std::string actual_proxy_server;
    839     EXPECT_TRUE(proxy_dict->GetProxyServer(&actual_proxy_server));
    840     EXPECT_EQ(expected_server, actual_proxy_server);
    841     EXPECT_EQ(expected_source, actual_source);
    842   }
    843 };
    844 
    845 // Verifies that proxy settings are correctly pushed to JavaScript during
    846 // initialization of the proxy settings page.
    847 IN_PROC_BROWSER_TEST_F(ProxyPreferencesBrowserTest, ChromeOSInitializeProxy) {
    848   // Boolean pref.
    849   pref_names_.push_back(chromeos::kProxySingle);
    850   non_default_values_.push_back(new base::FundamentalValue(true));
    851 
    852   // Integer prefs.
    853   pref_names_.push_back(chromeos::kProxySingleHttpPort);
    854   non_default_values_.push_back(new base::FundamentalValue(8080));
    855 
    856   // String pref.
    857   pref_names_.push_back(chromeos::kProxySingleHttp);
    858   non_default_values_.push_back(new base::StringValue("127.0.0.1"));
    859 
    860   // List pref.
    861   pref_names_.push_back(chromeos::kProxyIgnoreList);
    862   base::ListValue* list = new base::ListValue();
    863   list->Append(new base::StringValue("*.google.com"));
    864   list->Append(new base::StringValue("1.2.3.4:22"));
    865   non_default_values_.push_back(list);
    866 
    867   // Verify that no policy is presented to the UI. This must be verified on the
    868   // kProxyType and the kUseSharedProxies prefs.
    869   pref_names_.push_back(chromeos::kProxyType);
    870   non_default_values_.push_back(new base::FundamentalValue(2));
    871 
    872   pref_names_.push_back(prefs::kUseSharedProxies);
    873   non_default_values_.push_back(new base::FundamentalValue(false));
    874 
    875   std::string observed_json;
    876   SetupJavaScriptTestEnvironment(pref_names_, &observed_json);
    877   VerifyObservedPrefs(
    878       observed_json, pref_names_, non_default_values_, "", false, false);
    879 }
    880 
    881 IN_PROC_BROWSER_TEST_F(ProxyPreferencesBrowserTest, ONCPolicy) {
    882   SetONCPolicy(policy::key::kOpenNetworkConfiguration,
    883                policy::POLICY_SCOPE_USER);
    884 
    885   // Verify that per-network policy is presented to the UI. This must be
    886   // verified on the kProxyType.
    887   pref_names_.push_back(chromeos::kProxyType);
    888   non_default_values_.push_back(new base::FundamentalValue(3));
    889 
    890   std::string observed_json;
    891   SetupJavaScriptTestEnvironment(pref_names_, &observed_json);
    892   VerifyObservedPrefs(
    893       observed_json, pref_names_, non_default_values_, "policy", true, false);
    894 
    895   // Verify that 'use-shared-proxies' is not affected by per-network policy.
    896   pref_names_.clear();
    897   STLDeleteElements(&non_default_values_);
    898   pref_names_.push_back(prefs::kUseSharedProxies);
    899   non_default_values_.push_back(new base::FundamentalValue(false));
    900 
    901   SetupJavaScriptTestEnvironment(pref_names_, &observed_json);
    902   VerifyObservedPrefs(
    903       observed_json, pref_names_, non_default_values_, "", false, false);
    904 }
    905 
    906 IN_PROC_BROWSER_TEST_F(ProxyPreferencesBrowserTest, DeviceONCPolicy) {
    907   SetONCPolicy(policy::key::kDeviceOpenNetworkConfiguration,
    908                policy::POLICY_SCOPE_MACHINE);
    909 
    910   // Verify that the policy is presented to the UI. This verification must be
    911   // done on the kProxyType pref.
    912   pref_names_.push_back(chromeos::kProxyType);
    913   non_default_values_.push_back(new base::FundamentalValue(3));
    914 
    915   std::string observed_json;
    916   SetupJavaScriptTestEnvironment(pref_names_, &observed_json);
    917   VerifyObservedPrefs(
    918       observed_json, pref_names_, non_default_values_, "policy", true, false);
    919 
    920   // Verify that 'use-shared-proxies' is not affected by per-network policy.
    921   pref_names_.clear();
    922   STLDeleteElements(&non_default_values_);
    923   pref_names_.push_back(prefs::kUseSharedProxies);
    924   non_default_values_.push_back(new base::FundamentalValue(false));
    925 
    926   SetupJavaScriptTestEnvironment(pref_names_, &observed_json);
    927   VerifyObservedPrefs(
    928       observed_json, pref_names_, non_default_values_, "", false, false);
    929 }
    930 
    931 IN_PROC_BROWSER_TEST_F(ProxyPreferencesBrowserTest, UserProxyPolicy) {
    932   policy_names_.push_back(policy::key::kProxyMode);
    933   default_values_.push_back(
    934       new base::StringValue(ProxyPrefs::kAutoDetectProxyModeName));
    935   SetUserPolicies(
    936       policy_names_, default_values_, policy::POLICY_LEVEL_MANDATORY);
    937   content::RunAllPendingInMessageLoop();
    938 
    939   // Verify that the policy is presented to the UI. This verification must be
    940   // done on the kProxyType pref.
    941   pref_names_.push_back(chromeos::kProxyType);
    942   non_default_values_.push_back(new base::FundamentalValue(3));
    943 
    944   // Verify that 'use-shared-proxies' is controlled by the policy.
    945   pref_names_.push_back(prefs::kUseSharedProxies);
    946   non_default_values_.push_back(new base::FundamentalValue(false));
    947 
    948   std::string observed_json;
    949   SetupJavaScriptTestEnvironment(pref_names_, &observed_json);
    950   VerifyObservedPrefs(
    951       observed_json, pref_names_, non_default_values_, "policy", true, false);
    952 }
    953 
    954 // Verifies that modifications to the proxy settings are correctly pushed from
    955 // JavaScript to the ProxyConfig property stored in the network configuration.
    956 IN_PROC_BROWSER_TEST_F(ProxyPreferencesBrowserTest, ChromeOSSetProxy) {
    957   ASSERT_NO_FATAL_FAILURE(SetupJavaScriptTestEnvironment(pref_names_, NULL));
    958 
    959   SetProxyPref(chromeos::kProxySingleHttpPort, base::FundamentalValue(123));
    960   SetProxyPref(chromeos::kProxySingleHttp, base::StringValue("www.adomain.xy"));
    961 
    962   VerifyCurrentProxyServer("www.adomain.xy:123",
    963                            chromeos::onc::ONC_SOURCE_NONE);
    964 }
    965 
    966 // Verify that default proxy ports are used and that ports can be updated
    967 // without affecting the previously set hosts.
    968 IN_PROC_BROWSER_TEST_F(ProxyPreferencesBrowserTest, ChromeOSProxyDefaultPorts) {
    969   ASSERT_NO_FATAL_FAILURE(SetupJavaScriptTestEnvironment(pref_names_, NULL));
    970 
    971   // Set to manual, per scheme proxy.
    972   SetProxyPref(chromeos::kProxySingle, base::FundamentalValue(false));
    973 
    974   // Set hosts but no ports.
    975   SetProxyPref(chromeos::kProxyHttpUrl, base::StringValue("a.com"));
    976   SetProxyPref(chromeos::kProxyHttpsUrl, base::StringValue("4.3.2.1"));
    977   SetProxyPref(chromeos::kProxyFtpUrl, base::StringValue("c.com"));
    978   SetProxyPref(chromeos::kProxySocks, base::StringValue("d.com"));
    979 
    980   // Verify default ports.
    981   VerifyCurrentProxyServer(
    982       "http=a.com:80;https=4.3.2.1:80;ftp=c.com:80;socks=socks4://d.com:1080",
    983       chromeos::onc::ONC_SOURCE_NONE);
    984 
    985   // Set and verify the ports.
    986   SetProxyPref(chromeos::kProxyHttpPort, base::FundamentalValue(1));
    987   SetProxyPref(chromeos::kProxyHttpsPort, base::FundamentalValue(2));
    988   SetProxyPref(chromeos::kProxyFtpPort, base::FundamentalValue(3));
    989   SetProxyPref(chromeos::kProxySocksPort, base::FundamentalValue(4));
    990 
    991   VerifyCurrentProxyServer(
    992       "http=a.com:1;https=4.3.2.1:2;ftp=c.com:3;socks=socks4://d.com:4",
    993       chromeos::onc::ONC_SOURCE_NONE);
    994 }
    995 
    996 #endif
    997