// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <map>
#include <set>
#include <string>
#include <vector>

#include "ash/shell.h"
#include "ash/system/chromeos/session/logout_confirmation_controller.h"
#include "ash/system/chromeos/session/logout_confirmation_dialog.h"
#include "base/basictypes.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/location.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/path_service.h"
#include "base/prefs/pref_change_registrar.h"
#include "base/prefs/pref_service.h"
#include "base/run_loop.h"
#include "base/sequenced_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/sequenced_worker_pool.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/chromeos/extensions/device_local_account_external_policy_loader.h"
#include "chrome/browser/chromeos/extensions/external_cache.h"
#include "chrome/browser/chromeos/input_method/input_method_util.h"
#include "chrome/browser/chromeos/login/existing_user_controller.h"
#include "chrome/browser/chromeos/login/screens/base_screen.h"
#include "chrome/browser/chromeos/login/signin_specifics.h"
#include "chrome/browser/chromeos/login/ui/login_display_host.h"
#include "chrome/browser/chromeos/login/ui/login_display_host_impl.h"
#include "chrome/browser/chromeos/login/ui/webui_login_view.h"
#include "chrome/browser/chromeos/login/users/avatar/user_image_manager.h"
#include "chrome/browser/chromeos/login/users/avatar/user_image_manager_impl.h"
#include "chrome/browser/chromeos/login/users/avatar/user_image_manager_test_util.h"
#include "chrome/browser/chromeos/login/users/chrome_user_manager_impl.h"
#include "chrome/browser/chromeos/login/wizard_controller.h"
#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
#include "chrome/browser/chromeos/policy/cloud_external_data_manager_base_test_util.h"
#include "chrome/browser/chromeos/policy/device_local_account.h"
#include "chrome/browser/chromeos/policy/device_local_account_policy_service.h"
#include "chrome/browser/chromeos/policy/device_policy_builder.h"
#include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h"
#include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h"
#include "chrome/browser/extensions/crx_installer.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/lifetime/application_lifetime.h"
#include "chrome/browser/policy/profile_policy_connector.h"
#include "chrome/browser/policy/profile_policy_connector_factory.h"
#include "chrome/browser/policy/test/local_policy_test_server.h"
#include "chrome/browser/prefs/session_startup_pref.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/browser_list_observer.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/extensions/application_launch.h"
#include "chrome/browser/ui/host_desktop.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
#include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/extensions/extension_constants.h"
#include "chrome/grit/chromium_strings.h"
#include "chrome/grit/generated_resources.h"
#include "chromeos/chromeos_paths.h"
#include "chromeos/chromeos_switches.h"
#include "chromeos/dbus/fake_session_manager_client.h"
#include "chromeos/ime/extension_ime_util.h"
#include "chromeos/ime/input_method_descriptor.h"
#include "chromeos/ime/input_method_manager.h"
#include "chromeos/login/auth/mock_auth_status_consumer.h"
#include "chromeos/login/auth/user_context.h"
#include "components/policy/core/common/cloud/cloud_policy_constants.h"
#include "components/policy/core/common/cloud/cloud_policy_core.h"
#include "components/policy/core/common/cloud/cloud_policy_store.h"
#include "components/policy/core/common/cloud/policy_builder.h"
#include "components/policy/core/common/external_data_fetcher.h"
#include "components/policy/core/common/policy_map.h"
#include "components/policy/core/common/policy_namespace.h"
#include "components/policy/core/common/policy_service.h"
#include "components/policy/core/common/policy_switches.h"
#include "components/signin/core/common/signin_pref_names.h"
#include "components/user_manager/user.h"
#include "components/user_manager/user_manager.h"
#include "components/user_manager/user_type.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/test_utils.h"
#include "crypto/rsa_private_key.h"
#include "extensions/browser/app_window/app_window.h"
#include "extensions/browser/app_window/app_window_registry.h"
#include "extensions/browser/app_window/native_app_window.h"
#include "extensions/browser/extension_system.h"
#include "extensions/browser/management_policy.h"
#include "extensions/browser/notification_types.h"
#include "extensions/common/extension.h"
#include "net/base/url_util.h"
#include "net/http/http_status_code.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h"
#include "net/url_request/test_url_fetcher_factory.h"
#include "net/url_request/url_fetcher_delegate.h"
#include "net/url_request/url_request_status.h"
#include "policy/policy_constants.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "third_party/icu/source/common/unicode/locid.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/window_open_disposition.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/views/widget/widget.h"
#include "url/gurl.h"

namespace em = enterprise_management;

using chromeos::LoginScreenContext;
using testing::InvokeWithoutArgs;
using testing::Return;
using testing::_;

namespace policy {

namespace {

const char kDomain[] = "example.com";
const char kAccountId1[] = "dla1@example.com";
const char kAccountId2[] = "dla2@example.com";
const char kDisplayName1[] = "display name 1";
const char kDisplayName2[] = "display name 2";
const char* const kStartupURLs[] = {
  "chrome://policy",
  "chrome://about",
};
const char kExistentTermsOfServicePath[] = "chromeos/enterprise/tos.txt";
const char kNonexistentTermsOfServicePath[] = "chromeos/enterprise/tos404.txt";
const char kRelativeUpdateURL[] = "/service/update2/crx";
const char kUpdateManifestHeader[] =
    "<?xml version='1.0' encoding='UTF-8'?>\n"
    "<gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'>\n";
const char kUpdateManifestTemplate[] =
    "  <app appid='%s'>\n"
    "    <updatecheck codebase='%s' version='%s' />\n"
    "  </app>\n";
const char kUpdateManifestFooter[] =
    "</gupdate>\n";
const char kHostedAppID[] = "kbmnembihfiondgfjekmnmcbddelicoi";
const char kHostedAppCRXPath[] = "extensions/hosted_app.crx";
const char kHostedAppVersion[] = "1.0.0.0";
const char kGoodExtensionID[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf";
const char kGoodExtensionCRXPath[] = "extensions/good.crx";
const char kGoodExtensionVersion[] = "1.0";
const char kPackagedAppCRXPath[] = "extensions/platform_apps/app_window_2.crx";
const char kShowManagedStorageID[] = "ongnjlefhnoajpbodoldndkbkdgfomlp";
const char kShowManagedStorageCRXPath[] = "extensions/show_managed_storage.crx";
const char kShowManagedStorageVersion[] = "1.0";

const char kExternalData[] = "External data";
const char kExternalDataURL[] = "http://localhost/external_data";

const char* const kSingleRecommendedLocale[] = {
  "el",
};
const char* const kRecommendedLocales1[] = {
  "pl",
  "et",
  "en-US",
};
const char* const kRecommendedLocales2[] = {
  "fr",
  "nl",
};
const char* const kInvalidRecommendedLocale[] = {
  "xx",
};
const char kPublicSessionLocale[] = "de";
const char kPublicSessionInputMethodIDTemplate[] = "_comp_ime_%sxkb:de:neo:ger";

// The sequence token used by GetKeyboardLayoutsForLocale() for its background
// tasks.
const char kSequenceToken[] = "chromeos_login_l10n_util";

// Helper that serves extension update manifests to Chrome.
class TestingUpdateManifestProvider {
 public:
  // Update manifests will be served at |relative_update_url|.
  explicit TestingUpdateManifestProvider(
      const std::string& relative_update_url);
  ~TestingUpdateManifestProvider();

  // When an update manifest is requested for the given extension |id|, indicate
  // that |version| of the extension can be downloaded at |crx_url|.
  void AddUpdate(const std::string& id,
                 const std::string& version,
                 const GURL& crx_url);

  // This method must be registered with the test's EmbeddedTestServer to start
  // serving update manifests.
  scoped_ptr<net::test_server::HttpResponse> HandleRequest(
      const net::test_server::HttpRequest& request);

 private:
  struct Update {
   public:
    Update(const std::string& version, const GURL& crx_url);
    Update();

    std::string version;
    GURL crx_url;
  };
  typedef std::map<std::string, Update> UpdateMap;
  UpdateMap updates_;

  const std::string relative_update_url_;

  DISALLOW_COPY_AND_ASSIGN(TestingUpdateManifestProvider);
};

// Helper that observes the dictionary |pref| in local state and waits until the
// value stored for |key| matches |expected_value|.
class DictionaryPrefValueWaiter {
 public:
  DictionaryPrefValueWaiter(const std::string& pref,
                            const std::string& key,
                            const std::string& expected_value);
  ~DictionaryPrefValueWaiter();

  void Wait();

 private:
  void QuitLoopIfExpectedValueFound();

  const std::string pref_;
  const std::string key_;
  const std::string expected_value_;

  base::RunLoop run_loop_;
  PrefChangeRegistrar pref_change_registrar_;

  DISALLOW_COPY_AND_ASSIGN(DictionaryPrefValueWaiter);
};

TestingUpdateManifestProvider::Update::Update(const std::string& version,
                                              const GURL& crx_url)
    : version(version),
      crx_url(crx_url) {
}

TestingUpdateManifestProvider::Update::Update() {
}

TestingUpdateManifestProvider::TestingUpdateManifestProvider(
    const std::string& relative_update_url)
    : relative_update_url_(relative_update_url) {
}

TestingUpdateManifestProvider::~TestingUpdateManifestProvider() {
}

void TestingUpdateManifestProvider::AddUpdate(const std::string& id,
                                              const std::string& version,
                                              const GURL& crx_url) {
  updates_[id] = Update(version, crx_url);
}

scoped_ptr<net::test_server::HttpResponse>
    TestingUpdateManifestProvider::HandleRequest(
        const net::test_server::HttpRequest& request) {
  const GURL url("http://localhost" + request.relative_url);
  if (url.path() != relative_update_url_)
    return scoped_ptr<net::test_server::HttpResponse>();

  std::string content = kUpdateManifestHeader;
  for (net::QueryIterator it(url); !it.IsAtEnd(); it.Advance()) {
    if (it.GetKey() != "x")
      continue;
    // Extract the extension id from the subquery. Since GetValueForKeyInQuery()
    // expects a complete URL, dummy scheme and host must be prepended.
    std::string id;
    net::GetValueForKeyInQuery(GURL("http://dummy?" + it.GetUnescapedValue()),
                               "id", &id);
    UpdateMap::const_iterator entry = updates_.find(id);
    if (entry != updates_.end()) {
      content += base::StringPrintf(kUpdateManifestTemplate,
                                    id.c_str(),
                                    entry->second.crx_url.spec().c_str(),
                                    entry->second.version.c_str());
    }
  }
  content += kUpdateManifestFooter;
  scoped_ptr<net::test_server::BasicHttpResponse>
      http_response(new net::test_server::BasicHttpResponse);
  http_response->set_code(net::HTTP_OK);
  http_response->set_content(content);
  http_response->set_content_type("text/xml");
  return http_response.Pass();
}

DictionaryPrefValueWaiter::DictionaryPrefValueWaiter(
    const std::string& pref,
    const std::string& key,
    const std::string& expected_value)
    : pref_(pref),
      key_(key),
      expected_value_(expected_value) {
  pref_change_registrar_.Init(g_browser_process->local_state());
}

DictionaryPrefValueWaiter::~DictionaryPrefValueWaiter() {
}

void DictionaryPrefValueWaiter::Wait() {
  pref_change_registrar_.Add(
      pref_.c_str(),
      base::Bind(&DictionaryPrefValueWaiter::QuitLoopIfExpectedValueFound,
                 base::Unretained(this)));
  QuitLoopIfExpectedValueFound();
  run_loop_.Run();
}

void DictionaryPrefValueWaiter::QuitLoopIfExpectedValueFound() {
  const base::DictionaryValue* pref =
      pref_change_registrar_.prefs()->GetDictionary(pref_.c_str());
  ASSERT_TRUE(pref);
  std::string actual_value;
  if (pref->GetStringWithoutPathExpansion(key_, &actual_value) &&
      actual_value == expected_value_) {
    run_loop_.Quit();
  }
}

bool DoesInstallSuccessReferToId(const std::string& id,
                                 const content::NotificationSource& source,
                                 const content::NotificationDetails& details) {
  return content::Details<const extensions::InstalledExtensionInfo>(details)->
      extension->id() == id;
}

bool DoesInstallFailureReferToId(const std::string& id,
                                 const content::NotificationSource& source,
                                 const content::NotificationDetails& details) {
  return content::Details<const base::string16>(details)->
      find(base::UTF8ToUTF16(id)) != base::string16::npos;
}

scoped_ptr<net::FakeURLFetcher> RunCallbackAndReturnFakeURLFetcher(
    scoped_refptr<base::SequencedTaskRunner> task_runner,
    const base::Closure& callback,
    const GURL& url,
    net::URLFetcherDelegate* delegate,
    const std::string& response_data,
    net::HttpStatusCode response_code,
    net::URLRequestStatus::Status status) {
  task_runner->PostTask(FROM_HERE, callback);
  return make_scoped_ptr(new net::FakeURLFetcher(
      url, delegate, response_data, response_code, status));
}

bool IsSessionStarted() {
  return user_manager::UserManager::Get()->IsSessionStarted();
}

void PolicyChangedCallback(const base::Closure& callback,
                           const base::Value* old_value,
                           const base::Value* new_value) {
  callback.Run();
}

}  // namespace

class DeviceLocalAccountTest : public DevicePolicyCrosBrowserTest,
                               public user_manager::UserManager::Observer,
                               public chrome::BrowserListObserver,
                               public extensions::AppWindowRegistry::Observer {
 protected:
  DeviceLocalAccountTest()
      : user_id_1_(GenerateDeviceLocalAccountUserId(
            kAccountId1, DeviceLocalAccount::TYPE_PUBLIC_SESSION)),
        user_id_2_(GenerateDeviceLocalAccountUserId(
            kAccountId2, DeviceLocalAccount::TYPE_PUBLIC_SESSION)),
        public_session_input_method_id_(base::StringPrintf(
            kPublicSessionInputMethodIDTemplate,
            chromeos::extension_ime_util::kXkbExtensionId)),
        contents_(NULL) {
    set_exit_when_last_browser_closes(false);
  }

  virtual ~DeviceLocalAccountTest() {}

  virtual void SetUp() override {
    // Configure and start the test server.
    scoped_ptr<crypto::RSAPrivateKey> signing_key(
        PolicyBuilder::CreateTestSigningKey());
    ASSERT_TRUE(test_server_.SetSigningKeyAndSignature(
        signing_key.get(), PolicyBuilder::GetTestSigningKeySignature()));
    signing_key.reset();
    test_server_.RegisterClient(PolicyBuilder::kFakeToken,
                                PolicyBuilder::kFakeDeviceId);
    ASSERT_TRUE(test_server_.Start());

    BrowserList::AddObserver(this);

    DevicePolicyCrosBrowserTest::SetUp();
  }

  virtual void SetUpCommandLine(CommandLine* command_line) override {
    DevicePolicyCrosBrowserTest::SetUpCommandLine(command_line);
    command_line->AppendSwitch(chromeos::switches::kLoginManager);
    command_line->AppendSwitch(chromeos::switches::kForceLoginManagerInTests);
    command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile, "user");
    command_line->AppendSwitchASCII(policy::switches::kDeviceManagementUrl,
                                    test_server_.GetServiceURL().spec());
  }

  virtual void SetUpInProcessBrowserTestFixture() override {
    DevicePolicyCrosBrowserTest::SetUpInProcessBrowserTestFixture();

    // Clear command-line arguments (but keep command-line switches) so the
    // startup pages policy takes effect.
    CommandLine* command_line = CommandLine::ForCurrentProcess();
    CommandLine::StringVector argv(command_line->argv());
    argv.erase(argv.begin() + argv.size() - command_line->GetArgs().size(),
               argv.end());
    command_line->InitFromArgv(argv);

    InstallOwnerKey();
    MarkAsEnterpriseOwned();

    InitializePolicy();
  }

  virtual void SetUpOnMainThread() override {
    DevicePolicyCrosBrowserTest::SetUpOnMainThread();

    initial_locale_ = g_browser_process->GetApplicationLocale();
    initial_language_ = l10n_util::GetLanguage(initial_locale_);

    content::WindowedNotificationObserver(
        chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
        content::NotificationService::AllSources()).Wait();

    chromeos::LoginDisplayHostImpl* host =
        reinterpret_cast<chromeos::LoginDisplayHostImpl*>(
            chromeos::LoginDisplayHostImpl::default_host());
    ASSERT_TRUE(host);
    chromeos::WebUILoginView* web_ui_login_view = host->GetWebUILoginView();
    ASSERT_TRUE(web_ui_login_view);
    content::WebUI* web_ui = web_ui_login_view->GetWebUI();
    ASSERT_TRUE(web_ui);
    contents_ = web_ui->GetWebContents();
    ASSERT_TRUE(contents_);

    // Wait for the login UI to be ready.
    chromeos::OobeUI* oobe_ui = host->GetOobeUI();
    ASSERT_TRUE(oobe_ui);
    base::RunLoop run_loop;
    const bool oobe_ui_ready = oobe_ui->IsJSReady(run_loop.QuitClosure());
    if (!oobe_ui_ready)
      run_loop.Run();

    // The network selection screen changes the application locale on load and
    // once again on blur. Wait for the screen to load and blur it so that any
    // locale changes caused by this screen happen now and do not affect any
    // subsequent parts of the test.
    bool done = false;
    ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
        contents_,
        "var languageSelect = document.getElementById('language-select');"
        "var blurAndReportSuccess = function() {"
        "  languageSelect.blur();"
        "  domAutomationController.send(true);"
        "};"
        "var screenLoading = document.getElementById('outer-container')"
        "    .classList.contains('down');"
        "if (document.activeElement == languageSelect || !screenLoading)"
        "  blurAndReportSuccess();"
        "else"
        "  languageSelect.addEventListener('focus', blurAndReportSuccess);",
        &done));

    // Skip to the login screen.
    chromeos::WizardController* wizard_controller =
        chromeos::WizardController::default_controller();
    ASSERT_TRUE(wizard_controller);
    wizard_controller->SkipToLoginForTesting(LoginScreenContext());
  }

  virtual void TearDownOnMainThread() override {
    BrowserList::RemoveObserver(this);

    // This shuts down the login UI.
    base::MessageLoop::current()->PostTask(FROM_HERE,
                                           base::Bind(&chrome::AttemptExit));
    base::RunLoop().RunUntilIdle();
  }

  virtual void LocalStateChanged(
      user_manager::UserManager* user_manager) override {
    if (run_loop_)
      run_loop_->Quit();
  }

  virtual void OnBrowserRemoved(Browser* browser) override {
    if (run_loop_)
      run_loop_->Quit();
  }

  virtual void OnAppWindowAdded(extensions::AppWindow* app_window) override {
    if (run_loop_)
      run_loop_->Quit();
  }

  virtual void OnAppWindowRemoved(extensions::AppWindow* app_window) override {
    if (run_loop_)
      run_loop_->Quit();
  }

  void InitializePolicy() {
    device_policy()->policy_data().set_public_key_version(1);
    em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
    proto.mutable_show_user_names()->set_show_user_names(true);

    device_local_account_policy_.policy_data().set_policy_type(
        dm_protocol::kChromePublicAccountPolicyType);
    device_local_account_policy_.policy_data().set_username(kAccountId1);
    device_local_account_policy_.policy_data().set_settings_entity_id(
        kAccountId1);
    device_local_account_policy_.policy_data().set_public_key_version(1);
    device_local_account_policy_.payload().mutable_userdisplayname()->set_value(
        kDisplayName1);
  }

  void BuildDeviceLocalAccountPolicy() {
    device_local_account_policy_.SetDefaultSigningKey();
    device_local_account_policy_.Build();
  }

  void UploadDeviceLocalAccountPolicy() {
    BuildDeviceLocalAccountPolicy();
    test_server_.UpdatePolicy(
        dm_protocol::kChromePublicAccountPolicyType, kAccountId1,
        device_local_account_policy_.payload().SerializeAsString());
  }

  void UploadAndInstallDeviceLocalAccountPolicy() {
    UploadDeviceLocalAccountPolicy();
    session_manager_client()->set_device_local_account_policy(
        kAccountId1, device_local_account_policy_.GetBlob());
  }

  void SetRecommendedLocales(const char* const recommended_locales[],
                             size_t array_size) {
    em::StringListPolicyProto* session_locales_proto =
        device_local_account_policy_.payload().mutable_sessionlocales();
     session_locales_proto->mutable_policy_options()->set_mode(
        em::PolicyOptions_PolicyMode_RECOMMENDED);
    session_locales_proto->mutable_value()->Clear();
    for (size_t i = 0; i < array_size; ++i) {
      session_locales_proto->mutable_value()->add_entries(
          recommended_locales[i]);
    }
  }

  void AddPublicSessionToDevicePolicy(const std::string& username) {
    em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
    em::DeviceLocalAccountInfoProto* account =
        proto.mutable_device_local_accounts()->add_account();
    account->set_account_id(username);
    account->set_type(
        em::DeviceLocalAccountInfoProto::ACCOUNT_TYPE_PUBLIC_SESSION);
    RefreshDevicePolicy();
    test_server_.UpdatePolicy(dm_protocol::kChromeDevicePolicyType,
                              std::string(), proto.SerializeAsString());
  }

  void EnableAutoLogin() {
    em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
    em::DeviceLocalAccountsProto* device_local_accounts =
        proto.mutable_device_local_accounts();
    device_local_accounts->set_auto_login_id(kAccountId1);
    device_local_accounts->set_auto_login_delay(0);
    RefreshDevicePolicy();
    test_server_.UpdatePolicy(dm_protocol::kChromeDevicePolicyType,
                              std::string(), proto.SerializeAsString());
  }

  void CheckPublicSessionPresent(const std::string& id) {
    const user_manager::User* user =
        user_manager::UserManager::Get()->FindUser(id);
    ASSERT_TRUE(user);
    EXPECT_EQ(id, user->email());
    EXPECT_EQ(user_manager::USER_TYPE_PUBLIC_ACCOUNT, user->GetType());
  }

  base::FilePath GetExtensionCacheDirectoryForAccountID(
      const std::string& account_id) {
    base::FilePath extension_cache_root_dir;
    if (!PathService::Get(chromeos::DIR_DEVICE_LOCAL_ACCOUNT_EXTENSIONS,
                          &extension_cache_root_dir)) {
      ADD_FAILURE();
    }
    return extension_cache_root_dir.Append(
        base::HexEncode(account_id.c_str(), account_id.size()));
  }

  base::FilePath GetCacheCRXFile(const std::string& account_id,
                                 const std::string& id,
                                 const std::string& version) {
    return GetExtensionCacheDirectoryForAccountID(account_id)
        .Append(base::StringPrintf("%s-%s.crx", id.c_str(), version.c_str()));
  }

  // Returns a profile which can be used for testing.
  Profile* GetProfileForTest() {
    // Any profile can be used here since this test does not test multi profile.
    return ProfileManager::GetActiveUserProfile();
  }

  void WaitForDisplayName(const std::string& user_id,
                          const std::string& expected_display_name) {
    DictionaryPrefValueWaiter("UserDisplayName",
                              user_id,
                              expected_display_name).Wait();
  }

  void WaitForPolicy() {
    // Wait for the display name becoming available as that indicates
    // device-local account policy is fully loaded, which is a prerequisite for
    // successful login.
    WaitForDisplayName(user_id_1_, kDisplayName1);
  }

  void ExpandPublicSessionPod(bool expect_advanced) {
    bool advanced = false;
    // Click on the pod to expand it.
    ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
        contents_,
        base::StringPrintf(
            "var pod ="
            "    document.getElementById('pod-row').getPodWithUsername_('%s');"
            "pod.click();"
            "domAutomationController.send(pod.classList.contains('advanced'));",
            user_id_1_.c_str()),
        &advanced));
    // Verify that the pod expanded to its basic/advanced form, as expected.
    EXPECT_EQ(expect_advanced, advanced);

    // Verify that the construction of the pod's language list did not affect
    // the current ICU locale.
    EXPECT_EQ(initial_language_, icu::Locale::getDefault().getLanguage());
  }

  // GetKeyboardLayoutsForLocale() posts a task to a background task runner.
  // This method flushes that task runner and the current thread's message loop
  // to ensure that GetKeyboardLayoutsForLocale() is finished.
  void WaitForGetKeyboardLayoutsForLocaleToFinish() {
    base::SequencedWorkerPool* worker_pool =
        content::BrowserThread::GetBlockingPool();
     scoped_refptr<base::SequencedTaskRunner> background_task_runner =
         worker_pool->GetSequencedTaskRunner(
             worker_pool->GetNamedSequenceToken(kSequenceToken));
    base::RunLoop run_loop;
    background_task_runner->PostTaskAndReply(FROM_HERE,
                                             base::Bind(&base::DoNothing),
                                             run_loop.QuitClosure());
    run_loop.Run();
    base::RunLoop().RunUntilIdle();

    // Verify that the construction of the keyboard layout list did not affect
    // the current ICU locale.
    EXPECT_EQ(initial_language_, icu::Locale::getDefault().getLanguage());
  }

  void StartLogin(const std::string& locale,
                  const std::string& input_method) {
    // Start login into the device-local account.
    chromeos::LoginDisplayHostImpl* host =
        reinterpret_cast<chromeos::LoginDisplayHostImpl*>(
            chromeos::LoginDisplayHostImpl::default_host());
    ASSERT_TRUE(host);
    host->StartSignInScreen(LoginScreenContext());
    chromeos::ExistingUserController* controller =
        chromeos::ExistingUserController::current_controller();
    ASSERT_TRUE(controller);

    chromeos::UserContext user_context(user_manager::USER_TYPE_PUBLIC_ACCOUNT,
                                       user_id_1_);
    user_context.SetPublicSessionLocale(locale);
    user_context.SetPublicSessionInputMethod(input_method);
    controller->Login(user_context, chromeos::SigninSpecifics());
  }

  void WaitForSessionStart() {
    if (IsSessionStarted())
      return;
    content::WindowedNotificationObserver(chrome::NOTIFICATION_SESSION_STARTED,
                                          base::Bind(IsSessionStarted)).Wait();
  }

  void VerifyKeyboardLayoutMatchesLocale() {
    chromeos::input_method::InputMethodManager* input_method_manager =
        chromeos::input_method::InputMethodManager::Get();
    std::vector<std::string> layouts_from_locale;
    input_method_manager->GetInputMethodUtil()->
        GetInputMethodIdsFromLanguageCode(
            g_browser_process->GetApplicationLocale(),
            chromeos::input_method::kKeyboardLayoutsOnly,
            &layouts_from_locale);
    ASSERT_FALSE(layouts_from_locale.empty());
    EXPECT_EQ(layouts_from_locale.front(),
              input_method_manager->GetActiveIMEState()
                  ->GetCurrentInputMethod()
                  .id());
  }

  const std::string user_id_1_;
  const std::string user_id_2_;
  const std::string public_session_input_method_id_;

  std::string initial_locale_;
  std::string initial_language_;

  scoped_ptr<base::RunLoop> run_loop_;

  UserPolicyBuilder device_local_account_policy_;
  LocalPolicyTestServer test_server_;

  content::WebContents* contents_;

 private:
  DISALLOW_COPY_AND_ASSIGN(DeviceLocalAccountTest);
};

static bool IsKnownUser(const std::string& account_id) {
  return user_manager::UserManager::Get()->IsKnownUser(account_id);
}

IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, LoginScreen) {
  AddPublicSessionToDevicePolicy(kAccountId1);
  AddPublicSessionToDevicePolicy(kAccountId2);

  content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED,
                                        base::Bind(&IsKnownUser, user_id_1_))
      .Wait();
  EXPECT_TRUE(IsKnownUser(user_id_2_));

  CheckPublicSessionPresent(user_id_1_);
  CheckPublicSessionPresent(user_id_2_);
}

IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, DisplayName) {
  UploadAndInstallDeviceLocalAccountPolicy();
  AddPublicSessionToDevicePolicy(kAccountId1);

  WaitForPolicy();

  // Verify that the display name is shown in the UI.
  const std::string get_compact_pod_display_name = base::StringPrintf(
      "domAutomationController.send(document.getElementById('pod-row')"
      "    .getPodWithUsername_('%s').nameElement.textContent);",
      user_id_1_.c_str());
  std::string display_name;
  ASSERT_TRUE(content::ExecuteScriptAndExtractString(
      contents_,
      get_compact_pod_display_name,
      &display_name));
  EXPECT_EQ(kDisplayName1, display_name);
  const std::string get_expanded_pod_display_name = base::StringPrintf(
      "domAutomationController.send(document.getElementById('pod-row')"
      "    .getPodWithUsername_('%s').querySelector('.expanded-pane-name')"
      "        .textContent);",
      user_id_1_.c_str());
  display_name.clear();
  ASSERT_TRUE(content::ExecuteScriptAndExtractString(
      contents_,
      get_expanded_pod_display_name,
      &display_name));
  EXPECT_EQ(kDisplayName1, display_name);

  // Click on the pod to expand it.
  ASSERT_TRUE(content::ExecuteScript(
      contents_,
      base::StringPrintf(
          "document.getElementById('pod-row').getPodWithUsername_('%s')"
          "    .click();",
      user_id_1_.c_str())));

  // Change the display name.
  device_local_account_policy_.payload().mutable_userdisplayname()->set_value(
      kDisplayName2);
  UploadAndInstallDeviceLocalAccountPolicy();
  policy::BrowserPolicyConnectorChromeOS* connector =
      g_browser_process->platform_part()->browser_policy_connector_chromeos();
  DeviceLocalAccountPolicyBroker* broker =
      connector->GetDeviceLocalAccountPolicyService()->GetBrokerForUser(
          user_id_1_);
  ASSERT_TRUE(broker);
  broker->core()->store()->Load();
  WaitForDisplayName(user_id_1_, kDisplayName2);

  // Verify that the new display name is shown in the UI.
  display_name.clear();
  ASSERT_TRUE(content::ExecuteScriptAndExtractString(
      contents_,
      get_compact_pod_display_name,
      &display_name));
  EXPECT_EQ(kDisplayName2, display_name);
  display_name.clear();
  ASSERT_TRUE(content::ExecuteScriptAndExtractString(
      contents_,
      get_expanded_pod_display_name,
      &display_name));
  EXPECT_EQ(kDisplayName2, display_name);

  // Verify that the pod is still expanded. This indicates that the UI updated
  // without reloading and losing state.
  bool expanded = false;
  ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
      contents_,
      base::StringPrintf(
          "domAutomationController.send(document.getElementById('pod-row')"
          "    .getPodWithUsername_('%s').expanded);",
          user_id_1_.c_str()),
      &expanded));
  EXPECT_TRUE(expanded);
}

IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, PolicyDownload) {
  UploadDeviceLocalAccountPolicy();
  AddPublicSessionToDevicePolicy(kAccountId1);

  WaitForPolicy();

  // Sanity check: The policy should be present now.
  ASSERT_FALSE(session_manager_client()->device_local_account_policy(
      kAccountId1).empty());
}

static bool IsNotKnownUser(const std::string& account_id) {
  return !IsKnownUser(account_id);
}

IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, AccountListChange) {
  AddPublicSessionToDevicePolicy(kAccountId1);
  AddPublicSessionToDevicePolicy(kAccountId2);

  content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED,
                                        base::Bind(&IsKnownUser, user_id_1_))
      .Wait();
  EXPECT_TRUE(IsKnownUser(user_id_2_));

  // Update policy to remove kAccountId2.
  em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
  proto.mutable_device_local_accounts()->clear_account();
  AddPublicSessionToDevicePolicy(kAccountId1);

  em::ChromeDeviceSettingsProto policy;
  policy.mutable_show_user_names()->set_show_user_names(true);
  em::DeviceLocalAccountInfoProto* account1 =
      policy.mutable_device_local_accounts()->add_account();
  account1->set_account_id(kAccountId1);
  account1->set_type(
      em::DeviceLocalAccountInfoProto::ACCOUNT_TYPE_PUBLIC_SESSION);

  test_server_.UpdatePolicy(dm_protocol::kChromeDevicePolicyType, std::string(),
                            policy.SerializeAsString());
  g_browser_process->policy_service()->RefreshPolicies(base::Closure());

  // Make sure the second device-local account disappears.
  content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED,
                                        base::Bind(&IsNotKnownUser, user_id_2_))
      .Wait();
}

IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, StartSession) {
  // Specify startup pages.
  device_local_account_policy_.payload().mutable_restoreonstartup()->set_value(
      SessionStartupPref::kPrefValueURLs);
  em::StringListPolicyProto* startup_urls_proto =
      device_local_account_policy_.payload().mutable_restoreonstartupurls();
  for (size_t i = 0; i < arraysize(kStartupURLs); ++i)
    startup_urls_proto->mutable_value()->add_entries(kStartupURLs[i]);
  UploadAndInstallDeviceLocalAccountPolicy();
  AddPublicSessionToDevicePolicy(kAccountId1);

  WaitForPolicy();

  ASSERT_NO_FATAL_FAILURE(StartLogin(std::string(), std::string()));
  WaitForSessionStart();

  // Check that the startup pages specified in policy were opened.
  BrowserList* browser_list =
    BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH);
  EXPECT_EQ(1U, browser_list->size());
  Browser* browser = browser_list->get(0);
  ASSERT_TRUE(browser);

  TabStripModel* tabs = browser->tab_strip_model();
  ASSERT_TRUE(tabs);
  int expected_tab_count = static_cast<int>(arraysize(kStartupURLs));
  EXPECT_EQ(expected_tab_count, tabs->count());
  for (int i = 0; i < expected_tab_count && i < tabs->count(); ++i) {
    EXPECT_EQ(GURL(kStartupURLs[i]),
              tabs->GetWebContentsAt(i)->GetVisibleURL());
  }

  // Verify that the session is not considered to be logged in with a GAIA
  // account.
  Profile* profile = GetProfileForTest();
  ASSERT_TRUE(profile);
  EXPECT_FALSE(profile->GetPrefs()->HasPrefPath(
      prefs::kGoogleServicesUsername));
}

IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, FullscreenDisallowed) {
  UploadAndInstallDeviceLocalAccountPolicy();
  AddPublicSessionToDevicePolicy(kAccountId1);

  WaitForPolicy();

  ASSERT_NO_FATAL_FAILURE(StartLogin(std::string(), std::string()));
  WaitForSessionStart();

  BrowserList* browser_list =
    BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH);
  EXPECT_EQ(1U, browser_list->size());
  Browser* browser = browser_list->get(0);
  ASSERT_TRUE(browser);
  BrowserWindow* browser_window = browser->window();
  ASSERT_TRUE(browser_window);

  // Verify that an attempt to enter fullscreen mode is denied.
  EXPECT_FALSE(browser_window->IsFullscreen());
  chrome::ToggleFullscreenMode(browser);
  EXPECT_FALSE(browser_window->IsFullscreen());
}

IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, ExtensionsUncached) {
  // Make it possible to force-install a hosted app and an extension.
  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
  TestingUpdateManifestProvider testing_update_manifest_provider(
      kRelativeUpdateURL);
  testing_update_manifest_provider.AddUpdate(
      kHostedAppID,
      kHostedAppVersion,
      embedded_test_server()->GetURL(std::string("/") + kHostedAppCRXPath));
  testing_update_manifest_provider.AddUpdate(
      kGoodExtensionID,
      kGoodExtensionVersion,
      embedded_test_server()->GetURL(std::string("/") + kGoodExtensionCRXPath));
  embedded_test_server()->RegisterRequestHandler(
      base::Bind(&TestingUpdateManifestProvider::HandleRequest,
                 base::Unretained(&testing_update_manifest_provider)));

  // Specify policy to force-install the hosted app and the extension.
  em::StringList* forcelist = device_local_account_policy_.payload()
      .mutable_extensioninstallforcelist()->mutable_value();
  forcelist->add_entries(base::StringPrintf(
      "%s;%s",
      kHostedAppID,
      embedded_test_server()->GetURL(kRelativeUpdateURL).spec().c_str()));
  forcelist->add_entries(base::StringPrintf(
      "%s;%s",
      kGoodExtensionID,
      embedded_test_server()->GetURL(kRelativeUpdateURL).spec().c_str()));

  UploadAndInstallDeviceLocalAccountPolicy();
  AddPublicSessionToDevicePolicy(kAccountId1);

  WaitForPolicy();

  // Start listening for app/extension installation results.
  content::WindowedNotificationObserver hosted_app_observer(
      extensions::NOTIFICATION_EXTENSION_WILL_BE_INSTALLED_DEPRECATED,
      base::Bind(DoesInstallSuccessReferToId, kHostedAppID));
  content::WindowedNotificationObserver extension_observer(
      extensions::NOTIFICATION_EXTENSION_INSTALL_ERROR,
      base::Bind(DoesInstallFailureReferToId, kGoodExtensionID));

  ASSERT_NO_FATAL_FAILURE(StartLogin(std::string(), std::string()));

  // Wait for the hosted app installation to succeed and the extension
  // installation to fail (because hosted apps are whitelisted for use in
  // device-local accounts and extensions are not).
  hosted_app_observer.Wait();
  extension_observer.Wait();

  // Verify that the hosted app was installed.
  Profile* profile = GetProfileForTest();
  ASSERT_TRUE(profile);
  ExtensionService* extension_service =
      extensions::ExtensionSystem::Get(profile)->extension_service();
  EXPECT_TRUE(extension_service->GetExtensionById(kHostedAppID, true));

  // Verify that the extension was not installed.
  EXPECT_FALSE(extension_service->GetExtensionById(kGoodExtensionID, true));

  // Verify that the app was downloaded to the account's extension cache.
  base::FilePath test_dir;
  ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir));
  EXPECT_TRUE(ContentsEqual(
          GetCacheCRXFile(kAccountId1, kHostedAppID, kHostedAppVersion),
          test_dir.Append(kHostedAppCRXPath)));

  // Verify that the extension was removed from the account's extension cache
  // after the installation failure.
  DeviceLocalAccountPolicyBroker* broker =
      g_browser_process->platform_part()->browser_policy_connector_chromeos()->
          GetDeviceLocalAccountPolicyService()->GetBrokerForUser(user_id_1_);
  ASSERT_TRUE(broker);
  chromeos::ExternalCache* cache =
      broker->extension_loader()->GetExternalCacheForTesting();
  ASSERT_TRUE(cache);
  EXPECT_FALSE(cache->GetExtension(kGoodExtensionID, NULL, NULL));
}

IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, ExtensionsCached) {
  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());

  // Pre-populate the device local account's extension cache with a hosted app
  // and an extension.
  EXPECT_TRUE(base::CreateDirectory(
      GetExtensionCacheDirectoryForAccountID(kAccountId1)));
  base::FilePath test_dir;
  ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir));
  const base::FilePath cached_hosted_app =
      GetCacheCRXFile(kAccountId1, kHostedAppID, kHostedAppVersion);
  EXPECT_TRUE(CopyFile(test_dir.Append(kHostedAppCRXPath),
                       cached_hosted_app));
  EXPECT_TRUE(CopyFile(
      test_dir.Append(kGoodExtensionCRXPath),
      GetCacheCRXFile(kAccountId1, kGoodExtensionID, kGoodExtensionVersion)));

  // Specify policy to force-install the hosted app.
  em::StringList* forcelist = device_local_account_policy_.payload()
      .mutable_extensioninstallforcelist()->mutable_value();
  forcelist->add_entries(base::StringPrintf(
      "%s;%s",
      kHostedAppID,
      embedded_test_server()->GetURL(kRelativeUpdateURL).spec().c_str()));
  forcelist->add_entries(base::StringPrintf(
      "%s;%s",
      kGoodExtensionID,
      embedded_test_server()->GetURL(kRelativeUpdateURL).spec().c_str()));

  UploadAndInstallDeviceLocalAccountPolicy();
  AddPublicSessionToDevicePolicy(kAccountId1);

  WaitForPolicy();

  // Start listening for app/extension installation results.
  content::WindowedNotificationObserver hosted_app_observer(
      extensions::NOTIFICATION_EXTENSION_WILL_BE_INSTALLED_DEPRECATED,
      base::Bind(DoesInstallSuccessReferToId, kHostedAppID));
  content::WindowedNotificationObserver extension_observer(
      extensions::NOTIFICATION_EXTENSION_INSTALL_ERROR,
      base::Bind(DoesInstallFailureReferToId, kGoodExtensionID));

  ASSERT_NO_FATAL_FAILURE(StartLogin(std::string(), std::string()));

  // Wait for the hosted app installation to succeed and the extension
  // installation to fail.
  hosted_app_observer.Wait();
  extension_observer.Wait();

  // Verify that the hosted app was installed.
  Profile* profile = GetProfileForTest();
  ASSERT_TRUE(profile);
  ExtensionService* extension_service =
      extensions::ExtensionSystem::Get(profile)->extension_service();
  EXPECT_TRUE(extension_service->GetExtensionById(kHostedAppID, true));

  // Verify that the extension was not installed.
  EXPECT_FALSE(extension_service->GetExtensionById(kGoodExtensionID, true));

  // Verify that the app is still in the account's extension cache.
  EXPECT_TRUE(PathExists(cached_hosted_app));

  // Verify that the extension was removed from the account's extension cache.
  DeviceLocalAccountPolicyBroker* broker =
      g_browser_process->platform_part()->browser_policy_connector_chromeos()->
          GetDeviceLocalAccountPolicyService()->GetBrokerForUser(user_id_1_);
  ASSERT_TRUE(broker);
  chromeos::ExternalCache* cache =
      broker->extension_loader()->GetExternalCacheForTesting();
  ASSERT_TRUE(cache);
  EXPECT_FALSE(cache->GetExtension(kGoodExtensionID, NULL, NULL));
}

IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, ExternalData) {
  // user_manager::UserManager requests an external data fetch whenever
  // the key::kUserAvatarImage policy is set. Since this test wants to
  // verify that the underlying policy subsystem will start a fetch
  // without this request as well, the user_manager::UserManager must be
  // prevented from seeing the policy change.
  reinterpret_cast<chromeos::ChromeUserManagerImpl*>(
      user_manager::UserManager::Get())->StopPolicyObserverForTesting();

  UploadDeviceLocalAccountPolicy();
  AddPublicSessionToDevicePolicy(kAccountId1);

  WaitForPolicy();

  // Start serving external data at |kExternalDataURL|.
  scoped_ptr<base::RunLoop> run_loop(new base::RunLoop);
  scoped_ptr<net::FakeURLFetcherFactory> fetcher_factory(
      new net::FakeURLFetcherFactory(
          NULL,
          base::Bind(&RunCallbackAndReturnFakeURLFetcher,
                     base::MessageLoopProxy::current(),
                     run_loop->QuitClosure())));
  fetcher_factory->SetFakeResponse(GURL(kExternalDataURL),
                                   kExternalData,
                                   net::HTTP_OK,
                                   net::URLRequestStatus::SUCCESS);

  // Specify an external data reference for the key::kUserAvatarImage policy.
  scoped_ptr<base::DictionaryValue> metadata =
      test::ConstructExternalDataReference(kExternalDataURL, kExternalData);
  std::string policy;
  base::JSONWriter::Write(metadata.get(), &policy);
  device_local_account_policy_.payload().mutable_useravatarimage()->set_value(
      policy);
  UploadAndInstallDeviceLocalAccountPolicy();
  policy::BrowserPolicyConnectorChromeOS* connector =
      g_browser_process->platform_part()->browser_policy_connector_chromeos();
  DeviceLocalAccountPolicyBroker* broker =
      connector->GetDeviceLocalAccountPolicyService()->GetBrokerForUser(
          user_id_1_);
  ASSERT_TRUE(broker);
  broker->core()->store()->Load();

  // The external data should be fetched and cached automatically. Wait for this
  // fetch.
  run_loop->Run();

  // Stop serving external data at |kExternalDataURL|.
  fetcher_factory.reset();

  const PolicyMap::Entry* policy_entry =
      broker->core()->store()->policy_map().Get(key::kUserAvatarImage);
  ASSERT_TRUE(policy_entry);
  ASSERT_TRUE(policy_entry->external_data_fetcher);

  // Retrieve the external data. Although the data is no longer being served at
  // |kExternalDataURL|, the retrieval should succeed because the data has been
  // cached.
  run_loop.reset(new base::RunLoop);
  scoped_ptr<std::string> fetched_external_data;
  policy_entry->external_data_fetcher->Fetch(base::Bind(
      &test::ExternalDataFetchCallback,
      &fetched_external_data,
      run_loop->QuitClosure()));
  run_loop->Run();

  ASSERT_TRUE(fetched_external_data);
  EXPECT_EQ(kExternalData, *fetched_external_data);

  ASSERT_NO_FATAL_FAILURE(StartLogin(std::string(), std::string()));
  WaitForSessionStart();

  // Verify that the external data reference has propagated to the device-local
  // account's ProfilePolicyConnector.
  ProfilePolicyConnector* policy_connector =
      ProfilePolicyConnectorFactory::GetForProfile(GetProfileForTest());
  ASSERT_TRUE(policy_connector);
  const PolicyMap& policies = policy_connector->policy_service()->GetPolicies(
      PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()));
  policy_entry = policies.Get(key::kUserAvatarImage);
  ASSERT_TRUE(policy_entry);
  EXPECT_TRUE(base::Value::Equals(metadata.get(), policy_entry->value));
  ASSERT_TRUE(policy_entry->external_data_fetcher);

  // Retrieve the external data via the ProfilePolicyConnector. The retrieval
  // should succeed because the data has been cached.
  run_loop.reset(new base::RunLoop);
  fetched_external_data.reset();
  policy_entry->external_data_fetcher->Fetch(base::Bind(
      &test::ExternalDataFetchCallback,
      &fetched_external_data,
      run_loop->QuitClosure()));
  run_loop->Run();

  ASSERT_TRUE(fetched_external_data);
  EXPECT_EQ(kExternalData, *fetched_external_data);
}

IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, UserAvatarImage) {
  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());

  UploadDeviceLocalAccountPolicy();
  AddPublicSessionToDevicePolicy(kAccountId1);

  WaitForPolicy();

  base::FilePath test_dir;
  ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir));
  std::string image_data;
  ASSERT_TRUE(base::ReadFileToString(
      test_dir.Append(chromeos::test::kUserAvatarImage1RelativePath),
      &image_data));

  std::string policy;
  base::JSONWriter::Write(test::ConstructExternalDataReference(
      embedded_test_server()->GetURL(std::string("/") +
          chromeos::test::kUserAvatarImage1RelativePath).spec(),
      image_data).get(),
      &policy);
  device_local_account_policy_.payload().mutable_useravatarimage()->set_value(
      policy);
  UploadAndInstallDeviceLocalAccountPolicy();
  policy::BrowserPolicyConnectorChromeOS* connector =
      g_browser_process->platform_part()->browser_policy_connector_chromeos();
  DeviceLocalAccountPolicyBroker* broker =
      connector->GetDeviceLocalAccountPolicyService()->GetBrokerForUser(
          user_id_1_);
  ASSERT_TRUE(broker);

  run_loop_.reset(new base::RunLoop);
  user_manager::UserManager::Get()->AddObserver(this);
  broker->core()->store()->Load();
  run_loop_->Run();
  user_manager::UserManager::Get()->RemoveObserver(this);

  scoped_ptr<gfx::ImageSkia> policy_image = chromeos::test::ImageLoader(
      test_dir.Append(chromeos::test::kUserAvatarImage1RelativePath)).Load();
  ASSERT_TRUE(policy_image);

  const user_manager::User* user =
      user_manager::UserManager::Get()->FindUser(user_id_1_);
  ASSERT_TRUE(user);

  base::FilePath user_data_dir;
  ASSERT_TRUE(PathService::Get(chrome::DIR_USER_DATA, &user_data_dir));
  const base::FilePath saved_image_path =
      user_data_dir.Append(user_id_1_).AddExtension("jpg");

  EXPECT_FALSE(user->HasDefaultImage());
  EXPECT_EQ(user_manager::User::USER_IMAGE_EXTERNAL, user->image_index());
  EXPECT_TRUE(chromeos::test::AreImagesEqual(*policy_image, user->GetImage()));
  const base::DictionaryValue* images_pref =
      g_browser_process->local_state()->GetDictionary("user_image_info");
  ASSERT_TRUE(images_pref);
  const base::DictionaryValue* image_properties;
  ASSERT_TRUE(images_pref->GetDictionaryWithoutPathExpansion(
      user_id_1_,
      &image_properties));
  int image_index;
  std::string image_path;
  ASSERT_TRUE(image_properties->GetInteger("index", &image_index));
  ASSERT_TRUE(image_properties->GetString("path", &image_path));
  EXPECT_EQ(user_manager::User::USER_IMAGE_EXTERNAL, image_index);
  EXPECT_EQ(saved_image_path.value(), image_path);

  scoped_ptr<gfx::ImageSkia> saved_image =
      chromeos::test::ImageLoader(saved_image_path).Load();
  ASSERT_TRUE(saved_image);

  // Check image dimensions. Images can't be compared since JPEG is lossy.
  EXPECT_EQ(policy_image->width(), saved_image->width());
  EXPECT_EQ(policy_image->height(), saved_image->height());
}

IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, LastWindowClosedLogoutReminder) {
  UploadAndInstallDeviceLocalAccountPolicy();
  AddPublicSessionToDevicePolicy(kAccountId1);

  WaitForPolicy();

  ASSERT_NO_FATAL_FAILURE(StartLogin(std::string(), std::string()));
  WaitForSessionStart();

  Profile* profile = GetProfileForTest();
  ASSERT_TRUE(profile);
  extensions::AppWindowRegistry* app_window_registry =
      extensions::AppWindowRegistry::Get(profile);
  app_window_registry->AddObserver(this);

  // Verify that the logout confirmation dialog is not showing.
  ash::LogoutConfirmationController* logout_confirmation_controller =
      ash::Shell::GetInstance()->logout_confirmation_controller();
  ASSERT_TRUE(logout_confirmation_controller);
  EXPECT_FALSE(logout_confirmation_controller->dialog_for_testing());

  // Remove policy that allows only explicitly whitelisted apps to be installed
  // in a public session.
  extensions::ExtensionSystem* extension_system =
      extensions::ExtensionSystem::Get(profile);
  ASSERT_TRUE(extension_system);
  extension_system->management_policy()->UnregisterAllProviders();

  // Install and a platform app.
  scoped_refptr<extensions::CrxInstaller> installer =
      extensions::CrxInstaller::CreateSilent(
          extension_system->extension_service());
  installer->set_allow_silent_install(true);
  installer->set_install_cause(extension_misc::INSTALL_CAUSE_USER_DOWNLOAD);
  installer->set_creation_flags(extensions::Extension::FROM_WEBSTORE);
  content::WindowedNotificationObserver app_install_observer(
      extensions::NOTIFICATION_CRX_INSTALLER_DONE,
      content::NotificationService::AllSources());
  base::FilePath test_dir;
  ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir));
  installer->InstallCrx(test_dir.Append(kPackagedAppCRXPath));
  app_install_observer.Wait();
  const extensions::Extension* app =
      content::Details<const extensions::Extension>(
          app_install_observer.details()).ptr();

  // Start the platform app, causing it to open a window.
  run_loop_.reset(new base::RunLoop);
  OpenApplication(AppLaunchParams(
      profile, app, extensions::LAUNCH_CONTAINER_NONE, NEW_WINDOW));
  run_loop_->Run();
  EXPECT_EQ(1U, app_window_registry->app_windows().size());

  // Close the only open browser window.
  BrowserList* browser_list =
      BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH);
  EXPECT_EQ(1U, browser_list->size());
  Browser* browser = browser_list->get(0);
  ASSERT_TRUE(browser);
  BrowserWindow* browser_window = browser->window();
  ASSERT_TRUE(browser_window);
  run_loop_.reset(new base::RunLoop);
  browser_window->Close();
  browser_window = NULL;
  run_loop_->Run();
  browser = NULL;
  EXPECT_TRUE(browser_list->empty());

  // Verify that the logout confirmation dialog is not showing because an app
  // window is still open.
  EXPECT_FALSE(logout_confirmation_controller->dialog_for_testing());

  // Open a browser window.
  Browser* first_browser = CreateBrowser(profile);
  EXPECT_EQ(1U, browser_list->size());

  // Close the app window.
  run_loop_.reset(new base::RunLoop);
  ASSERT_EQ(1U, app_window_registry->app_windows().size());
  app_window_registry->app_windows().front()->GetBaseWindow()->Close();
  run_loop_->Run();
  EXPECT_TRUE(app_window_registry->app_windows().empty());

  // Verify that the logout confirmation dialog is not showing because a browser
  // window is still open.
  EXPECT_FALSE(logout_confirmation_controller->dialog_for_testing());

  // Open a second browser window.
  Browser* second_browser = CreateBrowser(profile);
  EXPECT_EQ(2U, browser_list->size());

  // Close the first browser window.
  browser_window = first_browser->window();
  ASSERT_TRUE(browser_window);
  run_loop_.reset(new base::RunLoop);
  browser_window->Close();
  browser_window = NULL;
  run_loop_->Run();
  first_browser = NULL;
  EXPECT_EQ(1U, browser_list->size());

  // Verify that the logout confirmation dialog is not showing because a browser
  // window is still open.
  EXPECT_FALSE(logout_confirmation_controller->dialog_for_testing());

  // Close the second browser window.
  browser_window = second_browser->window();
  ASSERT_TRUE(browser_window);
  run_loop_.reset(new base::RunLoop);
  browser_window->Close();
  browser_window = NULL;
  run_loop_->Run();
  second_browser = NULL;
  EXPECT_TRUE(browser_list->empty());

  // Verify that the logout confirmation dialog is showing.
  ash::LogoutConfirmationDialog* dialog =
      logout_confirmation_controller->dialog_for_testing();
  ASSERT_TRUE(dialog);

  // Deny the logout.
  dialog->GetWidget()->Close();
  dialog = NULL;
  base::RunLoop().RunUntilIdle();

  // Verify that the logout confirmation dialog is no longer showing.
  EXPECT_FALSE(logout_confirmation_controller->dialog_for_testing());

  // Open a browser window.
  browser = CreateBrowser(profile);
  EXPECT_EQ(1U, browser_list->size());

  // Close the browser window.
  browser_window = browser->window();
  ASSERT_TRUE(browser_window);
  run_loop_.reset(new base::RunLoop);
  browser_window->Close();
  browser_window = NULL;
  run_loop_->Run();
  browser = NULL;
  EXPECT_TRUE(browser_list->empty());

  // Verify that the logout confirmation dialog is showing again.
  dialog = logout_confirmation_controller->dialog_for_testing();
  ASSERT_TRUE(dialog);

  // Deny the logout.
  dialog->GetWidget()->Close();
  dialog = NULL;
  base::RunLoop().RunUntilIdle();

  app_window_registry->RemoveObserver(this);
};

IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, NoRecommendedLocaleNoSwitch) {
  UploadAndInstallDeviceLocalAccountPolicy();
  AddPublicSessionToDevicePolicy(kAccountId1);

  WaitForPolicy();

  ExpandPublicSessionPod(false);

  // Click the enter button to start the session.
  ASSERT_TRUE(content::ExecuteScript(
      contents_,
      base::StringPrintf(
          "document.getElementById('pod-row').getPodWithUsername_('%s')"
          "    .querySelector('.enter-button').click();",
          user_id_1_.c_str())));

  WaitForSessionStart();

  // Verify that the locale has not changed and the first keyboard layout
  // applicable to the locale was chosen.
  EXPECT_EQ(initial_locale_, g_browser_process->GetApplicationLocale());
  EXPECT_EQ(initial_language_, icu::Locale::getDefault().getLanguage());
  VerifyKeyboardLayoutMatchesLocale();
}

IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, NoRecommendedLocaleSwitch) {
  UploadAndInstallDeviceLocalAccountPolicy();
  AddPublicSessionToDevicePolicy(kAccountId1);

  WaitForPolicy();

  ExpandPublicSessionPod(false);

  // Click the link that switches the pod to its advanced form. Verify that the
  // pod switches from basic to advanced.
  bool advanced = false;
  ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
      contents_,
      base::StringPrintf(
          "var pod ="
          "    document.getElementById('pod-row').getPodWithUsername_('%s');"
          "pod.querySelector('.language-and-input').click();"
          "domAutomationController.send(pod.classList.contains('advanced'));",
          user_id_1_.c_str()),
      &advanced));
  EXPECT_FALSE(advanced);

  // Manually select a different locale.
  ASSERT_TRUE(content::ExecuteScript(
      contents_,
      base::StringPrintf(
          "var languageSelect = document.getElementById('pod-row')"
          "    .getPodWithUsername_('%s').querySelector('.language-select');"
          "languageSelect.value = '%s';"
          "var event = document.createEvent('HTMLEvents');"
          "event.initEvent('change', false, true);"
          "languageSelect.dispatchEvent(event);",
          user_id_1_.c_str(),
          kPublicSessionLocale)));

  // The UI will have requested an updated list of keyboard layouts at this
  // point. Wait for the constructions of this list to finish.
  WaitForGetKeyboardLayoutsForLocaleToFinish();

  // Manually select a different keyboard layout and click the enter button to
  // start the session.
  ASSERT_TRUE(content::ExecuteScript(
      contents_,
      base::StringPrintf(
          "var pod ="
          "    document.getElementById('pod-row').getPodWithUsername_('%s');"
          "pod.querySelector('.keyboard-select').value = '%s';"
          "pod.querySelector('.enter-button').click();",
          user_id_1_.c_str(),
          public_session_input_method_id_.c_str())));

  WaitForSessionStart();

  // Verify that the locale and keyboard layout have been applied.
  EXPECT_EQ(kPublicSessionLocale, g_browser_process->GetApplicationLocale());
  EXPECT_EQ(l10n_util::GetLanguage(kPublicSessionLocale),
            icu::Locale::getDefault().getLanguage());
  EXPECT_EQ(public_session_input_method_id_,
            chromeos::input_method::InputMethodManager::Get()
                ->GetActiveIMEState()
                ->GetCurrentInputMethod()
                .id());
}

IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, OneRecommendedLocale) {
  // Specify a recommended locale.
  SetRecommendedLocales(kSingleRecommendedLocale,
                        arraysize(kSingleRecommendedLocale));
  UploadAndInstallDeviceLocalAccountPolicy();
  AddPublicSessionToDevicePolicy(kAccountId1);

  WaitForPolicy();

  ExpandPublicSessionPod(false);

  // Click the enter button to start the session.
  ASSERT_TRUE(content::ExecuteScript(
      contents_,
      base::StringPrintf(
          "document.getElementById('pod-row').getPodWithUsername_('%s')"
          "    .querySelector('.enter-button').click();",
          user_id_1_.c_str())));

  WaitForSessionStart();

  // Verify that the recommended locale has been applied and the first keyboard
  // layout applicable to the locale was chosen.
  EXPECT_EQ(kSingleRecommendedLocale[0],
            g_browser_process->GetApplicationLocale());
  EXPECT_EQ(l10n_util::GetLanguage(kSingleRecommendedLocale[0]),
            icu::Locale::getDefault().getLanguage());
  VerifyKeyboardLayoutMatchesLocale();
}

IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, MultipleRecommendedLocales) {
  // Specify recommended locales.
  SetRecommendedLocales(kRecommendedLocales1, arraysize(kRecommendedLocales1));
  UploadAndInstallDeviceLocalAccountPolicy();
  AddPublicSessionToDevicePolicy(kAccountId1);
  AddPublicSessionToDevicePolicy(kAccountId2);

  WaitForPolicy();

  ExpandPublicSessionPod(true);

  // Verify that the pod shows a list of locales beginning with the recommended
  // ones, followed by others.
  const std::string get_locale_list = base::StringPrintf(
      "var languageSelect = document.getElementById('pod-row')"
      "    .getPodWithUsername_('%s').querySelector('.language-select');"
      "var locales = [];"
      "for (var i = 0; i < languageSelect.length; ++i)"
      "  locales.push(languageSelect.options[i].value);"
      "domAutomationController.send(JSON.stringify(locales));",
      user_id_1_.c_str());
  std::string json;
  ASSERT_TRUE(content::ExecuteScriptAndExtractString(contents_,
                                                     get_locale_list,
                                                     &json));
  scoped_ptr<base::Value> value_ptr(base::JSONReader::Read(json));
  const base::ListValue* locales = NULL;
  ASSERT_TRUE(value_ptr);
  ASSERT_TRUE(value_ptr->GetAsList(&locales));
  EXPECT_LT(arraysize(kRecommendedLocales1), locales->GetSize());

  // Verify that the list starts with the recommended locales, in correct order.
  for (size_t i = 0; i < arraysize(kRecommendedLocales1); ++i) {
    std::string locale;
    EXPECT_TRUE(locales->GetString(i, &locale));
    EXPECT_EQ(kRecommendedLocales1[i], locale);
  }

  // Verify that the recommended locales do not appear again in the remainder of
  // the list.
  std::set<std::string> recommended_locales;
  for (size_t i = 0; i < arraysize(kRecommendedLocales1); ++i)
    recommended_locales.insert(kRecommendedLocales1[i]);
  for (size_t i = arraysize(kRecommendedLocales1); i < locales->GetSize();
       ++i) {
    std::string locale;
    EXPECT_TRUE(locales->GetString(i, &locale));
    EXPECT_EQ(recommended_locales.end(), recommended_locales.find(locale));
  }

  // Verify that the first recommended locale is selected.
  const std::string get_selected_locale =
      base::StringPrintf(
          "domAutomationController.send(document.getElementById('pod-row')"
          "    .getPodWithUsername_('%s').querySelector('.language-select')"
          "        .value);",
          user_id_1_.c_str());
  std::string selected_locale;
  ASSERT_TRUE(content::ExecuteScriptAndExtractString(contents_,
                                                     get_selected_locale,
                                                     &selected_locale));
  EXPECT_EQ(kRecommendedLocales1[0], selected_locale);

  // Change the list of recommended locales.
  SetRecommendedLocales(kRecommendedLocales2, arraysize(kRecommendedLocales2));

  // Also change the display name as it is easy to ensure that policy has been
  // updated by waiting for a display name change.
  device_local_account_policy_.payload().mutable_userdisplayname()->set_value(
      kDisplayName2);
  UploadAndInstallDeviceLocalAccountPolicy();
  policy::BrowserPolicyConnectorChromeOS* connector =
      g_browser_process->platform_part()->browser_policy_connector_chromeos();
  DeviceLocalAccountPolicyBroker* broker =
      connector->GetDeviceLocalAccountPolicyService()->GetBrokerForUser(
          user_id_1_);
  ASSERT_TRUE(broker);
  broker->core()->store()->Load();
  WaitForDisplayName(user_id_1_, kDisplayName2);

  // Verify that the new list of locales is shown in the UI.
  ASSERT_TRUE(content::ExecuteScriptAndExtractString(contents_,
                                                     get_locale_list,
                                                     &json));
  value_ptr.reset(base::JSONReader::Read(json));
  locales = NULL;
  ASSERT_TRUE(value_ptr);
  ASSERT_TRUE(value_ptr->GetAsList(&locales));
  EXPECT_LT(arraysize(kRecommendedLocales2), locales->GetSize());
  for (size_t i = 0; i < arraysize(kRecommendedLocales2); ++i) {
    std::string locale;
    EXPECT_TRUE(locales->GetString(i, &locale));
    EXPECT_EQ(kRecommendedLocales2[i], locale);
  }

  // Verify that the first new recommended locale is selected.
  ASSERT_TRUE(content::ExecuteScriptAndExtractString(contents_,
                                                     get_selected_locale,
                                                     &selected_locale));
  EXPECT_EQ(kRecommendedLocales2[0], selected_locale);

  // Manually select a different locale.
  ASSERT_TRUE(content::ExecuteScript(
      contents_,
      base::StringPrintf(
          "var languageSelect = document.getElementById('pod-row')"
          "    .getPodWithUsername_('%s').querySelector('.language-select');"
          "languageSelect.value = '%s';"
          "var event = document.createEvent('HTMLEvents');"
          "event.initEvent('change', false, true);"
          "languageSelect.dispatchEvent(event);",
          user_id_1_.c_str(),
          kPublicSessionLocale)));

  // Change the list of recommended locales.
  SetRecommendedLocales(kRecommendedLocales2, arraysize(kRecommendedLocales2));
  device_local_account_policy_.payload().mutable_userdisplayname()->set_value(
      kDisplayName1);
  UploadAndInstallDeviceLocalAccountPolicy();
  broker->core()->store()->Load();
  WaitForDisplayName(user_id_1_, kDisplayName1);

  // Verify that the manually selected locale is still selected.
  ASSERT_TRUE(content::ExecuteScriptAndExtractString(contents_,
                                                     get_selected_locale,
                                                     &selected_locale));
  EXPECT_EQ(kPublicSessionLocale, selected_locale);

  // The UI will request an updated list of keyboard layouts at this point. Wait
  // for the constructions of this list to finish.
  WaitForGetKeyboardLayoutsForLocaleToFinish();

  // Manually select a different keyboard layout.
  ASSERT_TRUE(content::ExecuteScript(
      contents_,
      base::StringPrintf(
          "document.getElementById('pod-row').getPodWithUsername_('%s')"
          "    .querySelector('.keyboard-select').value = '%s';",
          user_id_1_.c_str(),
          public_session_input_method_id_.c_str())));

  // Click on a different pod, causing focus to shift away and the pod to
  // contract.
  ASSERT_TRUE(content::ExecuteScript(
      contents_,
      base::StringPrintf(
          "document.getElementById('pod-row').getPodWithUsername_('%s')"
          "    .click();",
          user_id_2_.c_str())));

  // Click on the pod again, causing it to expand again. Verify that the pod has
  // kept all its state (the advanced form is being shown, the manually selected
  // locale and keyboard layout are selected).
  ASSERT_TRUE(content::ExecuteScriptAndExtractString(
      contents_,
      base::StringPrintf(
          "var pod ="
          "    document.getElementById('pod-row').getPodWithUsername_('%s');"
          "pod.click();"
          "var state = {};"
          "state.advanced = pod.classList.contains('advanced');"
          "state.locale = pod.querySelector('.language-select').value;"
          "state.keyboardLayout = pod.querySelector('.keyboard-select').value;"
          "console.log(JSON.stringify(state));"
          "domAutomationController.send(JSON.stringify(state));",
          user_id_1_.c_str()),
      &json));
  LOG(ERROR) << json;
  value_ptr.reset(base::JSONReader::Read(json));
  const base::DictionaryValue* state = NULL;
  ASSERT_TRUE(value_ptr);
  ASSERT_TRUE(value_ptr->GetAsDictionary(&state));
  bool advanced = false;
  EXPECT_TRUE(state->GetBoolean("advanced", &advanced));
  EXPECT_TRUE(advanced);
  EXPECT_TRUE(state->GetString("locale", &selected_locale));
  EXPECT_EQ(kPublicSessionLocale, selected_locale);
  std::string selected_keyboard_layout;
  EXPECT_TRUE(state->GetString("keyboardLayout", &selected_keyboard_layout));
  EXPECT_EQ(public_session_input_method_id_, selected_keyboard_layout);

  // Click the enter button to start the session.
  ASSERT_TRUE(content::ExecuteScript(
      contents_,
      base::StringPrintf(
          "document.getElementById('pod-row').getPodWithUsername_('%s')"
          "    .querySelector('.enter-button').click();",
          user_id_1_.c_str())));

  WaitForSessionStart();

  // Verify that the locale and keyboard layout have been applied.
  EXPECT_EQ(kPublicSessionLocale, g_browser_process->GetApplicationLocale());
  EXPECT_EQ(l10n_util::GetLanguage(kPublicSessionLocale),
            icu::Locale::getDefault().getLanguage());
  EXPECT_EQ(public_session_input_method_id_,
            chromeos::input_method::InputMethodManager::Get()
                ->GetActiveIMEState()
                ->GetCurrentInputMethod()
                .id());
}

IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, InvalidRecommendedLocale) {
  // Specify an invalid recommended locale.
  SetRecommendedLocales(kInvalidRecommendedLocale,
                        arraysize(kInvalidRecommendedLocale));
  UploadAndInstallDeviceLocalAccountPolicy();
  AddPublicSessionToDevicePolicy(kAccountId1);

  WaitForPolicy();

  // Click on the pod to expand it. Verify that the pod expands to its basic
  // form as there is only one recommended locale.
  bool advanced = false;
  ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
      contents_,
      base::StringPrintf(
          "var pod ="
          "    document.getElementById('pod-row').getPodWithUsername_('%s');"
          "pod.click();"
          "domAutomationController.send(pod.classList.contains('advanced'));",
          user_id_1_.c_str()),
      &advanced));
  EXPECT_FALSE(advanced);
  EXPECT_EQ(l10n_util::GetLanguage(initial_locale_),
            icu::Locale::getDefault().getLanguage());

  // Click the enter button to start the session.
  ASSERT_TRUE(content::ExecuteScript(
      contents_,
      base::StringPrintf(
          "document.getElementById('pod-row').getPodWithUsername_('%s')"
          "    .querySelector('.enter-button').click();",
          user_id_1_.c_str())));

  WaitForSessionStart();

  // Verify that since the recommended locale was invalid, the locale has not
  // changed and the first keyboard layout applicable to the locale was chosen.
  EXPECT_EQ(initial_locale_, g_browser_process->GetApplicationLocale());
  EXPECT_EQ(l10n_util::GetLanguage(initial_locale_),
            icu::Locale::getDefault().getLanguage());
  VerifyKeyboardLayoutMatchesLocale();
}

IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest,
                       AutoLoginWithoutRecommendedLocales) {
  UploadAndInstallDeviceLocalAccountPolicy();
  AddPublicSessionToDevicePolicy(kAccountId1);
  EnableAutoLogin();

  WaitForPolicy();

  WaitForSessionStart();

  // Verify that the locale has not changed and the first keyboard layout
  // applicable to the locale was chosen.
  EXPECT_EQ(initial_locale_, g_browser_process->GetApplicationLocale());
  EXPECT_EQ(initial_language_, icu::Locale::getDefault().getLanguage());
  VerifyKeyboardLayoutMatchesLocale();
}

IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest,
                       AutoLoginWithRecommendedLocales) {
  // Specify recommended locales.
  SetRecommendedLocales(kRecommendedLocales1, arraysize(kRecommendedLocales1));
  UploadAndInstallDeviceLocalAccountPolicy();
  AddPublicSessionToDevicePolicy(kAccountId1);
  EnableAutoLogin();

  WaitForPolicy();

  WaitForSessionStart();

  // Verify that the first recommended locale has been applied and the first
  // keyboard layout applicable to the locale was chosen.
  EXPECT_EQ(kRecommendedLocales1[0], g_browser_process->GetApplicationLocale());
  EXPECT_EQ(l10n_util::GetLanguage(kRecommendedLocales1[0]),
            icu::Locale::getDefault().getLanguage());
  VerifyKeyboardLayoutMatchesLocale();
}

IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, TermsOfServiceWithLocaleSwitch) {
  // Specify Terms of Service URL.
  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
  device_local_account_policy_.payload().mutable_termsofserviceurl()->set_value(
      embedded_test_server()->GetURL(
          std::string("/") + kExistentTermsOfServicePath).spec());
  UploadAndInstallDeviceLocalAccountPolicy();
  AddPublicSessionToDevicePolicy(kAccountId1);

  WaitForPolicy();

  // Select a different locale.
  ASSERT_TRUE(content::ExecuteScript(
      contents_,
      base::StringPrintf(
          "var languageSelect = document.getElementById('pod-row')"
          "    .getPodWithUsername_('%s').querySelector('.language-select');"
          "languageSelect.value = '%s';"
          "var event = document.createEvent('HTMLEvents');"
          "event.initEvent('change', false, true);"
          "languageSelect.dispatchEvent(event);",
          user_id_1_.c_str(),
          kPublicSessionLocale)));

  // The UI will have requested an updated list of keyboard layouts at this
  // point. Wait for the constructions of this list to finish.
  WaitForGetKeyboardLayoutsForLocaleToFinish();

  // Set up an observer that will quit the message loop when login has succeeded
  // and the first wizard screen, if any, is being shown.
  base::RunLoop login_wait_run_loop;
  chromeos::MockAuthStatusConsumer login_status_consumer;
  EXPECT_CALL(login_status_consumer, OnAuthSuccess(_)).Times(1).WillOnce(
      InvokeWithoutArgs(&login_wait_run_loop, &base::RunLoop::Quit));
  chromeos::ExistingUserController* controller =
      chromeos::ExistingUserController::current_controller();
  ASSERT_TRUE(controller);
  controller->set_login_status_consumer(&login_status_consumer);

  // Manually select a different keyboard layout and click the enter button to
  // start the session.
  ASSERT_TRUE(content::ExecuteScript(
      contents_,
      base::StringPrintf(
          "var pod ="
          "    document.getElementById('pod-row').getPodWithUsername_('%s');"
          "pod.querySelector('.keyboard-select').value = '%s';"
          "pod.querySelector('.enter-button').click();",
          user_id_1_.c_str(),
          public_session_input_method_id_.c_str())));

  // Spin the loop until the login observer fires. Then, unregister the
  // observer.
  login_wait_run_loop.Run();
  controller->set_login_status_consumer(NULL);

  // Verify that the Terms of Service screen is being shown.
  chromeos::WizardController* wizard_controller =
        chromeos::WizardController::default_controller();
  ASSERT_TRUE(wizard_controller);
  ASSERT_TRUE(wizard_controller->current_screen());
  EXPECT_EQ(chromeos::WizardController::kTermsOfServiceScreenName,
            wizard_controller->current_screen()->GetName());

  // Wait for the Terms of Service to finish downloading.
  bool done = false;
  ASSERT_TRUE(content::ExecuteScriptAndExtractBool(contents_,
      "var screenElement = document.getElementById('terms-of-service');"
      "function SendReplyIfDownloadDone() {"
      "  if (screenElement.classList.contains('tos-loading'))"
      "    return false;"
      "  domAutomationController.send(true);"
      "  observer.disconnect();"
      "  return true;"
      "}"
      "var observer = new MutationObserver(SendReplyIfDownloadDone);"
      "if (!SendReplyIfDownloadDone()) {"
      "  var options = { attributes: true, attributeFilter: [ 'class' ] };"
      "  observer.observe(screenElement, options);"
      "}",
      &done));

  // Verify that the locale and keyboard layout have been applied.
  EXPECT_EQ(kPublicSessionLocale, g_browser_process->GetApplicationLocale());
  EXPECT_EQ(l10n_util::GetLanguage(kPublicSessionLocale),
            icu::Locale::getDefault().getLanguage());
  EXPECT_EQ(public_session_input_method_id_,
            chromeos::input_method::InputMethodManager::Get()
                ->GetActiveIMEState()
                ->GetCurrentInputMethod()
                .id());

  // Click the accept button.
  ASSERT_TRUE(content::ExecuteScript(contents_,
                                     "$('tos-accept-button').click();"));

  WaitForSessionStart();

  // Verify that the locale and keyboard layout are still in force.
  EXPECT_EQ(kPublicSessionLocale, g_browser_process->GetApplicationLocale());
  EXPECT_EQ(l10n_util::GetLanguage(kPublicSessionLocale),
            icu::Locale::getDefault().getLanguage());
  EXPECT_EQ(public_session_input_method_id_,
            chromeos::input_method::InputMethodManager::Get()
                ->GetActiveIMEState()
                ->GetCurrentInputMethod()
                .id());
}

IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, PolicyForExtensions) {
  // Set up a test update server for the Show Managed Storage app.
  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
  TestingUpdateManifestProvider testing_update_manifest_provider(
      kRelativeUpdateURL);
  testing_update_manifest_provider.AddUpdate(
      kShowManagedStorageID,
      kShowManagedStorageVersion,
      embedded_test_server()->GetURL(std::string("/") +
                                     kShowManagedStorageCRXPath));
  embedded_test_server()->RegisterRequestHandler(
      base::Bind(&TestingUpdateManifestProvider::HandleRequest,
                 base::Unretained(&testing_update_manifest_provider)));

  // Force-install the Show Managed Storage app. This app can be installed in
  // public sessions because it's whitelisted for testing purposes.
  em::StringList* forcelist = device_local_account_policy_.payload()
      .mutable_extensioninstallforcelist()->mutable_value();
  forcelist->add_entries(base::StringPrintf(
      "%s;%s",
      kShowManagedStorageID,
      embedded_test_server()->GetURL(kRelativeUpdateURL).spec().c_str()));

  // Set a policy for the app at the policy testserver.
  test_server_.UpdatePolicyData(dm_protocol::kChromeExtensionPolicyType,
                                kShowManagedStorageID,
                                "{"
                                "  \"string\": {"
                                "    \"Value\": \"policy test value one\""
                                "  }"
                                "}");

  UploadAndInstallDeviceLocalAccountPolicy();
  AddPublicSessionToDevicePolicy(kAccountId1);
  WaitForPolicy();

  // Observe the app installation after login.
  content::WindowedNotificationObserver extension_observer(
      extensions::NOTIFICATION_EXTENSION_WILL_BE_INSTALLED_DEPRECATED,
      base::Bind(DoesInstallSuccessReferToId, kShowManagedStorageID));
  ASSERT_NO_FATAL_FAILURE(StartLogin(std::string(), std::string()));
  WaitForSessionStart();
  extension_observer.Wait();

  // Verify that the app was installed.
  Profile* profile = GetProfileForTest();
  ASSERT_TRUE(profile);
  ExtensionService* extension_service =
      extensions::ExtensionSystem::Get(profile)->extension_service();
  EXPECT_TRUE(extension_service->GetExtensionById(kShowManagedStorageID, true));

  // Wait for the app policy if it hasn't been fetched yet.
  ProfilePolicyConnector* connector =
      ProfilePolicyConnectorFactory::GetForProfile(profile);
  ASSERT_TRUE(connector);
  PolicyService* policy_service = connector->policy_service();
  ASSERT_TRUE(policy_service);
  const PolicyNamespace ns(POLICY_DOMAIN_EXTENSIONS, kShowManagedStorageID);
  if (policy_service->GetPolicies(ns).empty()) {
    PolicyChangeRegistrar policy_registrar(policy_service, ns);
    base::RunLoop run_loop;
    policy_registrar.Observe(
        "string", base::Bind(&PolicyChangedCallback, run_loop.QuitClosure()));
    run_loop.Run();
  }

  // Verify that the app policy was set.
  base::StringValue expected_value("policy test value one");
  EXPECT_TRUE(base::Value::Equals(
      &expected_value,
      policy_service->GetPolicies(ns).GetValue("string")));

  // Now update the policy at the server.
  test_server_.UpdatePolicyData(dm_protocol::kChromeExtensionPolicyType,
                                kShowManagedStorageID,
                                "{"
                                "  \"string\": {"
                                "    \"Value\": \"policy test value two\""
                                "  }"
                                "}");

  // And issue a policy refresh.
  {
    PolicyChangeRegistrar policy_registrar(policy_service, ns);
    base::RunLoop run_loop;
    policy_registrar.Observe(
        "string", base::Bind(&PolicyChangedCallback, run_loop.QuitClosure()));
    policy_service->RefreshPolicies(base::Closure());
    run_loop.Run();
  }

  // Verify that the app policy was updated.
  base::StringValue expected_new_value("policy test value two");
  EXPECT_TRUE(base::Value::Equals(
      &expected_new_value,
      policy_service->GetPolicies(ns).GetValue("string")));
}

class TermsOfServiceDownloadTest : public DeviceLocalAccountTest,
                                   public testing::WithParamInterface<bool> {
};

IN_PROC_BROWSER_TEST_P(TermsOfServiceDownloadTest, TermsOfServiceScreen) {
  // Specify Terms of Service URL.
  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
  device_local_account_policy_.payload().mutable_termsofserviceurl()->set_value(
      embedded_test_server()->GetURL(
            std::string("/") +
                (GetParam() ? kExistentTermsOfServicePath
                            : kNonexistentTermsOfServicePath)).spec());
  UploadAndInstallDeviceLocalAccountPolicy();
  AddPublicSessionToDevicePolicy(kAccountId1);

  WaitForPolicy();

  ASSERT_NO_FATAL_FAILURE(StartLogin(std::string(), std::string()));

  // Set up an observer that will quit the message loop when login has succeeded
  // and the first wizard screen, if any, is being shown.
  base::RunLoop login_wait_run_loop;
  chromeos::MockAuthStatusConsumer login_status_consumer;
  EXPECT_CALL(login_status_consumer, OnAuthSuccess(_)).Times(1).WillOnce(
      InvokeWithoutArgs(&login_wait_run_loop, &base::RunLoop::Quit));

  // Spin the loop until the observer fires. Then, unregister the observer.
  chromeos::ExistingUserController* controller =
      chromeos::ExistingUserController::current_controller();
  ASSERT_TRUE(controller);
  controller->set_login_status_consumer(&login_status_consumer);
  login_wait_run_loop.Run();
  controller->set_login_status_consumer(NULL);

  // Verify that the Terms of Service screen is being shown.
  chromeos::WizardController* wizard_controller =
        chromeos::WizardController::default_controller();
  ASSERT_TRUE(wizard_controller);
  ASSERT_TRUE(wizard_controller->current_screen());
  EXPECT_EQ(chromeos::WizardController::kTermsOfServiceScreenName,
            wizard_controller->current_screen()->GetName());

  // Wait for the Terms of Service to finish downloading, then get the status of
  // the screen's UI elements.
  std::string json;
  ASSERT_TRUE(content::ExecuteScriptAndExtractString(contents_,
      "var screenElement = document.getElementById('terms-of-service');"
      "function SendReplyIfDownloadDone() {"
      "  if (screenElement.classList.contains('tos-loading'))"
      "    return false;"
      "  var status = {};"
      "  status.heading = document.getElementById('tos-heading').textContent;"
      "  status.subheading ="
      "      document.getElementById('tos-subheading').textContent;"
      "  status.contentHeading ="
      "      document.getElementById('tos-content-heading').textContent;"
      "  status.content ="
      "      document.getElementById('tos-content-main').textContent;"
      "  status.error = screenElement.classList.contains('error');"
      "  status.acceptEnabled ="
      "      !document.getElementById('tos-accept-button').disabled;"
      "  domAutomationController.send(JSON.stringify(status));"
      "  observer.disconnect();"
      "  return true;"
      "}"
      "var observer = new MutationObserver(SendReplyIfDownloadDone);"
      "if (!SendReplyIfDownloadDone()) {"
      "  var options = { attributes: true, attributeFilter: [ 'class' ] };"
      "  observer.observe(screenElement, options);"
      "}",
      &json));
  scoped_ptr<base::Value> value_ptr(base::JSONReader::Read(json));
  const base::DictionaryValue* status = NULL;
  ASSERT_TRUE(value_ptr);
  ASSERT_TRUE(value_ptr->GetAsDictionary(&status));
  std::string heading;
  EXPECT_TRUE(status->GetString("heading", &heading));
  std::string subheading;
  EXPECT_TRUE(status->GetString("subheading", &subheading));
  std::string content_heading;
  EXPECT_TRUE(status->GetString("contentHeading", &content_heading));
  std::string content;
  EXPECT_TRUE(status->GetString("content", &content));
  bool error;
  EXPECT_TRUE(status->GetBoolean("error", &error));
  bool accept_enabled;
  EXPECT_TRUE(status->GetBoolean("acceptEnabled", &accept_enabled));

  // Verify that the screen's headings have been set correctly.
  EXPECT_EQ(
      l10n_util::GetStringFUTF8(IDS_TERMS_OF_SERVICE_SCREEN_HEADING,
                                base::UTF8ToUTF16(kDomain)),
      heading);
  EXPECT_EQ(
      l10n_util::GetStringFUTF8(IDS_TERMS_OF_SERVICE_SCREEN_SUBHEADING,
                                base::UTF8ToUTF16(kDomain)),
      subheading);
  EXPECT_EQ(
      l10n_util::GetStringFUTF8(IDS_TERMS_OF_SERVICE_SCREEN_CONTENT_HEADING,
                                base::UTF8ToUTF16(kDomain)),
      content_heading);

  if (!GetParam()) {
    // The Terms of Service URL was invalid. Verify that the screen is showing
    // an error and the accept button is disabled.
    EXPECT_TRUE(error);
    EXPECT_FALSE(accept_enabled);
    return;
  }

  // The Terms of Service URL was valid. Verify that the screen is showing the
  // downloaded Terms of Service and the accept button is enabled.
  base::FilePath test_dir;
  ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir));
  std::string terms_of_service;
  ASSERT_TRUE(base::ReadFileToString(
      test_dir.Append(kExistentTermsOfServicePath), &terms_of_service));
  EXPECT_EQ(terms_of_service, content);
  EXPECT_FALSE(error);
  EXPECT_TRUE(accept_enabled);

  // Click the accept button.
  ASSERT_TRUE(content::ExecuteScript(contents_,
                                     "$('tos-accept-button').click();"));

  WaitForSessionStart();
}

INSTANTIATE_TEST_CASE_P(TermsOfServiceDownloadTestInstance,
                        TermsOfServiceDownloadTest, testing::Bool());

}  // namespace policy
