Home | History | Annotate | Download | only in policy
      1 // Copyright (c) 2013 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 <map>
      6 #include <set>
      7 #include <string>
      8 #include <vector>
      9 
     10 #include "ash/shell.h"
     11 #include "ash/system/chromeos/session/logout_confirmation_controller.h"
     12 #include "ash/system/chromeos/session/logout_confirmation_dialog.h"
     13 #include "base/basictypes.h"
     14 #include "base/bind.h"
     15 #include "base/bind_helpers.h"
     16 #include "base/callback.h"
     17 #include "base/command_line.h"
     18 #include "base/files/file_path.h"
     19 #include "base/files/file_util.h"
     20 #include "base/json/json_reader.h"
     21 #include "base/json/json_writer.h"
     22 #include "base/location.h"
     23 #include "base/macros.h"
     24 #include "base/memory/ref_counted.h"
     25 #include "base/memory/scoped_ptr.h"
     26 #include "base/message_loop/message_loop.h"
     27 #include "base/message_loop/message_loop_proxy.h"
     28 #include "base/path_service.h"
     29 #include "base/prefs/pref_change_registrar.h"
     30 #include "base/prefs/pref_service.h"
     31 #include "base/run_loop.h"
     32 #include "base/sequenced_task_runner.h"
     33 #include "base/strings/string_number_conversions.h"
     34 #include "base/strings/string_util.h"
     35 #include "base/strings/stringprintf.h"
     36 #include "base/strings/utf_string_conversions.h"
     37 #include "base/threading/sequenced_worker_pool.h"
     38 #include "base/values.h"
     39 #include "chrome/browser/browser_process.h"
     40 #include "chrome/browser/chrome_notification_types.h"
     41 #include "chrome/browser/chromeos/extensions/device_local_account_external_policy_loader.h"
     42 #include "chrome/browser/chromeos/extensions/external_cache.h"
     43 #include "chrome/browser/chromeos/input_method/input_method_util.h"
     44 #include "chrome/browser/chromeos/login/existing_user_controller.h"
     45 #include "chrome/browser/chromeos/login/screens/wizard_screen.h"
     46 #include "chrome/browser/chromeos/login/ui/login_display_host.h"
     47 #include "chrome/browser/chromeos/login/ui/login_display_host_impl.h"
     48 #include "chrome/browser/chromeos/login/ui/webui_login_view.h"
     49 #include "chrome/browser/chromeos/login/users/avatar/user_image_manager.h"
     50 #include "chrome/browser/chromeos/login/users/avatar/user_image_manager_impl.h"
     51 #include "chrome/browser/chromeos/login/users/avatar/user_image_manager_test_util.h"
     52 #include "chrome/browser/chromeos/login/users/chrome_user_manager_impl.h"
     53 #include "chrome/browser/chromeos/login/wizard_controller.h"
     54 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
     55 #include "chrome/browser/chromeos/policy/cloud_external_data_manager_base_test_util.h"
     56 #include "chrome/browser/chromeos/policy/device_local_account.h"
     57 #include "chrome/browser/chromeos/policy/device_local_account_policy_service.h"
     58 #include "chrome/browser/chromeos/policy/device_policy_builder.h"
     59 #include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h"
     60 #include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h"
     61 #include "chrome/browser/extensions/crx_installer.h"
     62 #include "chrome/browser/extensions/extension_service.h"
     63 #include "chrome/browser/lifetime/application_lifetime.h"
     64 #include "chrome/browser/policy/profile_policy_connector.h"
     65 #include "chrome/browser/policy/profile_policy_connector_factory.h"
     66 #include "chrome/browser/policy/test/local_policy_test_server.h"
     67 #include "chrome/browser/prefs/session_startup_pref.h"
     68 #include "chrome/browser/profiles/profile.h"
     69 #include "chrome/browser/profiles/profile_manager.h"
     70 #include "chrome/browser/ui/browser.h"
     71 #include "chrome/browser/ui/browser_commands.h"
     72 #include "chrome/browser/ui/browser_finder.h"
     73 #include "chrome/browser/ui/browser_list.h"
     74 #include "chrome/browser/ui/browser_list_observer.h"
     75 #include "chrome/browser/ui/browser_window.h"
     76 #include "chrome/browser/ui/extensions/application_launch.h"
     77 #include "chrome/browser/ui/host_desktop.h"
     78 #include "chrome/browser/ui/tabs/tab_strip_model.h"
     79 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
     80 #include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h"
     81 #include "chrome/common/chrome_paths.h"
     82 #include "chrome/common/extensions/extension_constants.h"
     83 #include "chrome/grit/chromium_strings.h"
     84 #include "chrome/grit/generated_resources.h"
     85 #include "chromeos/chromeos_paths.h"
     86 #include "chromeos/chromeos_switches.h"
     87 #include "chromeos/dbus/fake_session_manager_client.h"
     88 #include "chromeos/ime/extension_ime_util.h"
     89 #include "chromeos/ime/input_method_descriptor.h"
     90 #include "chromeos/ime/input_method_manager.h"
     91 #include "chromeos/login/auth/mock_auth_status_consumer.h"
     92 #include "chromeos/login/auth/user_context.h"
     93 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
     94 #include "components/policy/core/common/cloud/cloud_policy_core.h"
     95 #include "components/policy/core/common/cloud/cloud_policy_store.h"
     96 #include "components/policy/core/common/cloud/policy_builder.h"
     97 #include "components/policy/core/common/external_data_fetcher.h"
     98 #include "components/policy/core/common/policy_map.h"
     99 #include "components/policy/core/common/policy_namespace.h"
    100 #include "components/policy/core/common/policy_service.h"
    101 #include "components/policy/core/common/policy_switches.h"
    102 #include "components/signin/core/common/signin_pref_names.h"
    103 #include "components/user_manager/user.h"
    104 #include "components/user_manager/user_manager.h"
    105 #include "components/user_manager/user_type.h"
    106 #include "content/public/browser/browser_thread.h"
    107 #include "content/public/browser/notification_details.h"
    108 #include "content/public/browser/notification_service.h"
    109 #include "content/public/browser/notification_source.h"
    110 #include "content/public/browser/web_contents.h"
    111 #include "content/public/browser/web_ui.h"
    112 #include "content/public/test/browser_test_utils.h"
    113 #include "content/public/test/test_utils.h"
    114 #include "crypto/rsa_private_key.h"
    115 #include "extensions/browser/app_window/app_window.h"
    116 #include "extensions/browser/app_window/app_window_registry.h"
    117 #include "extensions/browser/app_window/native_app_window.h"
    118 #include "extensions/browser/extension_system.h"
    119 #include "extensions/browser/management_policy.h"
    120 #include "extensions/browser/notification_types.h"
    121 #include "extensions/common/extension.h"
    122 #include "net/base/url_util.h"
    123 #include "net/http/http_status_code.h"
    124 #include "net/test/embedded_test_server/embedded_test_server.h"
    125 #include "net/test/embedded_test_server/http_request.h"
    126 #include "net/test/embedded_test_server/http_response.h"
    127 #include "net/url_request/test_url_fetcher_factory.h"
    128 #include "net/url_request/url_fetcher_delegate.h"
    129 #include "net/url_request/url_request_status.h"
    130 #include "policy/policy_constants.h"
    131 #include "testing/gmock/include/gmock/gmock.h"
    132 #include "third_party/icu/source/common/unicode/locid.h"
    133 #include "ui/base/l10n/l10n_util.h"
    134 #include "ui/base/window_open_disposition.h"
    135 #include "ui/gfx/image/image_skia.h"
    136 #include "ui/views/widget/widget.h"
    137 #include "url/gurl.h"
    138 
    139 namespace em = enterprise_management;
    140 
    141 using chromeos::LoginScreenContext;
    142 using testing::InvokeWithoutArgs;
    143 using testing::Return;
    144 using testing::_;
    145 
    146 namespace policy {
    147 
    148 namespace {
    149 
    150 const char kDomain[] = "example.com";
    151 const char kAccountId1[] = "dla1 (at) example.com";
    152 const char kAccountId2[] = "dla2 (at) example.com";
    153 const char kDisplayName1[] = "display name 1";
    154 const char kDisplayName2[] = "display name 2";
    155 const char* kStartupURLs[] = {
    156   "chrome://policy",
    157   "chrome://about",
    158 };
    159 const char kExistentTermsOfServicePath[] = "chromeos/enterprise/tos.txt";
    160 const char kNonexistentTermsOfServicePath[] = "chromeos/enterprise/tos404.txt";
    161 const char kRelativeUpdateURL[] = "/service/update2/crx";
    162 const char kUpdateManifestHeader[] =
    163     "<?xml version='1.0' encoding='UTF-8'?>\n"
    164     "<gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'>\n";
    165 const char kUpdateManifestTemplate[] =
    166     "  <app appid='%s'>\n"
    167     "    <updatecheck codebase='%s' version='%s' />\n"
    168     "  </app>\n";
    169 const char kUpdateManifestFooter[] =
    170     "</gupdate>\n";
    171 const char kHostedAppID[] = "kbmnembihfiondgfjekmnmcbddelicoi";
    172 const char kHostedAppCRXPath[] = "extensions/hosted_app.crx";
    173 const char kHostedAppVersion[] = "1.0.0.0";
    174 const char kGoodExtensionID[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf";
    175 const char kGoodExtensionCRXPath[] = "extensions/good.crx";
    176 const char kGoodExtensionVersion[] = "1.0";
    177 const char kPackagedAppCRXPath[] = "extensions/platform_apps/app_window_2.crx";
    178 
    179 const char kExternalData[] = "External data";
    180 const char kExternalDataURL[] = "http://localhost/external_data";
    181 
    182 const char* kSingleRecommendedLocale[] = {
    183   "el",
    184 };
    185 const char* kRecommendedLocales1[] = {
    186   "pl",
    187   "et",
    188   "en-US",
    189 };
    190 const char* kRecommendedLocales2[] = {
    191   "fr",
    192   "nl",
    193 };
    194 const char* kInvalidRecommendedLocale[] = {
    195   "xx",
    196 };
    197 const char kPublicSessionLocale[] = "de";
    198 const char kPublicSessionInputMethodIDTemplate[] = "_comp_ime_%sxkb:de:neo:ger";
    199 
    200 // The sequence token used by GetKeyboardLayoutsForLocale() for its background
    201 // tasks.
    202 const char kSequenceToken[] = "chromeos_login_l10n_util";
    203 
    204 // Helper that serves extension update manifests to Chrome.
    205 class TestingUpdateManifestProvider {
    206  public:
    207   // Update manifests will be served at |relative_update_url|.
    208   explicit TestingUpdateManifestProvider(
    209       const std::string& relative_update_url);
    210   ~TestingUpdateManifestProvider();
    211 
    212   // When an update manifest is requested for the given extension |id|, indicate
    213   // that |version| of the extension can be downloaded at |crx_url|.
    214   void AddUpdate(const std::string& id,
    215                  const std::string& version,
    216                  const GURL& crx_url);
    217 
    218   // This method must be registered with the test's EmbeddedTestServer to start
    219   // serving update manifests.
    220   scoped_ptr<net::test_server::HttpResponse> HandleRequest(
    221       const net::test_server::HttpRequest& request);
    222 
    223  private:
    224   struct Update {
    225    public:
    226     Update(const std::string& version, const GURL& crx_url);
    227     Update();
    228 
    229     std::string version;
    230     GURL crx_url;
    231   };
    232   typedef std::map<std::string, Update> UpdateMap;
    233   UpdateMap updates_;
    234 
    235   const std::string relative_update_url_;
    236 
    237   DISALLOW_COPY_AND_ASSIGN(TestingUpdateManifestProvider);
    238 };
    239 
    240 // Helper that observes the dictionary |pref| in local state and waits until the
    241 // value stored for |key| matches |expected_value|.
    242 class DictionaryPrefValueWaiter {
    243  public:
    244   DictionaryPrefValueWaiter(const std::string& pref,
    245                             const std::string& key,
    246                             const std::string& expected_value);
    247   ~DictionaryPrefValueWaiter();
    248 
    249   void Wait();
    250 
    251  private:
    252   void QuitLoopIfExpectedValueFound();
    253 
    254   const std::string pref_;
    255   const std::string key_;
    256   const std::string expected_value_;
    257 
    258   base::RunLoop run_loop_;
    259   PrefChangeRegistrar pref_change_registrar_;
    260 
    261   DISALLOW_COPY_AND_ASSIGN(DictionaryPrefValueWaiter);
    262 };
    263 
    264 TestingUpdateManifestProvider::Update::Update(const std::string& version,
    265                                               const GURL& crx_url)
    266     : version(version),
    267       crx_url(crx_url) {
    268 }
    269 
    270 TestingUpdateManifestProvider::Update::Update() {
    271 }
    272 
    273 TestingUpdateManifestProvider::TestingUpdateManifestProvider(
    274     const std::string& relative_update_url)
    275     : relative_update_url_(relative_update_url) {
    276 }
    277 
    278 TestingUpdateManifestProvider::~TestingUpdateManifestProvider() {
    279 }
    280 
    281 void TestingUpdateManifestProvider::AddUpdate(const std::string& id,
    282                                               const std::string& version,
    283                                               const GURL& crx_url) {
    284   updates_[id] = Update(version, crx_url);
    285 }
    286 
    287 scoped_ptr<net::test_server::HttpResponse>
    288     TestingUpdateManifestProvider::HandleRequest(
    289         const net::test_server::HttpRequest& request) {
    290   const GURL url("http://localhost" + request.relative_url);
    291   if (url.path() != relative_update_url_)
    292     return scoped_ptr<net::test_server::HttpResponse>();
    293 
    294   std::string content = kUpdateManifestHeader;
    295   for (net::QueryIterator it(url); !it.IsAtEnd(); it.Advance()) {
    296     if (it.GetKey() != "x")
    297       continue;
    298     // Extract the extension id from the subquery. Since GetValueForKeyInQuery()
    299     // expects a complete URL, dummy scheme and host must be prepended.
    300     std::string id;
    301     net::GetValueForKeyInQuery(GURL("http://dummy?" + it.GetUnescapedValue()),
    302                                "id", &id);
    303     UpdateMap::const_iterator entry = updates_.find(id);
    304     if (entry != updates_.end()) {
    305       content += base::StringPrintf(kUpdateManifestTemplate,
    306                                     id.c_str(),
    307                                     entry->second.crx_url.spec().c_str(),
    308                                     entry->second.version.c_str());
    309     }
    310   }
    311   content += kUpdateManifestFooter;
    312   scoped_ptr<net::test_server::BasicHttpResponse>
    313       http_response(new net::test_server::BasicHttpResponse);
    314   http_response->set_code(net::HTTP_OK);
    315   http_response->set_content(content);
    316   http_response->set_content_type("text/xml");
    317   return http_response.PassAs<net::test_server::HttpResponse>();
    318 }
    319 
    320 DictionaryPrefValueWaiter::DictionaryPrefValueWaiter(
    321     const std::string& pref,
    322     const std::string& key,
    323     const std::string& expected_value)
    324     : pref_(pref),
    325       key_(key),
    326       expected_value_(expected_value) {
    327   pref_change_registrar_.Init(g_browser_process->local_state());
    328 }
    329 
    330 DictionaryPrefValueWaiter::~DictionaryPrefValueWaiter() {
    331 }
    332 
    333 void DictionaryPrefValueWaiter::Wait() {
    334   pref_change_registrar_.Add(
    335       pref_.c_str(),
    336       base::Bind(&DictionaryPrefValueWaiter::QuitLoopIfExpectedValueFound,
    337                  base::Unretained(this)));
    338   QuitLoopIfExpectedValueFound();
    339   run_loop_.Run();
    340 }
    341 
    342 void DictionaryPrefValueWaiter::QuitLoopIfExpectedValueFound() {
    343   const base::DictionaryValue* pref =
    344       pref_change_registrar_.prefs()->GetDictionary(pref_.c_str());
    345   ASSERT_TRUE(pref);
    346   std::string actual_value;
    347   if (pref->GetStringWithoutPathExpansion(key_, &actual_value) &&
    348       actual_value == expected_value_) {
    349     run_loop_.Quit();
    350   }
    351 }
    352 
    353 bool DoesInstallSuccessReferToId(const std::string& id,
    354                                  const content::NotificationSource& source,
    355                                  const content::NotificationDetails& details) {
    356   return content::Details<const extensions::InstalledExtensionInfo>(details)->
    357       extension->id() == id;
    358 }
    359 
    360 bool DoesInstallFailureReferToId(const std::string& id,
    361                                  const content::NotificationSource& source,
    362                                  const content::NotificationDetails& details) {
    363   return content::Details<const base::string16>(details)->
    364       find(base::UTF8ToUTF16(id)) != base::string16::npos;
    365 }
    366 
    367 scoped_ptr<net::FakeURLFetcher> RunCallbackAndReturnFakeURLFetcher(
    368     scoped_refptr<base::SequencedTaskRunner> task_runner,
    369     const base::Closure& callback,
    370     const GURL& url,
    371     net::URLFetcherDelegate* delegate,
    372     const std::string& response_data,
    373     net::HttpStatusCode response_code,
    374     net::URLRequestStatus::Status status) {
    375   task_runner->PostTask(FROM_HERE, callback);
    376   return make_scoped_ptr(new net::FakeURLFetcher(
    377       url, delegate, response_data, response_code, status));
    378 }
    379 
    380 bool IsSessionStarted() {
    381   return user_manager::UserManager::Get()->IsSessionStarted();
    382 }
    383 
    384 }  // namespace
    385 
    386 class DeviceLocalAccountTest : public DevicePolicyCrosBrowserTest,
    387                                public user_manager::UserManager::Observer,
    388                                public chrome::BrowserListObserver,
    389                                public extensions::AppWindowRegistry::Observer {
    390  protected:
    391   DeviceLocalAccountTest()
    392       : user_id_1_(GenerateDeviceLocalAccountUserId(
    393             kAccountId1, DeviceLocalAccount::TYPE_PUBLIC_SESSION)),
    394         user_id_2_(GenerateDeviceLocalAccountUserId(
    395             kAccountId2, DeviceLocalAccount::TYPE_PUBLIC_SESSION)),
    396         public_session_input_method_id_(base::StringPrintf(
    397             kPublicSessionInputMethodIDTemplate,
    398             chromeos::extension_ime_util::kXkbExtensionId)),
    399         contents_(NULL) {
    400     set_exit_when_last_browser_closes(false);
    401   }
    402 
    403   virtual ~DeviceLocalAccountTest() {}
    404 
    405   virtual void SetUp() OVERRIDE {
    406     // Configure and start the test server.
    407     scoped_ptr<crypto::RSAPrivateKey> signing_key(
    408         PolicyBuilder::CreateTestSigningKey());
    409     ASSERT_TRUE(test_server_.SetSigningKeyAndSignature(
    410         signing_key.get(), PolicyBuilder::GetTestSigningKeySignature()));
    411     signing_key.reset();
    412     test_server_.RegisterClient(PolicyBuilder::kFakeToken,
    413                                 PolicyBuilder::kFakeDeviceId);
    414     ASSERT_TRUE(test_server_.Start());
    415 
    416     BrowserList::AddObserver(this);
    417 
    418     DevicePolicyCrosBrowserTest::SetUp();
    419   }
    420 
    421   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
    422     DevicePolicyCrosBrowserTest::SetUpCommandLine(command_line);
    423     command_line->AppendSwitch(chromeos::switches::kLoginManager);
    424     command_line->AppendSwitch(chromeos::switches::kForceLoginManagerInTests);
    425     command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile, "user");
    426     command_line->AppendSwitchASCII(policy::switches::kDeviceManagementUrl,
    427                                     test_server_.GetServiceURL().spec());
    428   }
    429 
    430   virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
    431     DevicePolicyCrosBrowserTest::SetUpInProcessBrowserTestFixture();
    432 
    433     // Clear command-line arguments (but keep command-line switches) so the
    434     // startup pages policy takes effect.
    435     CommandLine* command_line = CommandLine::ForCurrentProcess();
    436     CommandLine::StringVector argv(command_line->argv());
    437     argv.erase(argv.begin() + argv.size() - command_line->GetArgs().size(),
    438                argv.end());
    439     command_line->InitFromArgv(argv);
    440 
    441     InstallOwnerKey();
    442     MarkAsEnterpriseOwned();
    443 
    444     InitializePolicy();
    445   }
    446 
    447   virtual void SetUpOnMainThread() OVERRIDE {
    448     DevicePolicyCrosBrowserTest::SetUpOnMainThread();
    449 
    450     initial_locale_ = g_browser_process->GetApplicationLocale();
    451     initial_language_ = l10n_util::GetLanguage(initial_locale_);
    452 
    453     content::WindowedNotificationObserver(
    454         chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
    455         content::NotificationService::AllSources()).Wait();
    456 
    457     chromeos::LoginDisplayHostImpl* host =
    458         reinterpret_cast<chromeos::LoginDisplayHostImpl*>(
    459             chromeos::LoginDisplayHostImpl::default_host());
    460     ASSERT_TRUE(host);
    461     chromeos::WebUILoginView* web_ui_login_view = host->GetWebUILoginView();
    462     ASSERT_TRUE(web_ui_login_view);
    463     content::WebUI* web_ui = web_ui_login_view->GetWebUI();
    464     ASSERT_TRUE(web_ui);
    465     contents_ = web_ui->GetWebContents();
    466     ASSERT_TRUE(contents_);
    467 
    468     // Wait for the login UI to be ready.
    469     chromeos::OobeUI* oobe_ui = host->GetOobeUI();
    470     ASSERT_TRUE(oobe_ui);
    471     base::RunLoop run_loop;
    472     const bool oobe_ui_ready = oobe_ui->IsJSReady(run_loop.QuitClosure());
    473     if (!oobe_ui_ready)
    474       run_loop.Run();
    475 
    476     // The network selection screen changes the application locale on load and
    477     // once again on blur. Wait for the screen to load and blur it so that any
    478     // locale changes caused by this screen happen now and do not affect any
    479     // subsequent parts of the test.
    480     bool done = false;
    481     ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
    482         contents_,
    483         "var languageSelect = document.getElementById('language-select');"
    484         "var blurAndReportSuccess = function() {"
    485         "  languageSelect.blur();"
    486         "  domAutomationController.send(true);"
    487         "};"
    488         "var screenLoading = document.getElementById('outer-container')"
    489         "    .classList.contains('down');"
    490         "if (document.activeElement == languageSelect || !screenLoading)"
    491         "  blurAndReportSuccess();"
    492         "else"
    493         "  languageSelect.addEventListener('focus', blurAndReportSuccess);",
    494         &done));
    495 
    496     // Skip to the login screen.
    497     chromeos::WizardController* wizard_controller =
    498         chromeos::WizardController::default_controller();
    499     ASSERT_TRUE(wizard_controller);
    500     wizard_controller->SkipToLoginForTesting(LoginScreenContext());
    501   }
    502 
    503   virtual void TearDownOnMainThread() OVERRIDE {
    504     BrowserList::RemoveObserver(this);
    505 
    506     // This shuts down the login UI.
    507     base::MessageLoop::current()->PostTask(FROM_HERE,
    508                                            base::Bind(&chrome::AttemptExit));
    509     base::RunLoop().RunUntilIdle();
    510   }
    511 
    512   virtual void LocalStateChanged(
    513       user_manager::UserManager* user_manager) OVERRIDE {
    514     if (run_loop_)
    515       run_loop_->Quit();
    516   }
    517 
    518   virtual void OnBrowserRemoved(Browser* browser) OVERRIDE {
    519     if (run_loop_)
    520       run_loop_->Quit();
    521   }
    522 
    523   virtual void OnAppWindowAdded(extensions::AppWindow* app_window) OVERRIDE {
    524     if (run_loop_)
    525       run_loop_->Quit();
    526   }
    527 
    528   virtual void OnAppWindowRemoved(extensions::AppWindow* app_window) OVERRIDE {
    529     if (run_loop_)
    530       run_loop_->Quit();
    531   }
    532 
    533   void InitializePolicy() {
    534     device_policy()->policy_data().set_public_key_version(1);
    535     em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
    536     proto.mutable_show_user_names()->set_show_user_names(true);
    537 
    538     device_local_account_policy_.policy_data().set_policy_type(
    539         dm_protocol::kChromePublicAccountPolicyType);
    540     device_local_account_policy_.policy_data().set_username(kAccountId1);
    541     device_local_account_policy_.policy_data().set_settings_entity_id(
    542         kAccountId1);
    543     device_local_account_policy_.policy_data().set_public_key_version(1);
    544     device_local_account_policy_.payload().mutable_userdisplayname()->set_value(
    545         kDisplayName1);
    546   }
    547 
    548   void BuildDeviceLocalAccountPolicy() {
    549     device_local_account_policy_.SetDefaultSigningKey();
    550     device_local_account_policy_.Build();
    551   }
    552 
    553   void UploadDeviceLocalAccountPolicy() {
    554     BuildDeviceLocalAccountPolicy();
    555     test_server_.UpdatePolicy(
    556         dm_protocol::kChromePublicAccountPolicyType, kAccountId1,
    557         device_local_account_policy_.payload().SerializeAsString());
    558   }
    559 
    560   void UploadAndInstallDeviceLocalAccountPolicy() {
    561     UploadDeviceLocalAccountPolicy();
    562     session_manager_client()->set_device_local_account_policy(
    563         kAccountId1, device_local_account_policy_.GetBlob());
    564   }
    565 
    566   void SetRecommendedLocales(const char* recommended_locales[],
    567                              size_t array_size) {
    568     em::StringListPolicyProto* session_locales_proto =
    569         device_local_account_policy_.payload().mutable_sessionlocales();
    570      session_locales_proto->mutable_policy_options()->set_mode(
    571         em::PolicyOptions_PolicyMode_RECOMMENDED);
    572     session_locales_proto->mutable_value()->Clear();
    573     for (size_t i = 0; i < array_size; ++i) {
    574       session_locales_proto->mutable_value()->add_entries(
    575           recommended_locales[i]);
    576     }
    577   }
    578 
    579   void AddPublicSessionToDevicePolicy(const std::string& username) {
    580     em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
    581     em::DeviceLocalAccountInfoProto* account =
    582         proto.mutable_device_local_accounts()->add_account();
    583     account->set_account_id(username);
    584     account->set_type(
    585         em::DeviceLocalAccountInfoProto::ACCOUNT_TYPE_PUBLIC_SESSION);
    586     RefreshDevicePolicy();
    587     test_server_.UpdatePolicy(dm_protocol::kChromeDevicePolicyType,
    588                               std::string(), proto.SerializeAsString());
    589   }
    590 
    591   void EnableAutoLogin() {
    592     em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
    593     em::DeviceLocalAccountsProto* device_local_accounts =
    594         proto.mutable_device_local_accounts();
    595     device_local_accounts->set_auto_login_id(kAccountId1);
    596     device_local_accounts->set_auto_login_delay(0);
    597     RefreshDevicePolicy();
    598     test_server_.UpdatePolicy(dm_protocol::kChromeDevicePolicyType,
    599                               std::string(), proto.SerializeAsString());
    600   }
    601 
    602   void CheckPublicSessionPresent(const std::string& id) {
    603     const user_manager::User* user =
    604         user_manager::UserManager::Get()->FindUser(id);
    605     ASSERT_TRUE(user);
    606     EXPECT_EQ(id, user->email());
    607     EXPECT_EQ(user_manager::USER_TYPE_PUBLIC_ACCOUNT, user->GetType());
    608   }
    609 
    610   base::FilePath GetExtensionCacheDirectoryForAccountID(
    611       const std::string& account_id) {
    612     base::FilePath extension_cache_root_dir;
    613     if (!PathService::Get(chromeos::DIR_DEVICE_LOCAL_ACCOUNT_EXTENSIONS,
    614                           &extension_cache_root_dir)) {
    615       ADD_FAILURE();
    616     }
    617     return extension_cache_root_dir.Append(
    618         base::HexEncode(account_id.c_str(), account_id.size()));
    619   }
    620 
    621   base::FilePath GetCacheCRXFile(const std::string& account_id,
    622                                  const std::string& id,
    623                                  const std::string& version) {
    624     return GetExtensionCacheDirectoryForAccountID(account_id)
    625         .Append(base::StringPrintf("%s-%s.crx", id.c_str(), version.c_str()));
    626   }
    627 
    628   // Returns a profile which can be used for testing.
    629   Profile* GetProfileForTest() {
    630     // Any profile can be used here since this test does not test multi profile.
    631     return ProfileManager::GetActiveUserProfile();
    632   }
    633 
    634   void WaitForDisplayName(const std::string& user_id,
    635                           const std::string& expected_display_name) {
    636     DictionaryPrefValueWaiter("UserDisplayName",
    637                               user_id,
    638                               expected_display_name).Wait();
    639   }
    640 
    641   void WaitForPolicy() {
    642     // Wait for the display name becoming available as that indicates
    643     // device-local account policy is fully loaded, which is a prerequisite for
    644     // successful login.
    645     WaitForDisplayName(user_id_1_, kDisplayName1);
    646   }
    647 
    648   void ExpandPublicSessionPod(bool expect_advanced) {
    649     bool advanced = false;
    650     // Click on the pod to expand it.
    651     ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
    652         contents_,
    653         base::StringPrintf(
    654             "var pod ="
    655             "    document.getElementById('pod-row').getPodWithUsername_('%s');"
    656             "pod.click();"
    657             "domAutomationController.send(pod.classList.contains('advanced'));",
    658             user_id_1_.c_str()),
    659         &advanced));
    660     // Verify that the pod expanded to its basic/advanced form, as expected.
    661     EXPECT_EQ(expect_advanced, advanced);
    662 
    663     // Verify that the construction of the pod's language list did not affect
    664     // the current ICU locale.
    665     EXPECT_EQ(initial_language_, icu::Locale::getDefault().getLanguage());
    666   }
    667 
    668   // GetKeyboardLayoutsForLocale() posts a task to a background task runner.
    669   // This method flushes that task runner and the current thread's message loop
    670   // to ensure that GetKeyboardLayoutsForLocale() is finished.
    671   void WaitForGetKeyboardLayoutsForLocaleToFinish() {
    672     base::SequencedWorkerPool* worker_pool =
    673         content::BrowserThread::GetBlockingPool();
    674      scoped_refptr<base::SequencedTaskRunner> background_task_runner =
    675          worker_pool->GetSequencedTaskRunner(
    676              worker_pool->GetNamedSequenceToken(kSequenceToken));
    677     base::RunLoop run_loop;
    678     background_task_runner->PostTaskAndReply(FROM_HERE,
    679                                              base::Bind(&base::DoNothing),
    680                                              run_loop.QuitClosure());
    681     run_loop.Run();
    682     base::RunLoop().RunUntilIdle();
    683 
    684     // Verify that the construction of the keyboard layout list did not affect
    685     // the current ICU locale.
    686     EXPECT_EQ(initial_language_, icu::Locale::getDefault().getLanguage());
    687   }
    688 
    689   void StartLogin(const std::string& locale,
    690                   const std::string& input_method) {
    691     // Start login into the device-local account.
    692     chromeos::LoginDisplayHostImpl* host =
    693         reinterpret_cast<chromeos::LoginDisplayHostImpl*>(
    694             chromeos::LoginDisplayHostImpl::default_host());
    695     ASSERT_TRUE(host);
    696     host->StartSignInScreen(LoginScreenContext());
    697     chromeos::ExistingUserController* controller =
    698         chromeos::ExistingUserController::current_controller();
    699     ASSERT_TRUE(controller);
    700 
    701     chromeos::UserContext user_context(user_manager::USER_TYPE_PUBLIC_ACCOUNT,
    702                                        user_id_1_);
    703     user_context.SetPublicSessionLocale(locale);
    704     user_context.SetPublicSessionInputMethod(input_method);
    705     controller->LoginAsPublicSession(user_context);
    706   }
    707 
    708   void WaitForSessionStart() {
    709     if (IsSessionStarted())
    710       return;
    711     content::WindowedNotificationObserver(chrome::NOTIFICATION_SESSION_STARTED,
    712                                           base::Bind(IsSessionStarted)).Wait();
    713   }
    714 
    715   void VerifyKeyboardLayoutMatchesLocale() {
    716     chromeos::input_method::InputMethodManager* input_method_manager =
    717         chromeos::input_method::InputMethodManager::Get();
    718     std::vector<std::string> layouts_from_locale;
    719     input_method_manager->GetInputMethodUtil()->
    720         GetInputMethodIdsFromLanguageCode(
    721             g_browser_process->GetApplicationLocale(),
    722             chromeos::input_method::kKeyboardLayoutsOnly,
    723             &layouts_from_locale);
    724     ASSERT_FALSE(layouts_from_locale.empty());
    725     EXPECT_EQ(layouts_from_locale.front(),
    726               input_method_manager->GetActiveIMEState()
    727                   ->GetCurrentInputMethod()
    728                   .id());
    729   }
    730 
    731   const std::string user_id_1_;
    732   const std::string user_id_2_;
    733   const std::string public_session_input_method_id_;
    734 
    735   std::string initial_locale_;
    736   std::string initial_language_;
    737 
    738   scoped_ptr<base::RunLoop> run_loop_;
    739 
    740   UserPolicyBuilder device_local_account_policy_;
    741   LocalPolicyTestServer test_server_;
    742 
    743   content::WebContents* contents_;
    744 
    745  private:
    746   DISALLOW_COPY_AND_ASSIGN(DeviceLocalAccountTest);
    747 };
    748 
    749 static bool IsKnownUser(const std::string& account_id) {
    750   return user_manager::UserManager::Get()->IsKnownUser(account_id);
    751 }
    752 
    753 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, LoginScreen) {
    754   AddPublicSessionToDevicePolicy(kAccountId1);
    755   AddPublicSessionToDevicePolicy(kAccountId2);
    756 
    757   content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED,
    758                                         base::Bind(&IsKnownUser, user_id_1_))
    759       .Wait();
    760   EXPECT_TRUE(IsKnownUser(user_id_2_));
    761 
    762   CheckPublicSessionPresent(user_id_1_);
    763   CheckPublicSessionPresent(user_id_2_);
    764 }
    765 
    766 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, DisplayName) {
    767   UploadAndInstallDeviceLocalAccountPolicy();
    768   AddPublicSessionToDevicePolicy(kAccountId1);
    769 
    770   WaitForPolicy();
    771 
    772   // Verify that the display name is shown in the UI.
    773   const std::string get_compact_pod_display_name = base::StringPrintf(
    774       "domAutomationController.send(document.getElementById('pod-row')"
    775       "    .getPodWithUsername_('%s').nameElement.textContent);",
    776       user_id_1_.c_str());
    777   std::string display_name;
    778   ASSERT_TRUE(content::ExecuteScriptAndExtractString(
    779       contents_,
    780       get_compact_pod_display_name,
    781       &display_name));
    782   EXPECT_EQ(kDisplayName1, display_name);
    783   const std::string get_expanded_pod_display_name = base::StringPrintf(
    784       "domAutomationController.send(document.getElementById('pod-row')"
    785       "    .getPodWithUsername_('%s').querySelector('.expanded-pane-name')"
    786       "        .textContent);",
    787       user_id_1_.c_str());
    788   display_name.clear();
    789   ASSERT_TRUE(content::ExecuteScriptAndExtractString(
    790       contents_,
    791       get_expanded_pod_display_name,
    792       &display_name));
    793   EXPECT_EQ(kDisplayName1, display_name);
    794 
    795   // Click on the pod to expand it.
    796   ASSERT_TRUE(content::ExecuteScript(
    797       contents_,
    798       base::StringPrintf(
    799           "document.getElementById('pod-row').getPodWithUsername_('%s')"
    800           "    .click();",
    801       user_id_1_.c_str())));
    802 
    803   // Change the display name.
    804   device_local_account_policy_.payload().mutable_userdisplayname()->set_value(
    805       kDisplayName2);
    806   UploadAndInstallDeviceLocalAccountPolicy();
    807   policy::BrowserPolicyConnectorChromeOS* connector =
    808       g_browser_process->platform_part()->browser_policy_connector_chromeos();
    809   DeviceLocalAccountPolicyBroker* broker =
    810       connector->GetDeviceLocalAccountPolicyService()->GetBrokerForUser(
    811           user_id_1_);
    812   ASSERT_TRUE(broker);
    813   broker->core()->store()->Load();
    814   WaitForDisplayName(user_id_1_, kDisplayName2);
    815 
    816   // Verify that the new display name is shown in the UI.
    817   display_name.clear();
    818   ASSERT_TRUE(content::ExecuteScriptAndExtractString(
    819       contents_,
    820       get_compact_pod_display_name,
    821       &display_name));
    822   EXPECT_EQ(kDisplayName2, display_name);
    823   display_name.clear();
    824   ASSERT_TRUE(content::ExecuteScriptAndExtractString(
    825       contents_,
    826       get_expanded_pod_display_name,
    827       &display_name));
    828   EXPECT_EQ(kDisplayName2, display_name);
    829 
    830   // Verify that the pod is still expanded. This indicates that the UI updated
    831   // without reloading and losing state.
    832   bool expanded = false;
    833   ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
    834       contents_,
    835       base::StringPrintf(
    836           "domAutomationController.send(document.getElementById('pod-row')"
    837           "    .getPodWithUsername_('%s').expanded);",
    838           user_id_1_.c_str()),
    839       &expanded));
    840   EXPECT_TRUE(expanded);
    841 }
    842 
    843 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, PolicyDownload) {
    844   UploadDeviceLocalAccountPolicy();
    845   AddPublicSessionToDevicePolicy(kAccountId1);
    846 
    847   WaitForPolicy();
    848 
    849   // Sanity check: The policy should be present now.
    850   ASSERT_FALSE(session_manager_client()->device_local_account_policy(
    851       kAccountId1).empty());
    852 }
    853 
    854 static bool IsNotKnownUser(const std::string& account_id) {
    855   return !IsKnownUser(account_id);
    856 }
    857 
    858 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, AccountListChange) {
    859   AddPublicSessionToDevicePolicy(kAccountId1);
    860   AddPublicSessionToDevicePolicy(kAccountId2);
    861 
    862   content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED,
    863                                         base::Bind(&IsKnownUser, user_id_1_))
    864       .Wait();
    865   EXPECT_TRUE(IsKnownUser(user_id_2_));
    866 
    867   // Update policy to remove kAccountId2.
    868   em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
    869   proto.mutable_device_local_accounts()->clear_account();
    870   AddPublicSessionToDevicePolicy(kAccountId1);
    871 
    872   em::ChromeDeviceSettingsProto policy;
    873   policy.mutable_show_user_names()->set_show_user_names(true);
    874   em::DeviceLocalAccountInfoProto* account1 =
    875       policy.mutable_device_local_accounts()->add_account();
    876   account1->set_account_id(kAccountId1);
    877   account1->set_type(
    878       em::DeviceLocalAccountInfoProto::ACCOUNT_TYPE_PUBLIC_SESSION);
    879 
    880   test_server_.UpdatePolicy(dm_protocol::kChromeDevicePolicyType, std::string(),
    881                             policy.SerializeAsString());
    882   g_browser_process->policy_service()->RefreshPolicies(base::Closure());
    883 
    884   // Make sure the second device-local account disappears.
    885   content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED,
    886                                         base::Bind(&IsNotKnownUser, user_id_2_))
    887       .Wait();
    888 }
    889 
    890 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, StartSession) {
    891   // Specify startup pages.
    892   device_local_account_policy_.payload().mutable_restoreonstartup()->set_value(
    893       SessionStartupPref::kPrefValueURLs);
    894   em::StringListPolicyProto* startup_urls_proto =
    895       device_local_account_policy_.payload().mutable_restoreonstartupurls();
    896   for (size_t i = 0; i < arraysize(kStartupURLs); ++i)
    897     startup_urls_proto->mutable_value()->add_entries(kStartupURLs[i]);
    898   UploadAndInstallDeviceLocalAccountPolicy();
    899   AddPublicSessionToDevicePolicy(kAccountId1);
    900 
    901   WaitForPolicy();
    902 
    903   ASSERT_NO_FATAL_FAILURE(StartLogin(std::string(), std::string()));
    904   WaitForSessionStart();
    905 
    906   // Check that the startup pages specified in policy were opened.
    907   BrowserList* browser_list =
    908     BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH);
    909   EXPECT_EQ(1U, browser_list->size());
    910   Browser* browser = browser_list->get(0);
    911   ASSERT_TRUE(browser);
    912 
    913   TabStripModel* tabs = browser->tab_strip_model();
    914   ASSERT_TRUE(tabs);
    915   int expected_tab_count = static_cast<int>(arraysize(kStartupURLs));
    916   EXPECT_EQ(expected_tab_count, tabs->count());
    917   for (int i = 0; i < expected_tab_count && i < tabs->count(); ++i) {
    918     EXPECT_EQ(GURL(kStartupURLs[i]),
    919               tabs->GetWebContentsAt(i)->GetVisibleURL());
    920   }
    921 
    922   // Verify that the session is not considered to be logged in with a GAIA
    923   // account.
    924   Profile* profile = GetProfileForTest();
    925   ASSERT_TRUE(profile);
    926   EXPECT_FALSE(profile->GetPrefs()->HasPrefPath(
    927       prefs::kGoogleServicesUsername));
    928 }
    929 
    930 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, FullscreenDisallowed) {
    931   UploadAndInstallDeviceLocalAccountPolicy();
    932   AddPublicSessionToDevicePolicy(kAccountId1);
    933 
    934   WaitForPolicy();
    935 
    936   ASSERT_NO_FATAL_FAILURE(StartLogin(std::string(), std::string()));
    937   WaitForSessionStart();
    938 
    939   BrowserList* browser_list =
    940     BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH);
    941   EXPECT_EQ(1U, browser_list->size());
    942   Browser* browser = browser_list->get(0);
    943   ASSERT_TRUE(browser);
    944   BrowserWindow* browser_window = browser->window();
    945   ASSERT_TRUE(browser_window);
    946 
    947   // Verify that an attempt to enter fullscreen mode is denied.
    948   EXPECT_FALSE(browser_window->IsFullscreen());
    949   chrome::ToggleFullscreenMode(browser);
    950   EXPECT_FALSE(browser_window->IsFullscreen());
    951 }
    952 
    953 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, ExtensionsUncached) {
    954   // Make it possible to force-install a hosted app and an extension.
    955   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
    956   TestingUpdateManifestProvider testing_update_manifest_provider(
    957       kRelativeUpdateURL);
    958   testing_update_manifest_provider.AddUpdate(
    959       kHostedAppID,
    960       kHostedAppVersion,
    961       embedded_test_server()->GetURL(std::string("/") + kHostedAppCRXPath));
    962   testing_update_manifest_provider.AddUpdate(
    963       kGoodExtensionID,
    964       kGoodExtensionVersion,
    965       embedded_test_server()->GetURL(std::string("/") + kGoodExtensionCRXPath));
    966   embedded_test_server()->RegisterRequestHandler(
    967       base::Bind(&TestingUpdateManifestProvider::HandleRequest,
    968                  base::Unretained(&testing_update_manifest_provider)));
    969 
    970   // Specify policy to force-install the hosted app and the extension.
    971   em::StringList* forcelist = device_local_account_policy_.payload()
    972       .mutable_extensioninstallforcelist()->mutable_value();
    973   forcelist->add_entries(base::StringPrintf(
    974       "%s;%s",
    975       kHostedAppID,
    976       embedded_test_server()->GetURL(kRelativeUpdateURL).spec().c_str()));
    977   forcelist->add_entries(base::StringPrintf(
    978       "%s;%s",
    979       kGoodExtensionID,
    980       embedded_test_server()->GetURL(kRelativeUpdateURL).spec().c_str()));
    981 
    982   UploadAndInstallDeviceLocalAccountPolicy();
    983   AddPublicSessionToDevicePolicy(kAccountId1);
    984 
    985   WaitForPolicy();
    986 
    987   // Start listening for app/extension installation results.
    988   content::WindowedNotificationObserver hosted_app_observer(
    989       extensions::NOTIFICATION_EXTENSION_WILL_BE_INSTALLED_DEPRECATED,
    990       base::Bind(DoesInstallSuccessReferToId, kHostedAppID));
    991   content::WindowedNotificationObserver extension_observer(
    992       extensions::NOTIFICATION_EXTENSION_INSTALL_ERROR,
    993       base::Bind(DoesInstallFailureReferToId, kGoodExtensionID));
    994 
    995   ASSERT_NO_FATAL_FAILURE(StartLogin(std::string(), std::string()));
    996 
    997   // Wait for the hosted app installation to succeed and the extension
    998   // installation to fail (because hosted apps are whitelisted for use in
    999   // device-local accounts and extensions are not).
   1000   hosted_app_observer.Wait();
   1001   extension_observer.Wait();
   1002 
   1003   // Verify that the hosted app was installed.
   1004   Profile* profile = GetProfileForTest();
   1005   ASSERT_TRUE(profile);
   1006   ExtensionService* extension_service =
   1007       extensions::ExtensionSystem::Get(profile)->extension_service();
   1008   EXPECT_TRUE(extension_service->GetExtensionById(kHostedAppID, true));
   1009 
   1010   // Verify that the extension was not installed.
   1011   EXPECT_FALSE(extension_service->GetExtensionById(kGoodExtensionID, true));
   1012 
   1013   // Verify that the app was downloaded to the account's extension cache.
   1014   base::FilePath test_dir;
   1015   ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir));
   1016   EXPECT_TRUE(ContentsEqual(
   1017           GetCacheCRXFile(kAccountId1, kHostedAppID, kHostedAppVersion),
   1018           test_dir.Append(kHostedAppCRXPath)));
   1019 
   1020   // Verify that the extension was removed from the account's extension cache
   1021   // after the installation failure.
   1022   DeviceLocalAccountPolicyBroker* broker =
   1023       g_browser_process->platform_part()->browser_policy_connector_chromeos()->
   1024           GetDeviceLocalAccountPolicyService()->GetBrokerForUser(user_id_1_);
   1025   ASSERT_TRUE(broker);
   1026   chromeos::ExternalCache* cache =
   1027       broker->extension_loader()->GetExternalCacheForTesting();
   1028   ASSERT_TRUE(cache);
   1029   EXPECT_FALSE(cache->GetExtension(kGoodExtensionID, NULL, NULL));
   1030 }
   1031 
   1032 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, ExtensionsCached) {
   1033   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
   1034 
   1035   // Pre-populate the device local account's extension cache with a hosted app
   1036   // and an extension.
   1037   EXPECT_TRUE(base::CreateDirectory(
   1038       GetExtensionCacheDirectoryForAccountID(kAccountId1)));
   1039   base::FilePath test_dir;
   1040   ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir));
   1041   const base::FilePath cached_hosted_app =
   1042       GetCacheCRXFile(kAccountId1, kHostedAppID, kHostedAppVersion);
   1043   EXPECT_TRUE(CopyFile(test_dir.Append(kHostedAppCRXPath),
   1044                        cached_hosted_app));
   1045   EXPECT_TRUE(CopyFile(
   1046       test_dir.Append(kGoodExtensionCRXPath),
   1047       GetCacheCRXFile(kAccountId1, kGoodExtensionID, kGoodExtensionVersion)));
   1048 
   1049   // Specify policy to force-install the hosted app.
   1050   em::StringList* forcelist = device_local_account_policy_.payload()
   1051       .mutable_extensioninstallforcelist()->mutable_value();
   1052   forcelist->add_entries(base::StringPrintf(
   1053       "%s;%s",
   1054       kHostedAppID,
   1055       embedded_test_server()->GetURL(kRelativeUpdateURL).spec().c_str()));
   1056   forcelist->add_entries(base::StringPrintf(
   1057       "%s;%s",
   1058       kGoodExtensionID,
   1059       embedded_test_server()->GetURL(kRelativeUpdateURL).spec().c_str()));
   1060 
   1061   UploadAndInstallDeviceLocalAccountPolicy();
   1062   AddPublicSessionToDevicePolicy(kAccountId1);
   1063 
   1064   WaitForPolicy();
   1065 
   1066   // Start listening for app/extension installation results.
   1067   content::WindowedNotificationObserver hosted_app_observer(
   1068       extensions::NOTIFICATION_EXTENSION_WILL_BE_INSTALLED_DEPRECATED,
   1069       base::Bind(DoesInstallSuccessReferToId, kHostedAppID));
   1070   content::WindowedNotificationObserver extension_observer(
   1071       extensions::NOTIFICATION_EXTENSION_INSTALL_ERROR,
   1072       base::Bind(DoesInstallFailureReferToId, kGoodExtensionID));
   1073 
   1074   ASSERT_NO_FATAL_FAILURE(StartLogin(std::string(), std::string()));
   1075 
   1076   // Wait for the hosted app installation to succeed and the extension
   1077   // installation to fail.
   1078   hosted_app_observer.Wait();
   1079   extension_observer.Wait();
   1080 
   1081   // Verify that the hosted app was installed.
   1082   Profile* profile = GetProfileForTest();
   1083   ASSERT_TRUE(profile);
   1084   ExtensionService* extension_service =
   1085       extensions::ExtensionSystem::Get(profile)->extension_service();
   1086   EXPECT_TRUE(extension_service->GetExtensionById(kHostedAppID, true));
   1087 
   1088   // Verify that the extension was not installed.
   1089   EXPECT_FALSE(extension_service->GetExtensionById(kGoodExtensionID, true));
   1090 
   1091   // Verify that the app is still in the account's extension cache.
   1092   EXPECT_TRUE(PathExists(cached_hosted_app));
   1093 
   1094   // Verify that the extension was removed from the account's extension cache.
   1095   DeviceLocalAccountPolicyBroker* broker =
   1096       g_browser_process->platform_part()->browser_policy_connector_chromeos()->
   1097           GetDeviceLocalAccountPolicyService()->GetBrokerForUser(user_id_1_);
   1098   ASSERT_TRUE(broker);
   1099   chromeos::ExternalCache* cache =
   1100       broker->extension_loader()->GetExternalCacheForTesting();
   1101   ASSERT_TRUE(cache);
   1102   EXPECT_FALSE(cache->GetExtension(kGoodExtensionID, NULL, NULL));
   1103 }
   1104 
   1105 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, ExternalData) {
   1106   // user_manager::UserManager requests an external data fetch whenever
   1107   // the key::kUserAvatarImage policy is set. Since this test wants to
   1108   // verify that the underlying policy subsystem will start a fetch
   1109   // without this request as well, the user_manager::UserManager must be
   1110   // prevented from seeing the policy change.
   1111   reinterpret_cast<chromeos::ChromeUserManagerImpl*>(
   1112       user_manager::UserManager::Get())->StopPolicyObserverForTesting();
   1113 
   1114   UploadDeviceLocalAccountPolicy();
   1115   AddPublicSessionToDevicePolicy(kAccountId1);
   1116 
   1117   WaitForPolicy();
   1118 
   1119   // Start serving external data at |kExternalDataURL|.
   1120   scoped_ptr<base::RunLoop> run_loop(new base::RunLoop);
   1121   scoped_ptr<net::FakeURLFetcherFactory> fetcher_factory(
   1122       new net::FakeURLFetcherFactory(
   1123           NULL,
   1124           base::Bind(&RunCallbackAndReturnFakeURLFetcher,
   1125                      base::MessageLoopProxy::current(),
   1126                      run_loop->QuitClosure())));
   1127   fetcher_factory->SetFakeResponse(GURL(kExternalDataURL),
   1128                                    kExternalData,
   1129                                    net::HTTP_OK,
   1130                                    net::URLRequestStatus::SUCCESS);
   1131 
   1132   // Specify an external data reference for the key::kUserAvatarImage policy.
   1133   scoped_ptr<base::DictionaryValue> metadata =
   1134       test::ConstructExternalDataReference(kExternalDataURL, kExternalData);
   1135   std::string policy;
   1136   base::JSONWriter::Write(metadata.get(), &policy);
   1137   device_local_account_policy_.payload().mutable_useravatarimage()->set_value(
   1138       policy);
   1139   UploadAndInstallDeviceLocalAccountPolicy();
   1140   policy::BrowserPolicyConnectorChromeOS* connector =
   1141       g_browser_process->platform_part()->browser_policy_connector_chromeos();
   1142   DeviceLocalAccountPolicyBroker* broker =
   1143       connector->GetDeviceLocalAccountPolicyService()->GetBrokerForUser(
   1144           user_id_1_);
   1145   ASSERT_TRUE(broker);
   1146   broker->core()->store()->Load();
   1147 
   1148   // The external data should be fetched and cached automatically. Wait for this
   1149   // fetch.
   1150   run_loop->Run();
   1151 
   1152   // Stop serving external data at |kExternalDataURL|.
   1153   fetcher_factory.reset();
   1154 
   1155   const PolicyMap::Entry* policy_entry =
   1156       broker->core()->store()->policy_map().Get(key::kUserAvatarImage);
   1157   ASSERT_TRUE(policy_entry);
   1158   ASSERT_TRUE(policy_entry->external_data_fetcher);
   1159 
   1160   // Retrieve the external data. Although the data is no longer being served at
   1161   // |kExternalDataURL|, the retrieval should succeed because the data has been
   1162   // cached.
   1163   run_loop.reset(new base::RunLoop);
   1164   scoped_ptr<std::string> fetched_external_data;
   1165   policy_entry->external_data_fetcher->Fetch(base::Bind(
   1166       &test::ExternalDataFetchCallback,
   1167       &fetched_external_data,
   1168       run_loop->QuitClosure()));
   1169   run_loop->Run();
   1170 
   1171   ASSERT_TRUE(fetched_external_data);
   1172   EXPECT_EQ(kExternalData, *fetched_external_data);
   1173 
   1174   ASSERT_NO_FATAL_FAILURE(StartLogin(std::string(), std::string()));
   1175   WaitForSessionStart();
   1176 
   1177   // Verify that the external data reference has propagated to the device-local
   1178   // account's ProfilePolicyConnector.
   1179   ProfilePolicyConnector* policy_connector =
   1180       ProfilePolicyConnectorFactory::GetForProfile(GetProfileForTest());
   1181   ASSERT_TRUE(policy_connector);
   1182   const PolicyMap& policies = policy_connector->policy_service()->GetPolicies(
   1183       PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()));
   1184   policy_entry = policies.Get(key::kUserAvatarImage);
   1185   ASSERT_TRUE(policy_entry);
   1186   EXPECT_TRUE(base::Value::Equals(metadata.get(), policy_entry->value));
   1187   ASSERT_TRUE(policy_entry->external_data_fetcher);
   1188 
   1189   // Retrieve the external data via the ProfilePolicyConnector. The retrieval
   1190   // should succeed because the data has been cached.
   1191   run_loop.reset(new base::RunLoop);
   1192   fetched_external_data.reset();
   1193   policy_entry->external_data_fetcher->Fetch(base::Bind(
   1194       &test::ExternalDataFetchCallback,
   1195       &fetched_external_data,
   1196       run_loop->QuitClosure()));
   1197   run_loop->Run();
   1198 
   1199   ASSERT_TRUE(fetched_external_data);
   1200   EXPECT_EQ(kExternalData, *fetched_external_data);
   1201 }
   1202 
   1203 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, UserAvatarImage) {
   1204   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
   1205 
   1206   UploadDeviceLocalAccountPolicy();
   1207   AddPublicSessionToDevicePolicy(kAccountId1);
   1208 
   1209   WaitForPolicy();
   1210 
   1211   base::FilePath test_dir;
   1212   ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir));
   1213   std::string image_data;
   1214   ASSERT_TRUE(base::ReadFileToString(
   1215       test_dir.Append(chromeos::test::kUserAvatarImage1RelativePath),
   1216       &image_data));
   1217 
   1218   std::string policy;
   1219   base::JSONWriter::Write(test::ConstructExternalDataReference(
   1220       embedded_test_server()->GetURL(std::string("/") +
   1221           chromeos::test::kUserAvatarImage1RelativePath).spec(),
   1222       image_data).get(),
   1223       &policy);
   1224   device_local_account_policy_.payload().mutable_useravatarimage()->set_value(
   1225       policy);
   1226   UploadAndInstallDeviceLocalAccountPolicy();
   1227   policy::BrowserPolicyConnectorChromeOS* connector =
   1228       g_browser_process->platform_part()->browser_policy_connector_chromeos();
   1229   DeviceLocalAccountPolicyBroker* broker =
   1230       connector->GetDeviceLocalAccountPolicyService()->GetBrokerForUser(
   1231           user_id_1_);
   1232   ASSERT_TRUE(broker);
   1233 
   1234   run_loop_.reset(new base::RunLoop);
   1235   user_manager::UserManager::Get()->AddObserver(this);
   1236   broker->core()->store()->Load();
   1237   run_loop_->Run();
   1238   user_manager::UserManager::Get()->RemoveObserver(this);
   1239 
   1240   scoped_ptr<gfx::ImageSkia> policy_image = chromeos::test::ImageLoader(
   1241       test_dir.Append(chromeos::test::kUserAvatarImage1RelativePath)).Load();
   1242   ASSERT_TRUE(policy_image);
   1243 
   1244   const user_manager::User* user =
   1245       user_manager::UserManager::Get()->FindUser(user_id_1_);
   1246   ASSERT_TRUE(user);
   1247 
   1248   base::FilePath user_data_dir;
   1249   ASSERT_TRUE(PathService::Get(chrome::DIR_USER_DATA, &user_data_dir));
   1250   const base::FilePath saved_image_path =
   1251       user_data_dir.Append(user_id_1_).AddExtension("jpg");
   1252 
   1253   EXPECT_FALSE(user->HasDefaultImage());
   1254   EXPECT_EQ(user_manager::User::USER_IMAGE_EXTERNAL, user->image_index());
   1255   EXPECT_TRUE(chromeos::test::AreImagesEqual(*policy_image, user->GetImage()));
   1256   const base::DictionaryValue* images_pref =
   1257       g_browser_process->local_state()->GetDictionary("user_image_info");
   1258   ASSERT_TRUE(images_pref);
   1259   const base::DictionaryValue* image_properties;
   1260   ASSERT_TRUE(images_pref->GetDictionaryWithoutPathExpansion(
   1261       user_id_1_,
   1262       &image_properties));
   1263   int image_index;
   1264   std::string image_path;
   1265   ASSERT_TRUE(image_properties->GetInteger("index", &image_index));
   1266   ASSERT_TRUE(image_properties->GetString("path", &image_path));
   1267   EXPECT_EQ(user_manager::User::USER_IMAGE_EXTERNAL, image_index);
   1268   EXPECT_EQ(saved_image_path.value(), image_path);
   1269 
   1270   scoped_ptr<gfx::ImageSkia> saved_image =
   1271       chromeos::test::ImageLoader(saved_image_path).Load();
   1272   ASSERT_TRUE(saved_image);
   1273 
   1274   // Check image dimensions. Images can't be compared since JPEG is lossy.
   1275   EXPECT_EQ(policy_image->width(), saved_image->width());
   1276   EXPECT_EQ(policy_image->height(), saved_image->height());
   1277 }
   1278 
   1279 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, LastWindowClosedLogoutReminder) {
   1280   UploadAndInstallDeviceLocalAccountPolicy();
   1281   AddPublicSessionToDevicePolicy(kAccountId1);
   1282 
   1283   WaitForPolicy();
   1284 
   1285   ASSERT_NO_FATAL_FAILURE(StartLogin(std::string(), std::string()));
   1286   WaitForSessionStart();
   1287 
   1288   Profile* profile = GetProfileForTest();
   1289   ASSERT_TRUE(profile);
   1290   extensions::AppWindowRegistry* app_window_registry =
   1291       extensions::AppWindowRegistry::Get(profile);
   1292   app_window_registry->AddObserver(this);
   1293 
   1294   // Verify that the logout confirmation dialog is not showing.
   1295   ash::LogoutConfirmationController* logout_confirmation_controller =
   1296       ash::Shell::GetInstance()->logout_confirmation_controller();
   1297   ASSERT_TRUE(logout_confirmation_controller);
   1298   EXPECT_FALSE(logout_confirmation_controller->dialog_for_testing());
   1299 
   1300   // Remove policy that allows only explicitly whitelisted apps to be installed
   1301   // in a public session.
   1302   extensions::ExtensionSystem* extension_system =
   1303       extensions::ExtensionSystem::Get(profile);
   1304   ASSERT_TRUE(extension_system);
   1305   extension_system->management_policy()->UnregisterAllProviders();
   1306 
   1307   // Install and a platform app.
   1308   scoped_refptr<extensions::CrxInstaller> installer =
   1309       extensions::CrxInstaller::CreateSilent(
   1310           extension_system->extension_service());
   1311   installer->set_allow_silent_install(true);
   1312   installer->set_install_cause(extension_misc::INSTALL_CAUSE_USER_DOWNLOAD);
   1313   installer->set_creation_flags(extensions::Extension::FROM_WEBSTORE);
   1314   content::WindowedNotificationObserver app_install_observer(
   1315       extensions::NOTIFICATION_CRX_INSTALLER_DONE,
   1316       content::NotificationService::AllSources());
   1317   base::FilePath test_dir;
   1318   ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir));
   1319   installer->InstallCrx(test_dir.Append(kPackagedAppCRXPath));
   1320   app_install_observer.Wait();
   1321   const extensions::Extension* app =
   1322       content::Details<const extensions::Extension>(
   1323           app_install_observer.details()).ptr();
   1324 
   1325   // Start the platform app, causing it to open a window.
   1326   run_loop_.reset(new base::RunLoop);
   1327   OpenApplication(AppLaunchParams(
   1328       profile, app, extensions::LAUNCH_CONTAINER_NONE, NEW_WINDOW));
   1329   run_loop_->Run();
   1330   EXPECT_EQ(1U, app_window_registry->app_windows().size());
   1331 
   1332   // Close the only open browser window.
   1333   BrowserList* browser_list =
   1334       BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH);
   1335   EXPECT_EQ(1U, browser_list->size());
   1336   Browser* browser = browser_list->get(0);
   1337   ASSERT_TRUE(browser);
   1338   BrowserWindow* browser_window = browser->window();
   1339   ASSERT_TRUE(browser_window);
   1340   run_loop_.reset(new base::RunLoop);
   1341   browser_window->Close();
   1342   browser_window = NULL;
   1343   run_loop_->Run();
   1344   browser = NULL;
   1345   EXPECT_TRUE(browser_list->empty());
   1346 
   1347   // Verify that the logout confirmation dialog is not showing because an app
   1348   // window is still open.
   1349   EXPECT_FALSE(logout_confirmation_controller->dialog_for_testing());
   1350 
   1351   // Open a browser window.
   1352   Browser* first_browser = CreateBrowser(profile);
   1353   EXPECT_EQ(1U, browser_list->size());
   1354 
   1355   // Close the app window.
   1356   run_loop_.reset(new base::RunLoop);
   1357   ASSERT_EQ(1U, app_window_registry->app_windows().size());
   1358   app_window_registry->app_windows().front()->GetBaseWindow()->Close();
   1359   run_loop_->Run();
   1360   EXPECT_TRUE(app_window_registry->app_windows().empty());
   1361 
   1362   // Verify that the logout confirmation dialog is not showing because a browser
   1363   // window is still open.
   1364   EXPECT_FALSE(logout_confirmation_controller->dialog_for_testing());
   1365 
   1366   // Open a second browser window.
   1367   Browser* second_browser = CreateBrowser(profile);
   1368   EXPECT_EQ(2U, browser_list->size());
   1369 
   1370   // Close the first browser window.
   1371   browser_window = first_browser->window();
   1372   ASSERT_TRUE(browser_window);
   1373   run_loop_.reset(new base::RunLoop);
   1374   browser_window->Close();
   1375   browser_window = NULL;
   1376   run_loop_->Run();
   1377   first_browser = NULL;
   1378   EXPECT_EQ(1U, browser_list->size());
   1379 
   1380   // Verify that the logout confirmation dialog is not showing because a browser
   1381   // window is still open.
   1382   EXPECT_FALSE(logout_confirmation_controller->dialog_for_testing());
   1383 
   1384   // Close the second browser window.
   1385   browser_window = second_browser->window();
   1386   ASSERT_TRUE(browser_window);
   1387   run_loop_.reset(new base::RunLoop);
   1388   browser_window->Close();
   1389   browser_window = NULL;
   1390   run_loop_->Run();
   1391   second_browser = NULL;
   1392   EXPECT_TRUE(browser_list->empty());
   1393 
   1394   // Verify that the logout confirmation dialog is showing.
   1395   ash::LogoutConfirmationDialog* dialog =
   1396       logout_confirmation_controller->dialog_for_testing();
   1397   ASSERT_TRUE(dialog);
   1398 
   1399   // Deny the logout.
   1400   dialog->GetWidget()->Close();
   1401   dialog = NULL;
   1402   base::RunLoop().RunUntilIdle();
   1403 
   1404   // Verify that the logout confirmation dialog is no longer showing.
   1405   EXPECT_FALSE(logout_confirmation_controller->dialog_for_testing());
   1406 
   1407   // Open a browser window.
   1408   browser = CreateBrowser(profile);
   1409   EXPECT_EQ(1U, browser_list->size());
   1410 
   1411   // Close the browser window.
   1412   browser_window = browser->window();
   1413   ASSERT_TRUE(browser_window);
   1414   run_loop_.reset(new base::RunLoop);
   1415   browser_window->Close();
   1416   browser_window = NULL;
   1417   run_loop_->Run();
   1418   browser = NULL;
   1419   EXPECT_TRUE(browser_list->empty());
   1420 
   1421   // Verify that the logout confirmation dialog is showing again.
   1422   dialog = logout_confirmation_controller->dialog_for_testing();
   1423   ASSERT_TRUE(dialog);
   1424 
   1425   // Deny the logout.
   1426   dialog->GetWidget()->Close();
   1427   dialog = NULL;
   1428   base::RunLoop().RunUntilIdle();
   1429 
   1430   app_window_registry->RemoveObserver(this);
   1431 };
   1432 
   1433 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, NoRecommendedLocaleNoSwitch) {
   1434   UploadAndInstallDeviceLocalAccountPolicy();
   1435   AddPublicSessionToDevicePolicy(kAccountId1);
   1436 
   1437   WaitForPolicy();
   1438 
   1439   ExpandPublicSessionPod(false);
   1440 
   1441   // Click the enter button to start the session.
   1442   ASSERT_TRUE(content::ExecuteScript(
   1443       contents_,
   1444       base::StringPrintf(
   1445           "document.getElementById('pod-row').getPodWithUsername_('%s')"
   1446           "    .querySelector('.enter-button').click();",
   1447           user_id_1_.c_str())));
   1448 
   1449   WaitForSessionStart();
   1450 
   1451   // Verify that the locale has not changed and the first keyboard layout
   1452   // applicable to the locale was chosen.
   1453   EXPECT_EQ(initial_locale_, g_browser_process->GetApplicationLocale());
   1454   EXPECT_EQ(initial_language_, icu::Locale::getDefault().getLanguage());
   1455   VerifyKeyboardLayoutMatchesLocale();
   1456 }
   1457 
   1458 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, NoRecommendedLocaleSwitch) {
   1459   UploadAndInstallDeviceLocalAccountPolicy();
   1460   AddPublicSessionToDevicePolicy(kAccountId1);
   1461 
   1462   WaitForPolicy();
   1463 
   1464   ExpandPublicSessionPod(false);
   1465 
   1466   // Click the link that switches the pod to its advanced form. Verify that the
   1467   // pod switches from basic to advanced.
   1468   bool advanced = false;
   1469   ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
   1470       contents_,
   1471       base::StringPrintf(
   1472           "var pod ="
   1473           "    document.getElementById('pod-row').getPodWithUsername_('%s');"
   1474           "pod.querySelector('.language-and-input').click();"
   1475           "domAutomationController.send(pod.classList.contains('advanced'));",
   1476           user_id_1_.c_str()),
   1477       &advanced));
   1478   EXPECT_FALSE(advanced);
   1479 
   1480   // Manually select a different locale.
   1481   ASSERT_TRUE(content::ExecuteScript(
   1482       contents_,
   1483       base::StringPrintf(
   1484           "var languageSelect = document.getElementById('pod-row')"
   1485           "    .getPodWithUsername_('%s').querySelector('.language-select');"
   1486           "languageSelect.value = '%s';"
   1487           "var event = document.createEvent('HTMLEvents');"
   1488           "event.initEvent('change', false, true);"
   1489           "languageSelect.dispatchEvent(event);",
   1490           user_id_1_.c_str(),
   1491           kPublicSessionLocale)));
   1492 
   1493   // The UI will have requested an updated list of keyboard layouts at this
   1494   // point. Wait for the constructions of this list to finish.
   1495   WaitForGetKeyboardLayoutsForLocaleToFinish();
   1496 
   1497   // Manually select a different keyboard layout and click the enter button to
   1498   // start the session.
   1499   ASSERT_TRUE(content::ExecuteScript(
   1500       contents_,
   1501       base::StringPrintf(
   1502           "var pod ="
   1503           "    document.getElementById('pod-row').getPodWithUsername_('%s');"
   1504           "pod.querySelector('.keyboard-select').value = '%s';"
   1505           "pod.querySelector('.enter-button').click();",
   1506           user_id_1_.c_str(),
   1507           public_session_input_method_id_.c_str())));
   1508 
   1509   WaitForSessionStart();
   1510 
   1511   // Verify that the locale and keyboard layout have been applied.
   1512   EXPECT_EQ(kPublicSessionLocale, g_browser_process->GetApplicationLocale());
   1513   EXPECT_EQ(l10n_util::GetLanguage(kPublicSessionLocale),
   1514             icu::Locale::getDefault().getLanguage());
   1515   EXPECT_EQ(public_session_input_method_id_,
   1516             chromeos::input_method::InputMethodManager::Get()
   1517                 ->GetActiveIMEState()
   1518                 ->GetCurrentInputMethod()
   1519                 .id());
   1520 }
   1521 
   1522 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, OneRecommendedLocale) {
   1523   // Specify a recommended locale.
   1524   SetRecommendedLocales(kSingleRecommendedLocale,
   1525                         arraysize(kSingleRecommendedLocale));
   1526   UploadAndInstallDeviceLocalAccountPolicy();
   1527   AddPublicSessionToDevicePolicy(kAccountId1);
   1528 
   1529   WaitForPolicy();
   1530 
   1531   ExpandPublicSessionPod(false);
   1532 
   1533   // Click the enter button to start the session.
   1534   ASSERT_TRUE(content::ExecuteScript(
   1535       contents_,
   1536       base::StringPrintf(
   1537           "document.getElementById('pod-row').getPodWithUsername_('%s')"
   1538           "    .querySelector('.enter-button').click();",
   1539           user_id_1_.c_str())));
   1540 
   1541   WaitForSessionStart();
   1542 
   1543   // Verify that the recommended locale has been applied and the first keyboard
   1544   // layout applicable to the locale was chosen.
   1545   EXPECT_EQ(kSingleRecommendedLocale[0],
   1546             g_browser_process->GetApplicationLocale());
   1547   EXPECT_EQ(l10n_util::GetLanguage(kSingleRecommendedLocale[0]),
   1548             icu::Locale::getDefault().getLanguage());
   1549   VerifyKeyboardLayoutMatchesLocale();
   1550 }
   1551 
   1552 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, MultipleRecommendedLocales) {
   1553   // Specify recommended locales.
   1554   SetRecommendedLocales(kRecommendedLocales1, arraysize(kRecommendedLocales1));
   1555   UploadAndInstallDeviceLocalAccountPolicy();
   1556   AddPublicSessionToDevicePolicy(kAccountId1);
   1557   AddPublicSessionToDevicePolicy(kAccountId2);
   1558 
   1559   WaitForPolicy();
   1560 
   1561   ExpandPublicSessionPod(true);
   1562 
   1563   // Verify that the pod shows a list of locales beginning with the recommended
   1564   // ones, followed by others.
   1565   const std::string get_locale_list = base::StringPrintf(
   1566       "var languageSelect = document.getElementById('pod-row')"
   1567       "    .getPodWithUsername_('%s').querySelector('.language-select');"
   1568       "var locales = [];"
   1569       "for (var i = 0; i < languageSelect.length; ++i)"
   1570       "  locales.push(languageSelect.options[i].value);"
   1571       "domAutomationController.send(JSON.stringify(locales));",
   1572       user_id_1_.c_str());
   1573   std::string json;
   1574   ASSERT_TRUE(content::ExecuteScriptAndExtractString(contents_,
   1575                                                      get_locale_list,
   1576                                                      &json));
   1577   scoped_ptr<base::Value> value_ptr(base::JSONReader::Read(json));
   1578   const base::ListValue* locales = NULL;
   1579   ASSERT_TRUE(value_ptr);
   1580   ASSERT_TRUE(value_ptr->GetAsList(&locales));
   1581   EXPECT_LT(arraysize(kRecommendedLocales1), locales->GetSize());
   1582 
   1583   // Verify that the list starts with the recommended locales, in correct order.
   1584   for (size_t i = 0; i < arraysize(kRecommendedLocales1); ++i) {
   1585     std::string locale;
   1586     EXPECT_TRUE(locales->GetString(i, &locale));
   1587     EXPECT_EQ(kRecommendedLocales1[i], locale);
   1588   }
   1589 
   1590   // Verify that the recommended locales do not appear again in the remainder of
   1591   // the list.
   1592   std::set<std::string> recommended_locales;
   1593   for (size_t i = 0; i < arraysize(kRecommendedLocales1); ++i)
   1594     recommended_locales.insert(kRecommendedLocales1[i]);
   1595   for (size_t i = arraysize(kRecommendedLocales1); i < locales->GetSize();
   1596        ++i) {
   1597     std::string locale;
   1598     EXPECT_TRUE(locales->GetString(i, &locale));
   1599     EXPECT_EQ(recommended_locales.end(), recommended_locales.find(locale));
   1600   }
   1601 
   1602   // Verify that the first recommended locale is selected.
   1603   const std::string get_selected_locale =
   1604       base::StringPrintf(
   1605           "domAutomationController.send(document.getElementById('pod-row')"
   1606           "    .getPodWithUsername_('%s').querySelector('.language-select')"
   1607           "        .value);",
   1608           user_id_1_.c_str());
   1609   std::string selected_locale;
   1610   ASSERT_TRUE(content::ExecuteScriptAndExtractString(contents_,
   1611                                                      get_selected_locale,
   1612                                                      &selected_locale));
   1613   EXPECT_EQ(kRecommendedLocales1[0], selected_locale);
   1614 
   1615   // Change the list of recommended locales.
   1616   SetRecommendedLocales(kRecommendedLocales2, arraysize(kRecommendedLocales2));
   1617 
   1618   // Also change the display name as it is easy to ensure that policy has been
   1619   // updated by waiting for a display name change.
   1620   device_local_account_policy_.payload().mutable_userdisplayname()->set_value(
   1621       kDisplayName2);
   1622   UploadAndInstallDeviceLocalAccountPolicy();
   1623   policy::BrowserPolicyConnectorChromeOS* connector =
   1624       g_browser_process->platform_part()->browser_policy_connector_chromeos();
   1625   DeviceLocalAccountPolicyBroker* broker =
   1626       connector->GetDeviceLocalAccountPolicyService()->GetBrokerForUser(
   1627           user_id_1_);
   1628   ASSERT_TRUE(broker);
   1629   broker->core()->store()->Load();
   1630   WaitForDisplayName(user_id_1_, kDisplayName2);
   1631 
   1632   // Verify that the new list of locales is shown in the UI.
   1633   ASSERT_TRUE(content::ExecuteScriptAndExtractString(contents_,
   1634                                                      get_locale_list,
   1635                                                      &json));
   1636   value_ptr.reset(base::JSONReader::Read(json));
   1637   locales = NULL;
   1638   ASSERT_TRUE(value_ptr);
   1639   ASSERT_TRUE(value_ptr->GetAsList(&locales));
   1640   EXPECT_LT(arraysize(kRecommendedLocales2), locales->GetSize());
   1641   for (size_t i = 0; i < arraysize(kRecommendedLocales2); ++i) {
   1642     std::string locale;
   1643     EXPECT_TRUE(locales->GetString(i, &locale));
   1644     EXPECT_EQ(kRecommendedLocales2[i], locale);
   1645   }
   1646 
   1647   // Verify that the first new recommended locale is selected.
   1648   ASSERT_TRUE(content::ExecuteScriptAndExtractString(contents_,
   1649                                                      get_selected_locale,
   1650                                                      &selected_locale));
   1651   EXPECT_EQ(kRecommendedLocales2[0], selected_locale);
   1652 
   1653   // Manually select a different locale.
   1654   ASSERT_TRUE(content::ExecuteScript(
   1655       contents_,
   1656       base::StringPrintf(
   1657           "var languageSelect = document.getElementById('pod-row')"
   1658           "    .getPodWithUsername_('%s').querySelector('.language-select');"
   1659           "languageSelect.value = '%s';"
   1660           "var event = document.createEvent('HTMLEvents');"
   1661           "event.initEvent('change', false, true);"
   1662           "languageSelect.dispatchEvent(event);",
   1663           user_id_1_.c_str(),
   1664           kPublicSessionLocale)));
   1665 
   1666   // Change the list of recommended locales.
   1667   SetRecommendedLocales(kRecommendedLocales2, arraysize(kRecommendedLocales2));
   1668   device_local_account_policy_.payload().mutable_userdisplayname()->set_value(
   1669       kDisplayName1);
   1670   UploadAndInstallDeviceLocalAccountPolicy();
   1671   broker->core()->store()->Load();
   1672   WaitForDisplayName(user_id_1_, kDisplayName1);
   1673 
   1674   // Verify that the manually selected locale is still selected.
   1675   ASSERT_TRUE(content::ExecuteScriptAndExtractString(contents_,
   1676                                                      get_selected_locale,
   1677                                                      &selected_locale));
   1678   EXPECT_EQ(kPublicSessionLocale, selected_locale);
   1679 
   1680   // The UI will request an updated list of keyboard layouts at this point. Wait
   1681   // for the constructions of this list to finish.
   1682   WaitForGetKeyboardLayoutsForLocaleToFinish();
   1683 
   1684   // Manually select a different keyboard layout.
   1685   ASSERT_TRUE(content::ExecuteScript(
   1686       contents_,
   1687       base::StringPrintf(
   1688           "document.getElementById('pod-row').getPodWithUsername_('%s')"
   1689           "    .querySelector('.keyboard-select').value = '%s';",
   1690           user_id_1_.c_str(),
   1691           public_session_input_method_id_.c_str())));
   1692 
   1693   // Click on a different pod, causing focus to shift away and the pod to
   1694   // contract.
   1695   ASSERT_TRUE(content::ExecuteScript(
   1696       contents_,
   1697       base::StringPrintf(
   1698           "document.getElementById('pod-row').getPodWithUsername_('%s')"
   1699           "    .click();",
   1700           user_id_2_.c_str())));
   1701 
   1702   // Click on the pod again, causing it to expand again. Verify that the pod has
   1703   // kept all its state (the advanced form is being shown, the manually selected
   1704   // locale and keyboard layout are selected).
   1705   ASSERT_TRUE(content::ExecuteScriptAndExtractString(
   1706       contents_,
   1707       base::StringPrintf(
   1708           "var pod ="
   1709           "    document.getElementById('pod-row').getPodWithUsername_('%s');"
   1710           "pod.click();"
   1711           "var state = {};"
   1712           "state.advanced = pod.classList.contains('advanced');"
   1713           "state.locale = pod.querySelector('.language-select').value;"
   1714           "state.keyboardLayout = pod.querySelector('.keyboard-select').value;"
   1715           "console.log(JSON.stringify(state));"
   1716           "domAutomationController.send(JSON.stringify(state));",
   1717           user_id_1_.c_str()),
   1718       &json));
   1719   LOG(ERROR) << json;
   1720   value_ptr.reset(base::JSONReader::Read(json));
   1721   const base::DictionaryValue* state = NULL;
   1722   ASSERT_TRUE(value_ptr);
   1723   ASSERT_TRUE(value_ptr->GetAsDictionary(&state));
   1724   bool advanced = false;
   1725   EXPECT_TRUE(state->GetBoolean("advanced", &advanced));
   1726   EXPECT_TRUE(advanced);
   1727   EXPECT_TRUE(state->GetString("locale", &selected_locale));
   1728   EXPECT_EQ(kPublicSessionLocale, selected_locale);
   1729   std::string selected_keyboard_layout;
   1730   EXPECT_TRUE(state->GetString("keyboardLayout", &selected_keyboard_layout));
   1731   EXPECT_EQ(public_session_input_method_id_, selected_keyboard_layout);
   1732 
   1733   // Click the enter button to start the session.
   1734   ASSERT_TRUE(content::ExecuteScript(
   1735       contents_,
   1736       base::StringPrintf(
   1737           "document.getElementById('pod-row').getPodWithUsername_('%s')"
   1738           "    .querySelector('.enter-button').click();",
   1739           user_id_1_.c_str())));
   1740 
   1741   WaitForSessionStart();
   1742 
   1743   // Verify that the locale and keyboard layout have been applied.
   1744   EXPECT_EQ(kPublicSessionLocale, g_browser_process->GetApplicationLocale());
   1745   EXPECT_EQ(l10n_util::GetLanguage(kPublicSessionLocale),
   1746             icu::Locale::getDefault().getLanguage());
   1747   EXPECT_EQ(public_session_input_method_id_,
   1748             chromeos::input_method::InputMethodManager::Get()
   1749                 ->GetActiveIMEState()
   1750                 ->GetCurrentInputMethod()
   1751                 .id());
   1752 }
   1753 
   1754 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, InvalidRecommendedLocale) {
   1755   // Specify an invalid recommended locale.
   1756   SetRecommendedLocales(kInvalidRecommendedLocale,
   1757                         arraysize(kInvalidRecommendedLocale));
   1758   UploadAndInstallDeviceLocalAccountPolicy();
   1759   AddPublicSessionToDevicePolicy(kAccountId1);
   1760 
   1761   WaitForPolicy();
   1762 
   1763   // Click on the pod to expand it. Verify that the pod expands to its basic
   1764   // form as there is only one recommended locale.
   1765   bool advanced = false;
   1766   ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
   1767       contents_,
   1768       base::StringPrintf(
   1769           "var pod ="
   1770           "    document.getElementById('pod-row').getPodWithUsername_('%s');"
   1771           "pod.click();"
   1772           "domAutomationController.send(pod.classList.contains('advanced'));",
   1773           user_id_1_.c_str()),
   1774       &advanced));
   1775   EXPECT_FALSE(advanced);
   1776   EXPECT_EQ(l10n_util::GetLanguage(initial_locale_),
   1777             icu::Locale::getDefault().getLanguage());
   1778 
   1779   // Click the enter button to start the session.
   1780   ASSERT_TRUE(content::ExecuteScript(
   1781       contents_,
   1782       base::StringPrintf(
   1783           "document.getElementById('pod-row').getPodWithUsername_('%s')"
   1784           "    .querySelector('.enter-button').click();",
   1785           user_id_1_.c_str())));
   1786 
   1787   WaitForSessionStart();
   1788 
   1789   // Verify that since the recommended locale was invalid, the locale has not
   1790   // changed and the first keyboard layout applicable to the locale was chosen.
   1791   EXPECT_EQ(initial_locale_, g_browser_process->GetApplicationLocale());
   1792   EXPECT_EQ(l10n_util::GetLanguage(initial_locale_),
   1793             icu::Locale::getDefault().getLanguage());
   1794   VerifyKeyboardLayoutMatchesLocale();
   1795 }
   1796 
   1797 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest,
   1798                        AutoLoginWithoutRecommendedLocales) {
   1799   UploadAndInstallDeviceLocalAccountPolicy();
   1800   AddPublicSessionToDevicePolicy(kAccountId1);
   1801   EnableAutoLogin();
   1802 
   1803   WaitForPolicy();
   1804 
   1805   WaitForSessionStart();
   1806 
   1807   // Verify that the locale has not changed and the first keyboard layout
   1808   // applicable to the locale was chosen.
   1809   EXPECT_EQ(initial_locale_, g_browser_process->GetApplicationLocale());
   1810   EXPECT_EQ(initial_language_, icu::Locale::getDefault().getLanguage());
   1811   VerifyKeyboardLayoutMatchesLocale();
   1812 }
   1813 
   1814 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest,
   1815                        AutoLoginWithRecommendedLocales) {
   1816   // Specify recommended locales.
   1817   SetRecommendedLocales(kRecommendedLocales1, arraysize(kRecommendedLocales1));
   1818   UploadAndInstallDeviceLocalAccountPolicy();
   1819   AddPublicSessionToDevicePolicy(kAccountId1);
   1820   EnableAutoLogin();
   1821 
   1822   WaitForPolicy();
   1823 
   1824   WaitForSessionStart();
   1825 
   1826   // Verify that the first recommended locale has been applied and the first
   1827   // keyboard layout applicable to the locale was chosen.
   1828   EXPECT_EQ(kRecommendedLocales1[0], g_browser_process->GetApplicationLocale());
   1829   EXPECT_EQ(l10n_util::GetLanguage(kRecommendedLocales1[0]),
   1830             icu::Locale::getDefault().getLanguage());
   1831   VerifyKeyboardLayoutMatchesLocale();
   1832 }
   1833 
   1834 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, TermsOfServiceWithLocaleSwitch) {
   1835   // Specify Terms of Service URL.
   1836   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
   1837   device_local_account_policy_.payload().mutable_termsofserviceurl()->set_value(
   1838       embedded_test_server()->GetURL(
   1839           std::string("/") + kExistentTermsOfServicePath).spec());
   1840   UploadAndInstallDeviceLocalAccountPolicy();
   1841   AddPublicSessionToDevicePolicy(kAccountId1);
   1842 
   1843   WaitForPolicy();
   1844 
   1845   // Select a different locale.
   1846   ASSERT_TRUE(content::ExecuteScript(
   1847       contents_,
   1848       base::StringPrintf(
   1849           "var languageSelect = document.getElementById('pod-row')"
   1850           "    .getPodWithUsername_('%s').querySelector('.language-select');"
   1851           "languageSelect.value = '%s';"
   1852           "var event = document.createEvent('HTMLEvents');"
   1853           "event.initEvent('change', false, true);"
   1854           "languageSelect.dispatchEvent(event);",
   1855           user_id_1_.c_str(),
   1856           kPublicSessionLocale)));
   1857 
   1858   // The UI will have requested an updated list of keyboard layouts at this
   1859   // point. Wait for the constructions of this list to finish.
   1860   WaitForGetKeyboardLayoutsForLocaleToFinish();
   1861 
   1862   // Set up an observer that will quit the message loop when login has succeeded
   1863   // and the first wizard screen, if any, is being shown.
   1864   base::RunLoop login_wait_run_loop;
   1865   chromeos::MockAuthStatusConsumer login_status_consumer;
   1866   EXPECT_CALL(login_status_consumer, OnAuthSuccess(_)).Times(1).WillOnce(
   1867       InvokeWithoutArgs(&login_wait_run_loop, &base::RunLoop::Quit));
   1868   chromeos::ExistingUserController* controller =
   1869       chromeos::ExistingUserController::current_controller();
   1870   ASSERT_TRUE(controller);
   1871   controller->set_login_status_consumer(&login_status_consumer);
   1872 
   1873   // Manually select a different keyboard layout and click the enter button to
   1874   // start the session.
   1875   ASSERT_TRUE(content::ExecuteScript(
   1876       contents_,
   1877       base::StringPrintf(
   1878           "var pod ="
   1879           "    document.getElementById('pod-row').getPodWithUsername_('%s');"
   1880           "pod.querySelector('.keyboard-select').value = '%s';"
   1881           "pod.querySelector('.enter-button').click();",
   1882           user_id_1_.c_str(),
   1883           public_session_input_method_id_.c_str())));
   1884 
   1885   // Spin the loop until the login observer fires. Then, unregister the
   1886   // observer.
   1887   login_wait_run_loop.Run();
   1888   controller->set_login_status_consumer(NULL);
   1889 
   1890   // Verify that the Terms of Service screen is being shown.
   1891   chromeos::WizardController* wizard_controller =
   1892         chromeos::WizardController::default_controller();
   1893   ASSERT_TRUE(wizard_controller);
   1894   ASSERT_TRUE(wizard_controller->current_screen());
   1895   EXPECT_EQ(chromeos::WizardController::kTermsOfServiceScreenName,
   1896             wizard_controller->current_screen()->GetName());
   1897 
   1898   // Wait for the Terms of Service to finish downloading.
   1899   bool done = false;
   1900   ASSERT_TRUE(content::ExecuteScriptAndExtractBool(contents_,
   1901       "var screenElement = document.getElementById('terms-of-service');"
   1902       "function SendReplyIfDownloadDone() {"
   1903       "  if (screenElement.classList.contains('tos-loading'))"
   1904       "    return false;"
   1905       "  domAutomationController.send(true);"
   1906       "  observer.disconnect();"
   1907       "  return true;"
   1908       "}"
   1909       "var observer = new MutationObserver(SendReplyIfDownloadDone);"
   1910       "if (!SendReplyIfDownloadDone()) {"
   1911       "  var options = { attributes: true, attributeFilter: [ 'class' ] };"
   1912       "  observer.observe(screenElement, options);"
   1913       "}",
   1914       &done));
   1915 
   1916   // Verify that the locale and keyboard layout have been applied.
   1917   EXPECT_EQ(kPublicSessionLocale, g_browser_process->GetApplicationLocale());
   1918   EXPECT_EQ(l10n_util::GetLanguage(kPublicSessionLocale),
   1919             icu::Locale::getDefault().getLanguage());
   1920   EXPECT_EQ(public_session_input_method_id_,
   1921             chromeos::input_method::InputMethodManager::Get()
   1922                 ->GetActiveIMEState()
   1923                 ->GetCurrentInputMethod()
   1924                 .id());
   1925 
   1926   // Click the accept button.
   1927   ASSERT_TRUE(content::ExecuteScript(contents_,
   1928                                      "$('tos-accept-button').click();"));
   1929 
   1930   WaitForSessionStart();
   1931 
   1932   // Verify that the locale and keyboard layout are still in force.
   1933   EXPECT_EQ(kPublicSessionLocale, g_browser_process->GetApplicationLocale());
   1934   EXPECT_EQ(l10n_util::GetLanguage(kPublicSessionLocale),
   1935             icu::Locale::getDefault().getLanguage());
   1936   EXPECT_EQ(public_session_input_method_id_,
   1937             chromeos::input_method::InputMethodManager::Get()
   1938                 ->GetActiveIMEState()
   1939                 ->GetCurrentInputMethod()
   1940                 .id());
   1941 }
   1942 
   1943 class TermsOfServiceDownloadTest : public DeviceLocalAccountTest,
   1944                                    public testing::WithParamInterface<bool> {
   1945 };
   1946 
   1947 IN_PROC_BROWSER_TEST_P(TermsOfServiceDownloadTest, TermsOfServiceScreen) {
   1948   // Specify Terms of Service URL.
   1949   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
   1950   device_local_account_policy_.payload().mutable_termsofserviceurl()->set_value(
   1951       embedded_test_server()->GetURL(
   1952             std::string("/") +
   1953                 (GetParam() ? kExistentTermsOfServicePath
   1954                             : kNonexistentTermsOfServicePath)).spec());
   1955   UploadAndInstallDeviceLocalAccountPolicy();
   1956   AddPublicSessionToDevicePolicy(kAccountId1);
   1957 
   1958   WaitForPolicy();
   1959 
   1960   ASSERT_NO_FATAL_FAILURE(StartLogin(std::string(), std::string()));
   1961 
   1962   // Set up an observer that will quit the message loop when login has succeeded
   1963   // and the first wizard screen, if any, is being shown.
   1964   base::RunLoop login_wait_run_loop;
   1965   chromeos::MockAuthStatusConsumer login_status_consumer;
   1966   EXPECT_CALL(login_status_consumer, OnAuthSuccess(_)).Times(1).WillOnce(
   1967       InvokeWithoutArgs(&login_wait_run_loop, &base::RunLoop::Quit));
   1968 
   1969   // Spin the loop until the observer fires. Then, unregister the observer.
   1970   chromeos::ExistingUserController* controller =
   1971       chromeos::ExistingUserController::current_controller();
   1972   ASSERT_TRUE(controller);
   1973   controller->set_login_status_consumer(&login_status_consumer);
   1974   login_wait_run_loop.Run();
   1975   controller->set_login_status_consumer(NULL);
   1976 
   1977   // Verify that the Terms of Service screen is being shown.
   1978   chromeos::WizardController* wizard_controller =
   1979         chromeos::WizardController::default_controller();
   1980   ASSERT_TRUE(wizard_controller);
   1981   ASSERT_TRUE(wizard_controller->current_screen());
   1982   EXPECT_EQ(chromeos::WizardController::kTermsOfServiceScreenName,
   1983             wizard_controller->current_screen()->GetName());
   1984 
   1985   // Wait for the Terms of Service to finish downloading, then get the status of
   1986   // the screen's UI elements.
   1987   std::string json;
   1988   ASSERT_TRUE(content::ExecuteScriptAndExtractString(contents_,
   1989       "var screenElement = document.getElementById('terms-of-service');"
   1990       "function SendReplyIfDownloadDone() {"
   1991       "  if (screenElement.classList.contains('tos-loading'))"
   1992       "    return false;"
   1993       "  var status = {};"
   1994       "  status.heading = document.getElementById('tos-heading').textContent;"
   1995       "  status.subheading ="
   1996       "      document.getElementById('tos-subheading').textContent;"
   1997       "  status.contentHeading ="
   1998       "      document.getElementById('tos-content-heading').textContent;"
   1999       "  status.content ="
   2000       "      document.getElementById('tos-content-main').textContent;"
   2001       "  status.error = screenElement.classList.contains('error');"
   2002       "  status.acceptEnabled ="
   2003       "      !document.getElementById('tos-accept-button').disabled;"
   2004       "  domAutomationController.send(JSON.stringify(status));"
   2005       "  observer.disconnect();"
   2006       "  return true;"
   2007       "}"
   2008       "var observer = new MutationObserver(SendReplyIfDownloadDone);"
   2009       "if (!SendReplyIfDownloadDone()) {"
   2010       "  var options = { attributes: true, attributeFilter: [ 'class' ] };"
   2011       "  observer.observe(screenElement, options);"
   2012       "}",
   2013       &json));
   2014   scoped_ptr<base::Value> value_ptr(base::JSONReader::Read(json));
   2015   const base::DictionaryValue* status = NULL;
   2016   ASSERT_TRUE(value_ptr);
   2017   ASSERT_TRUE(value_ptr->GetAsDictionary(&status));
   2018   std::string heading;
   2019   EXPECT_TRUE(status->GetString("heading", &heading));
   2020   std::string subheading;
   2021   EXPECT_TRUE(status->GetString("subheading", &subheading));
   2022   std::string content_heading;
   2023   EXPECT_TRUE(status->GetString("contentHeading", &content_heading));
   2024   std::string content;
   2025   EXPECT_TRUE(status->GetString("content", &content));
   2026   bool error;
   2027   EXPECT_TRUE(status->GetBoolean("error", &error));
   2028   bool accept_enabled;
   2029   EXPECT_TRUE(status->GetBoolean("acceptEnabled", &accept_enabled));
   2030 
   2031   // Verify that the screen's headings have been set correctly.
   2032   EXPECT_EQ(
   2033       l10n_util::GetStringFUTF8(IDS_TERMS_OF_SERVICE_SCREEN_HEADING,
   2034                                 base::UTF8ToUTF16(kDomain)),
   2035       heading);
   2036   EXPECT_EQ(
   2037       l10n_util::GetStringFUTF8(IDS_TERMS_OF_SERVICE_SCREEN_SUBHEADING,
   2038                                 base::UTF8ToUTF16(kDomain)),
   2039       subheading);
   2040   EXPECT_EQ(
   2041       l10n_util::GetStringFUTF8(IDS_TERMS_OF_SERVICE_SCREEN_CONTENT_HEADING,
   2042                                 base::UTF8ToUTF16(kDomain)),
   2043       content_heading);
   2044 
   2045   if (!GetParam()) {
   2046     // The Terms of Service URL was invalid. Verify that the screen is showing
   2047     // an error and the accept button is disabled.
   2048     EXPECT_TRUE(error);
   2049     EXPECT_FALSE(accept_enabled);
   2050     return;
   2051   }
   2052 
   2053   // The Terms of Service URL was valid. Verify that the screen is showing the
   2054   // downloaded Terms of Service and the accept button is enabled.
   2055   base::FilePath test_dir;
   2056   ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir));
   2057   std::string terms_of_service;
   2058   ASSERT_TRUE(base::ReadFileToString(
   2059       test_dir.Append(kExistentTermsOfServicePath), &terms_of_service));
   2060   EXPECT_EQ(terms_of_service, content);
   2061   EXPECT_FALSE(error);
   2062   EXPECT_TRUE(accept_enabled);
   2063 
   2064   // Click the accept button.
   2065   ASSERT_TRUE(content::ExecuteScript(contents_,
   2066                                      "$('tos-accept-button').click();"));
   2067 
   2068   WaitForSessionStart();
   2069 }
   2070 
   2071 INSTANTIATE_TEST_CASE_P(TermsOfServiceDownloadTestInstance,
   2072                         TermsOfServiceDownloadTest, testing::Bool());
   2073 
   2074 }  // namespace policy
   2075