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 <string>
      7 
      8 #include "base/basictypes.h"
      9 #include "base/bind.h"
     10 #include "base/bind_helpers.h"
     11 #include "base/callback.h"
     12 #include "base/command_line.h"
     13 #include "base/file_util.h"
     14 #include "base/files/file_path.h"
     15 #include "base/files/scoped_temp_dir.h"
     16 #include "base/json/json_reader.h"
     17 #include "base/json/json_writer.h"
     18 #include "base/location.h"
     19 #include "base/memory/ref_counted.h"
     20 #include "base/memory/scoped_ptr.h"
     21 #include "base/message_loop/message_loop.h"
     22 #include "base/message_loop/message_loop_proxy.h"
     23 #include "base/path_service.h"
     24 #include "base/prefs/pref_service.h"
     25 #include "base/run_loop.h"
     26 #include "base/sequenced_task_runner.h"
     27 #include "base/strings/string_number_conversions.h"
     28 #include "base/strings/string_util.h"
     29 #include "base/strings/stringprintf.h"
     30 #include "base/strings/utf_string_conversions.h"
     31 #include "base/test/scoped_path_override.h"
     32 #include "base/values.h"
     33 #include "chrome/browser/browser_process.h"
     34 #include "chrome/browser/chrome_notification_types.h"
     35 #include "chrome/browser/chromeos/login/existing_user_controller.h"
     36 #include "chrome/browser/chromeos/login/login_display_host.h"
     37 #include "chrome/browser/chromeos/login/login_display_host_impl.h"
     38 #include "chrome/browser/chromeos/login/mock_login_status_consumer.h"
     39 #include "chrome/browser/chromeos/login/screens/wizard_screen.h"
     40 #include "chrome/browser/chromeos/login/user.h"
     41 #include "chrome/browser/chromeos/login/user_image_manager.h"
     42 #include "chrome/browser/chromeos/login/user_image_manager_impl.h"
     43 #include "chrome/browser/chromeos/login/user_image_manager_test_util.h"
     44 #include "chrome/browser/chromeos/login/user_manager.h"
     45 #include "chrome/browser/chromeos/login/webui_login_view.h"
     46 #include "chrome/browser/chromeos/login/wizard_controller.h"
     47 #include "chrome/browser/chromeos/policy/cloud_external_data_manager_base_test_util.h"
     48 #include "chrome/browser/chromeos/policy/device_local_account.h"
     49 #include "chrome/browser/chromeos/policy/device_local_account_policy_service.h"
     50 #include "chrome/browser/chromeos/policy/device_policy_builder.h"
     51 #include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h"
     52 #include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h"
     53 #include "chrome/browser/extensions/extension_service.h"
     54 #include "chrome/browser/extensions/extension_system.h"
     55 #include "chrome/browser/lifetime/application_lifetime.h"
     56 #include "chrome/browser/policy/browser_policy_connector.h"
     57 #include "chrome/browser/policy/profile_policy_connector.h"
     58 #include "chrome/browser/policy/profile_policy_connector_factory.h"
     59 #include "chrome/browser/policy/test/local_policy_test_server.h"
     60 #include "chrome/browser/prefs/session_startup_pref.h"
     61 #include "chrome/browser/profiles/profile.h"
     62 #include "chrome/browser/profiles/profile_manager.h"
     63 #include "chrome/browser/ui/browser.h"
     64 #include "chrome/browser/ui/browser_commands.h"
     65 #include "chrome/browser/ui/browser_finder.h"
     66 #include "chrome/browser/ui/browser_list.h"
     67 #include "chrome/browser/ui/browser_window.h"
     68 #include "chrome/browser/ui/host_desktop.h"
     69 #include "chrome/browser/ui/tabs/tab_strip_model.h"
     70 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
     71 #include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h"
     72 #include "chrome/common/chrome_paths.h"
     73 #include "chrome/common/chrome_switches.h"
     74 #include "chromeos/chromeos_paths.h"
     75 #include "chromeos/chromeos_switches.h"
     76 #include "chromeos/dbus/fake_session_manager_client.h"
     77 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
     78 #include "components/policy/core/common/cloud/cloud_policy_core.h"
     79 #include "components/policy/core/common/cloud/cloud_policy_store.h"
     80 #include "components/policy/core/common/cloud/policy_builder.h"
     81 #include "components/policy/core/common/external_data_fetcher.h"
     82 #include "components/policy/core/common/policy_map.h"
     83 #include "components/policy/core/common/policy_namespace.h"
     84 #include "components/policy/core/common/policy_service.h"
     85 #include "content/public/browser/notification_details.h"
     86 #include "content/public/browser/notification_source.h"
     87 #include "content/public/browser/web_contents.h"
     88 #include "content/public/browser/web_ui.h"
     89 #include "content/public/test/browser_test_utils.h"
     90 #include "content/public/test/test_utils.h"
     91 #include "crypto/rsa_private_key.h"
     92 #include "extensions/common/extension.h"
     93 #include "grit/chromium_strings.h"
     94 #include "grit/generated_resources.h"
     95 #include "net/base/url_util.h"
     96 #include "net/http/http_status_code.h"
     97 #include "net/test/embedded_test_server/embedded_test_server.h"
     98 #include "net/test/embedded_test_server/http_request.h"
     99 #include "net/test/embedded_test_server/http_response.h"
    100 #include "net/url_request/test_url_fetcher_factory.h"
    101 #include "net/url_request/url_fetcher_delegate.h"
    102 #include "net/url_request/url_request_status.h"
    103 #include "policy/policy_constants.h"
    104 #include "testing/gmock/include/gmock/gmock.h"
    105 #include "ui/base/l10n/l10n_util.h"
    106 #include "ui/gfx/image/image_skia.h"
    107 #include "url/gurl.h"
    108 //#include "third_party/cros_system_api/dbus/service_constants.h"
    109 
    110 namespace em = enterprise_management;
    111 
    112 using chromeos::LoginScreenContext;
    113 using testing::InvokeWithoutArgs;
    114 using testing::Return;
    115 using testing::_;
    116 
    117 namespace policy {
    118 
    119 namespace {
    120 
    121 const char kDomain[] = "example.com";
    122 const char kAccountId1[] = "dla1 (at) example.com";
    123 const char kAccountId2[] = "dla2 (at) example.com";
    124 const char kDisplayName[] = "display name";
    125 const char* kStartupURLs[] = {
    126   "chrome://policy",
    127   "chrome://about",
    128 };
    129 const char kExistentTermsOfServicePath[] = "chromeos/enterprise/tos.txt";
    130 const char kNonexistentTermsOfServicePath[] = "chromeos/enterprise/tos404.txt";
    131 const char kRelativeUpdateURL[] = "/service/update2/crx";
    132 const char kUpdateManifestHeader[] =
    133     "<?xml version='1.0' encoding='UTF-8'?>\n"
    134     "<gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'>\n";
    135 const char kUpdateManifestTemplate[] =
    136     "  <app appid='%s'>\n"
    137     "    <updatecheck codebase='%s' version='%s' />\n"
    138     "  </app>\n";
    139 const char kUpdateManifestFooter[] =
    140     "</gupdate>\n";
    141 const char kHostedAppID[] = "kbmnembihfiondgfjekmnmcbddelicoi";
    142 const char kHostedAppCRXPath[] = "extensions/hosted_app.crx";
    143 const char kHostedAppVersion[] = "1.0.0.0";
    144 const char kGoodExtensionID[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf";
    145 const char kGoodExtensionCRXPath[] = "extensions/good.crx";
    146 const char kGoodExtensionVersion[] = "1.0";
    147 
    148 const char kExternalData[] = "External data";
    149 const char kExternalDataURL[] = "http://localhost/external_data";
    150 
    151 // Helper that serves extension update manifests to Chrome.
    152 class TestingUpdateManifestProvider {
    153  public:
    154 
    155   // Update manifests will be served at |relative_update_url|.
    156   explicit TestingUpdateManifestProvider(
    157       const std::string& relative_update_url);
    158   ~TestingUpdateManifestProvider();
    159 
    160   // When an update manifest is requested for the given extension |id|, indicate
    161   // that |version| of the extension can be downloaded at |crx_url|.
    162   void AddUpdate(const std::string& id,
    163                  const std::string& version,
    164                  const GURL& crx_url);
    165 
    166   // This method must be registered with the test's EmbeddedTestServer to start
    167   // serving update manifests.
    168   scoped_ptr<net::test_server::HttpResponse> HandleRequest(
    169       const net::test_server::HttpRequest& request);
    170 
    171  private:
    172   struct Update {
    173    public:
    174     Update(const std::string& version, const GURL& crx_url);
    175     Update();
    176 
    177     std::string version;
    178     GURL crx_url;
    179   };
    180   typedef std::map<std::string, Update> UpdateMap;
    181   UpdateMap updates_;
    182 
    183   const std::string relative_update_url_;
    184 
    185   DISALLOW_COPY_AND_ASSIGN(TestingUpdateManifestProvider);
    186 };
    187 
    188 TestingUpdateManifestProvider::Update::Update(const std::string& version,
    189                                               const GURL& crx_url)
    190     : version(version),
    191       crx_url(crx_url) {
    192 }
    193 
    194 TestingUpdateManifestProvider::Update::Update() {
    195 }
    196 
    197 TestingUpdateManifestProvider::TestingUpdateManifestProvider(
    198     const std::string& relative_update_url)
    199     : relative_update_url_(relative_update_url) {
    200 }
    201 
    202 TestingUpdateManifestProvider::~TestingUpdateManifestProvider() {
    203 }
    204 
    205 void TestingUpdateManifestProvider::AddUpdate(const std::string& id,
    206                                               const std::string& version,
    207                                               const GURL& crx_url) {
    208   updates_[id] = Update(version, crx_url);
    209 }
    210 
    211 scoped_ptr<net::test_server::HttpResponse>
    212     TestingUpdateManifestProvider::HandleRequest(
    213         const net::test_server::HttpRequest& request) {
    214   const GURL url("http://localhost" + request.relative_url);
    215   if (url.path() != relative_update_url_)
    216     return scoped_ptr<net::test_server::HttpResponse>();
    217 
    218   std::string content = kUpdateManifestHeader;
    219   for (net::QueryIterator it(url); !it.IsAtEnd(); it.Advance()) {
    220     if (it.GetKey() != "x")
    221       continue;
    222     // Extract the extension id from the subquery. Since GetValueForKeyInQuery()
    223     // expects a complete URL, dummy scheme and host must be prepended.
    224     std::string id;
    225     net::GetValueForKeyInQuery(GURL("http://dummy?" + it.GetUnescapedValue()),
    226                                "id", &id);
    227     UpdateMap::const_iterator entry = updates_.find(id);
    228     if (entry != updates_.end()) {
    229       content += base::StringPrintf(kUpdateManifestTemplate,
    230                                     id.c_str(),
    231                                     entry->second.crx_url.spec().c_str(),
    232                                     entry->second.version.c_str());
    233     }
    234   }
    235   content += kUpdateManifestFooter;
    236   scoped_ptr<net::test_server::BasicHttpResponse>
    237       http_response(new net::test_server::BasicHttpResponse);
    238   http_response->set_code(net::HTTP_OK);
    239   http_response->set_content(content);
    240   http_response->set_content_type("text/xml");
    241   return http_response.PassAs<net::test_server::HttpResponse>();
    242 }
    243 
    244 bool DoesInstallSuccessReferToId(const std::string& id,
    245                                  const content::NotificationSource& source,
    246                                  const content::NotificationDetails& details) {
    247   return content::Details<const extensions::InstalledExtensionInfo>(details)->
    248       extension->id() == id;
    249 }
    250 
    251 bool DoesInstallFailureReferToId(const std::string& id,
    252                                  const content::NotificationSource& source,
    253                                  const content::NotificationDetails& details) {
    254   return content::Details<const base::string16>(details)->find(UTF8ToUTF16(id)) !=
    255       base::string16::npos;
    256 }
    257 
    258 scoped_ptr<net::FakeURLFetcher> RunCallbackAndReturnFakeURLFetcher(
    259     scoped_refptr<base::SequencedTaskRunner> task_runner,
    260     const base::Closure& callback,
    261     const GURL& url,
    262     net::URLFetcherDelegate* delegate,
    263     const std::string& response_data,
    264     net::HttpStatusCode response_code,
    265     net::URLRequestStatus::Status status) {
    266   task_runner->PostTask(FROM_HERE, callback);
    267   return make_scoped_ptr(new net::FakeURLFetcher(
    268       url, delegate, response_data, response_code, status));
    269 }
    270 
    271 }  // namespace
    272 
    273 class DeviceLocalAccountTest : public DevicePolicyCrosBrowserTest,
    274                                public chromeos::UserManager::Observer {
    275  protected:
    276   DeviceLocalAccountTest()
    277       : user_id_1_(GenerateDeviceLocalAccountUserId(
    278             kAccountId1, DeviceLocalAccount::TYPE_PUBLIC_SESSION)),
    279         user_id_2_(GenerateDeviceLocalAccountUserId(
    280             kAccountId2, DeviceLocalAccount::TYPE_PUBLIC_SESSION)) {}
    281 
    282   virtual ~DeviceLocalAccountTest() {}
    283 
    284   virtual void SetUp() OVERRIDE {
    285     // Configure and start the test server.
    286     scoped_ptr<crypto::RSAPrivateKey> signing_key(
    287         PolicyBuilder::CreateTestSigningKey());
    288     ASSERT_TRUE(test_server_.SetSigningKey(signing_key.get()));
    289     signing_key.reset();
    290     test_server_.RegisterClient(PolicyBuilder::kFakeToken,
    291                                 PolicyBuilder::kFakeDeviceId);
    292     ASSERT_TRUE(test_server_.Start());
    293 
    294     ASSERT_TRUE(extension_cache_root_dir_.CreateUniqueTempDir());
    295     extension_cache_root_dir_override_.reset(new base::ScopedPathOverride(
    296         chromeos::DIR_DEVICE_LOCAL_ACCOUNT_EXTENSIONS,
    297         extension_cache_root_dir_.path()));
    298     ASSERT_TRUE(external_data_cache_dir_.CreateUniqueTempDir());
    299     external_data_cache_dir_override_.reset(new base::ScopedPathOverride(
    300         chromeos::DIR_DEVICE_LOCAL_ACCOUNT_EXTERNAL_DATA,
    301         external_data_cache_dir_.path()));
    302     DevicePolicyCrosBrowserTest::SetUp();
    303   }
    304 
    305   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
    306     DevicePolicyCrosBrowserTest::SetUpCommandLine(command_line);
    307     command_line->AppendSwitch(chromeos::switches::kLoginManager);
    308     command_line->AppendSwitch(chromeos::switches::kForceLoginManagerInTests);
    309     command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile, "user");
    310     command_line->AppendSwitchASCII(
    311         switches::kDeviceManagementUrl, test_server_.GetServiceURL().spec());
    312   }
    313 
    314   virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
    315     DevicePolicyCrosBrowserTest::SetUpInProcessBrowserTestFixture();
    316 
    317     // Clear command-line arguments (but keep command-line switches) so the
    318     // startup pages policy takes effect.
    319     CommandLine* command_line = CommandLine::ForCurrentProcess();
    320     CommandLine::StringVector argv(command_line->argv());
    321     argv.erase(argv.begin() + argv.size() - command_line->GetArgs().size(),
    322                argv.end());
    323     command_line->InitFromArgv(argv);
    324 
    325     InstallOwnerKey();
    326     MarkAsEnterpriseOwned();
    327 
    328     InitializePolicy();
    329   }
    330 
    331   virtual void CleanUpOnMainThread() OVERRIDE {
    332     // This shuts down the login UI.
    333     base::MessageLoop::current()->PostTask(FROM_HERE,
    334                                            base::Bind(&chrome::AttemptExit));
    335     base::RunLoop().RunUntilIdle();
    336   }
    337 
    338   virtual void LocalStateChanged(chromeos::UserManager* user_manager) OVERRIDE {
    339     run_loop_->Quit();
    340   }
    341 
    342   void InitializePolicy() {
    343     device_policy()->policy_data().set_public_key_version(1);
    344     em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
    345     proto.mutable_show_user_names()->set_show_user_names(true);
    346 
    347     device_local_account_policy_.policy_data().set_policy_type(
    348         dm_protocol::kChromePublicAccountPolicyType);
    349     device_local_account_policy_.policy_data().set_username(kAccountId1);
    350     device_local_account_policy_.policy_data().set_settings_entity_id(
    351         kAccountId1);
    352     device_local_account_policy_.policy_data().set_public_key_version(1);
    353     device_local_account_policy_.payload().mutable_userdisplayname()->set_value(
    354         kDisplayName);
    355   }
    356 
    357   void BuildDeviceLocalAccountPolicy() {
    358     device_local_account_policy_.SetDefaultSigningKey();
    359     device_local_account_policy_.Build();
    360   }
    361 
    362   void UploadDeviceLocalAccountPolicy() {
    363     BuildDeviceLocalAccountPolicy();
    364     test_server_.UpdatePolicy(
    365         dm_protocol::kChromePublicAccountPolicyType, kAccountId1,
    366         device_local_account_policy_.payload().SerializeAsString());
    367   }
    368 
    369   void UploadAndInstallDeviceLocalAccountPolicy() {
    370     UploadDeviceLocalAccountPolicy();
    371     session_manager_client()->set_device_local_account_policy(
    372         kAccountId1, device_local_account_policy_.GetBlob());
    373   }
    374 
    375   void AddPublicSessionToDevicePolicy(const std::string& username) {
    376     em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
    377     em::DeviceLocalAccountInfoProto* account =
    378         proto.mutable_device_local_accounts()->add_account();
    379     account->set_account_id(username);
    380     account->set_type(
    381         em::DeviceLocalAccountInfoProto::ACCOUNT_TYPE_PUBLIC_SESSION);
    382     RefreshDevicePolicy();
    383     test_server_.UpdatePolicy(dm_protocol::kChromeDevicePolicyType,
    384                               std::string(), proto.SerializeAsString());
    385   }
    386 
    387   void CheckPublicSessionPresent(const std::string& id) {
    388     const chromeos::User* user = chromeos::UserManager::Get()->FindUser(id);
    389     ASSERT_TRUE(user);
    390     EXPECT_EQ(id, user->email());
    391     EXPECT_EQ(chromeos::User::USER_TYPE_PUBLIC_ACCOUNT, user->GetType());
    392   }
    393 
    394   base::FilePath GetCacheDirectoryForAccountID(const std::string& account_id) {
    395     return extension_cache_root_dir_.path()
    396         .Append(base::HexEncode(account_id.c_str(), account_id.size()));
    397   }
    398 
    399   base::FilePath GetCacheCRXFile(const std::string& account_id,
    400                                  const std::string& id,
    401                                  const std::string& version) {
    402     return GetCacheDirectoryForAccountID(account_id)
    403         .Append(base::StringPrintf("%s-%s.crx", id.c_str(), version.c_str()));
    404   }
    405 
    406   // Returns a profile which can be used for testing.
    407   Profile* GetProfileForTest() {
    408     // Any profile can be used here since this test does not test multi profile.
    409     return ProfileManager::GetActiveUserProfile();
    410   }
    411 
    412   const std::string user_id_1_;
    413   const std::string user_id_2_;
    414 
    415   scoped_ptr<base::RunLoop> run_loop_;
    416 
    417   UserPolicyBuilder device_local_account_policy_;
    418   LocalPolicyTestServer test_server_;
    419 
    420  private:
    421   base::ScopedTempDir extension_cache_root_dir_;
    422   base::ScopedTempDir external_data_cache_dir_;
    423   scoped_ptr<base::ScopedPathOverride> extension_cache_root_dir_override_;
    424   scoped_ptr<base::ScopedPathOverride> external_data_cache_dir_override_;
    425 
    426   DISALLOW_COPY_AND_ASSIGN(DeviceLocalAccountTest);
    427 };
    428 
    429 static bool IsKnownUser(const std::string& account_id) {
    430   return chromeos::UserManager::Get()->IsKnownUser(account_id);
    431 }
    432 
    433 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, LoginScreen) {
    434   AddPublicSessionToDevicePolicy(kAccountId1);
    435   AddPublicSessionToDevicePolicy(kAccountId2);
    436 
    437   content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED,
    438                                         base::Bind(&IsKnownUser, user_id_1_))
    439       .Wait();
    440   content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED,
    441                                         base::Bind(&IsKnownUser, user_id_2_))
    442       .Wait();
    443 
    444   CheckPublicSessionPresent(user_id_1_);
    445   CheckPublicSessionPresent(user_id_2_);
    446 }
    447 
    448 static bool DisplayNameMatches(const std::string& account_id,
    449                                const std::string& display_name) {
    450   const chromeos::User* user =
    451       chromeos::UserManager::Get()->FindUser(account_id);
    452   if (!user || user->display_name().empty())
    453     return false;
    454   EXPECT_EQ(UTF8ToUTF16(display_name), user->display_name());
    455   return true;
    456 }
    457 
    458 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, DisplayName) {
    459   UploadAndInstallDeviceLocalAccountPolicy();
    460   AddPublicSessionToDevicePolicy(kAccountId1);
    461 
    462   content::WindowedNotificationObserver(
    463       chrome::NOTIFICATION_USER_LIST_CHANGED,
    464       base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait();
    465 }
    466 
    467 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, PolicyDownload) {
    468   UploadDeviceLocalAccountPolicy();
    469   AddPublicSessionToDevicePolicy(kAccountId1);
    470 
    471   // Policy for the account is not installed in session_manager_client. Because
    472   // of this, the presence of the display name (which comes from policy) can be
    473   // used as a signal that indicates successful policy download.
    474   content::WindowedNotificationObserver(
    475       chrome::NOTIFICATION_USER_LIST_CHANGED,
    476       base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait();
    477 
    478   // Sanity check: The policy should be present now.
    479   ASSERT_FALSE(session_manager_client()->device_local_account_policy(
    480       kAccountId1).empty());
    481 }
    482 
    483 static bool IsNotKnownUser(const std::string& account_id) {
    484   return !IsKnownUser(account_id);
    485 }
    486 
    487 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, DevicePolicyChange) {
    488   AddPublicSessionToDevicePolicy(kAccountId1);
    489   AddPublicSessionToDevicePolicy(kAccountId2);
    490 
    491   // Wait until the login screen is up.
    492   content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED,
    493                                         base::Bind(&IsKnownUser, user_id_1_))
    494       .Wait();
    495   content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED,
    496                                         base::Bind(&IsKnownUser, user_id_2_))
    497       .Wait();
    498 
    499   // Update policy to remove kAccountId2.
    500   em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
    501   proto.mutable_device_local_accounts()->clear_account();
    502   AddPublicSessionToDevicePolicy(kAccountId1);
    503 
    504   em::ChromeDeviceSettingsProto policy;
    505   policy.mutable_show_user_names()->set_show_user_names(true);
    506   em::DeviceLocalAccountInfoProto* account1 =
    507       policy.mutable_device_local_accounts()->add_account();
    508   account1->set_account_id(kAccountId1);
    509   account1->set_type(
    510       em::DeviceLocalAccountInfoProto::ACCOUNT_TYPE_PUBLIC_SESSION);
    511 
    512   test_server_.UpdatePolicy(dm_protocol::kChromeDevicePolicyType, std::string(),
    513                             policy.SerializeAsString());
    514   g_browser_process->policy_service()->RefreshPolicies(base::Closure());
    515 
    516   // Make sure the second device-local account disappears.
    517   content::WindowedNotificationObserver(
    518       chrome::NOTIFICATION_USER_LIST_CHANGED,
    519       base::Bind(&IsNotKnownUser, user_id_2_)).Wait();
    520 }
    521 
    522 static bool IsSessionStarted() {
    523   return chromeos::UserManager::Get()->IsSessionStarted();
    524 }
    525 
    526 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, StartSession) {
    527   // Specify startup pages.
    528   device_local_account_policy_.payload().mutable_restoreonstartup()->set_value(
    529       SessionStartupPref::kPrefValueURLs);
    530   em::StringListPolicyProto* startup_urls_proto =
    531       device_local_account_policy_.payload().mutable_restoreonstartupurls();
    532   for (size_t i = 0; i < arraysize(kStartupURLs); ++i)
    533     startup_urls_proto->mutable_value()->add_entries(kStartupURLs[i]);
    534   UploadAndInstallDeviceLocalAccountPolicy();
    535   AddPublicSessionToDevicePolicy(kAccountId1);
    536 
    537   // This observes the display name becoming available as this indicates
    538   // device-local account policy is fully loaded, which is a prerequisite for
    539   // successful login.
    540   content::WindowedNotificationObserver(
    541       chrome::NOTIFICATION_USER_LIST_CHANGED,
    542       base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait();
    543 
    544   // Wait for the login UI to be ready.
    545   chromeos::LoginDisplayHostImpl* host =
    546       reinterpret_cast<chromeos::LoginDisplayHostImpl*>(
    547           chromeos::LoginDisplayHostImpl::default_host());
    548   ASSERT_TRUE(host);
    549   chromeos::OobeUI* oobe_ui = host->GetOobeUI();
    550   ASSERT_TRUE(oobe_ui);
    551   base::RunLoop run_loop;
    552   const bool oobe_ui_ready = oobe_ui->IsJSReady(run_loop.QuitClosure());
    553   if (!oobe_ui_ready)
    554     run_loop.Run();
    555 
    556   // Start login into the device-local account.
    557   host->StartSignInScreen(LoginScreenContext());
    558   chromeos::ExistingUserController* controller =
    559       chromeos::ExistingUserController::current_controller();
    560   ASSERT_TRUE(controller);
    561   controller->LoginAsPublicAccount(user_id_1_);
    562 
    563   // Wait for the session to start.
    564   content::WindowedNotificationObserver(chrome::NOTIFICATION_SESSION_STARTED,
    565                                         base::Bind(IsSessionStarted)).Wait();
    566 
    567   // Check that the startup pages specified in policy were opened.
    568   BrowserList* browser_list =
    569     BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH);
    570   EXPECT_EQ(1U, browser_list->size());
    571   Browser* browser = browser_list->get(0);
    572   ASSERT_TRUE(browser);
    573 
    574   TabStripModel* tabs = browser->tab_strip_model();
    575   ASSERT_TRUE(tabs);
    576   int expected_tab_count = static_cast<int>(arraysize(kStartupURLs));
    577   EXPECT_EQ(expected_tab_count, tabs->count());
    578   for (int i = 0; i < expected_tab_count && i < tabs->count(); ++i) {
    579     EXPECT_EQ(GURL(kStartupURLs[i]),
    580               tabs->GetWebContentsAt(i)->GetVisibleURL());
    581   }
    582 }
    583 
    584 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, FullscreenDisallowed) {
    585   UploadAndInstallDeviceLocalAccountPolicy();
    586   AddPublicSessionToDevicePolicy(kAccountId1);
    587 
    588   // This observes the display name becoming available as this indicates
    589   // device-local account policy is fully loaded, which is a prerequisite for
    590   // successful login.
    591   content::WindowedNotificationObserver(
    592       chrome::NOTIFICATION_USER_LIST_CHANGED,
    593       base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait();
    594 
    595   // Wait for the login UI to be ready.
    596   chromeos::LoginDisplayHostImpl* host =
    597       reinterpret_cast<chromeos::LoginDisplayHostImpl*>(
    598           chromeos::LoginDisplayHostImpl::default_host());
    599   ASSERT_TRUE(host);
    600   chromeos::OobeUI* oobe_ui = host->GetOobeUI();
    601   ASSERT_TRUE(oobe_ui);
    602   base::RunLoop run_loop;
    603   const bool oobe_ui_ready = oobe_ui->IsJSReady(run_loop.QuitClosure());
    604   if (!oobe_ui_ready)
    605     run_loop.Run();
    606 
    607   // Ensure that the browser stays alive, even though no windows are opened
    608   // during session start.
    609   chrome::StartKeepAlive();
    610 
    611   // Start login into the device-local account.
    612   host->StartSignInScreen(LoginScreenContext());
    613   chromeos::ExistingUserController* controller =
    614       chromeos::ExistingUserController::current_controller();
    615   ASSERT_TRUE(controller);
    616   controller->LoginAsPublicAccount(user_id_1_);
    617 
    618   // Wait for the session to start.
    619   content::WindowedNotificationObserver(chrome::NOTIFICATION_SESSION_STARTED,
    620                                         base::Bind(IsSessionStarted)).Wait();
    621 
    622   // Open a browser window.
    623   chrome::NewEmptyWindow(GetProfileForTest(), chrome::HOST_DESKTOP_TYPE_ASH);
    624   BrowserList* browser_list =
    625     BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH);
    626   EXPECT_EQ(1U, browser_list->size());
    627   Browser* browser = browser_list->get(0);
    628   ASSERT_TRUE(browser);
    629   BrowserWindow* browser_window = browser->window();
    630   ASSERT_TRUE(browser_window);
    631   chrome::EndKeepAlive();
    632 
    633   // Verify that an attempt to enter fullscreen mode is denied.
    634   EXPECT_FALSE(browser_window->IsFullscreen());
    635   chrome::ToggleFullscreenMode(browser);
    636   EXPECT_FALSE(browser_window->IsFullscreen());
    637 }
    638 
    639 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, ExtensionsUncached) {
    640   // Make it possible to force-install a hosted app and an extension.
    641   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
    642   TestingUpdateManifestProvider testing_update_manifest_provider(
    643       kRelativeUpdateURL);
    644   testing_update_manifest_provider.AddUpdate(
    645       kHostedAppID,
    646       kHostedAppVersion,
    647       embedded_test_server()->GetURL(std::string("/") + kHostedAppCRXPath));
    648   testing_update_manifest_provider.AddUpdate(
    649       kGoodExtensionID,
    650       kGoodExtensionVersion,
    651       embedded_test_server()->GetURL(std::string("/") + kGoodExtensionCRXPath));
    652   embedded_test_server()->RegisterRequestHandler(
    653       base::Bind(&TestingUpdateManifestProvider::HandleRequest,
    654                  base::Unretained(&testing_update_manifest_provider)));
    655 
    656   // Specify policy to force-install the hosted app and the extension.
    657   em::StringList* forcelist = device_local_account_policy_.payload()
    658       .mutable_extensioninstallforcelist()->mutable_value();
    659   forcelist->add_entries(base::StringPrintf(
    660       "%s;%s",
    661       kHostedAppID,
    662       embedded_test_server()->GetURL(kRelativeUpdateURL).spec().c_str()));
    663   forcelist->add_entries(base::StringPrintf(
    664       "%s;%s",
    665       kGoodExtensionID,
    666       embedded_test_server()->GetURL(kRelativeUpdateURL).spec().c_str()));
    667 
    668   UploadAndInstallDeviceLocalAccountPolicy();
    669   AddPublicSessionToDevicePolicy(kAccountId1);
    670 
    671   // This observes the display name becoming available as this indicates
    672   // device-local account policy is fully loaded, which is a prerequisite for
    673   // successful login.
    674   content::WindowedNotificationObserver(
    675       chrome::NOTIFICATION_USER_LIST_CHANGED,
    676       base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait();
    677 
    678   // Wait for the login UI to be ready.
    679   chromeos::LoginDisplayHostImpl* host =
    680       reinterpret_cast<chromeos::LoginDisplayHostImpl*>(
    681           chromeos::LoginDisplayHostImpl::default_host());
    682   ASSERT_TRUE(host);
    683   chromeos::OobeUI* oobe_ui = host->GetOobeUI();
    684   ASSERT_TRUE(oobe_ui);
    685   base::RunLoop run_loop;
    686   const bool oobe_ui_ready = oobe_ui->IsJSReady(run_loop.QuitClosure());
    687   if (!oobe_ui_ready)
    688     run_loop.Run();
    689 
    690   // Ensure that the browser stays alive, even though no windows are opened
    691   // during session start.
    692   chrome::StartKeepAlive();
    693 
    694   // Start listening for app/extension installation results.
    695   content::WindowedNotificationObserver hosted_app_observer(
    696       chrome::NOTIFICATION_EXTENSION_INSTALLED,
    697       base::Bind(DoesInstallSuccessReferToId, kHostedAppID));
    698   content::WindowedNotificationObserver extension_observer(
    699       chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR,
    700       base::Bind(DoesInstallFailureReferToId, kGoodExtensionID));
    701 
    702   // Start login into the device-local account.
    703   host->StartSignInScreen(LoginScreenContext());
    704   chromeos::ExistingUserController* controller =
    705       chromeos::ExistingUserController::current_controller();
    706   ASSERT_TRUE(controller);
    707   controller->LoginAsPublicAccount(user_id_1_);
    708 
    709   // Wait for the hosted app installation to succeed and the extension
    710   // installation to fail (because hosted apps are whitelisted for use in
    711   // device-local accounts and extensions are not).
    712   hosted_app_observer.Wait();
    713   extension_observer.Wait();
    714 
    715   // Verify that the hosted app was installed.
    716   Profile* profile = GetProfileForTest();
    717   ASSERT_TRUE(profile);
    718   ExtensionService* extension_service =
    719       extensions::ExtensionSystem::Get(profile)->extension_service();
    720   EXPECT_TRUE(extension_service->GetExtensionById(kHostedAppID, true));
    721 
    722   // Verify that the extension was not installed.
    723   EXPECT_FALSE(extension_service->GetExtensionById(kGoodExtensionID, true));
    724 
    725   // Verify that the app was copied to the account's extension cache.
    726   base::FilePath test_dir;
    727   ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir));
    728   EXPECT_TRUE(ContentsEqual(
    729           GetCacheCRXFile(kAccountId1, kHostedAppID, kHostedAppVersion),
    730           test_dir.Append(kHostedAppCRXPath)));
    731 
    732   // Verify that the extension was not copied to the account's extension cache.
    733   EXPECT_FALSE(PathExists(GetCacheCRXFile(
    734       kAccountId1, kGoodExtensionID, kGoodExtensionVersion)));
    735 }
    736 
    737 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, ExtensionsCached) {
    738   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
    739 
    740   // Pre-populate the device local account's extension cache with a hosted app
    741   // and an extension.
    742   EXPECT_TRUE(base::CreateDirectory(
    743       GetCacheDirectoryForAccountID(kAccountId1)));
    744   base::FilePath test_dir;
    745   ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir));
    746   const base::FilePath cached_hosted_app =
    747       GetCacheCRXFile(kAccountId1, kHostedAppID, kHostedAppVersion);
    748   EXPECT_TRUE(CopyFile(test_dir.Append(kHostedAppCRXPath),
    749                        cached_hosted_app));
    750   const base::FilePath cached_extension =
    751       GetCacheCRXFile(kAccountId1, kGoodExtensionID, kGoodExtensionVersion);
    752   EXPECT_TRUE(CopyFile(test_dir.Append(kGoodExtensionCRXPath),
    753                        cached_extension));
    754 
    755   // Specify policy to force-install the hosted app.
    756   em::StringList* forcelist = device_local_account_policy_.payload()
    757       .mutable_extensioninstallforcelist()->mutable_value();
    758   forcelist->add_entries(base::StringPrintf(
    759       "%s;%s",
    760       kHostedAppID,
    761       embedded_test_server()->GetURL(kRelativeUpdateURL).spec().c_str()));
    762   forcelist->add_entries(base::StringPrintf(
    763       "%s;%s",
    764       kGoodExtensionID,
    765       embedded_test_server()->GetURL(kRelativeUpdateURL).spec().c_str()));
    766 
    767   UploadAndInstallDeviceLocalAccountPolicy();
    768   AddPublicSessionToDevicePolicy(kAccountId1);
    769 
    770   // This observes the display name becoming available as this indicates
    771   // device-local account policy is fully loaded, which is a prerequisite for
    772   // successful login.
    773   content::WindowedNotificationObserver(
    774       chrome::NOTIFICATION_USER_LIST_CHANGED,
    775       base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait();
    776 
    777   // Wait for the login UI to be ready.
    778   chromeos::LoginDisplayHostImpl* host =
    779       reinterpret_cast<chromeos::LoginDisplayHostImpl*>(
    780           chromeos::LoginDisplayHostImpl::default_host());
    781   ASSERT_TRUE(host);
    782   chromeos::OobeUI* oobe_ui = host->GetOobeUI();
    783   ASSERT_TRUE(oobe_ui);
    784   base::RunLoop run_loop;
    785   const bool oobe_ui_ready = oobe_ui->IsJSReady(run_loop.QuitClosure());
    786   if (!oobe_ui_ready)
    787     run_loop.Run();
    788 
    789   // Ensure that the browser stays alive, even though no windows are opened
    790   // during session start.
    791   chrome::StartKeepAlive();
    792 
    793   // Start listening for app/extension installation results.
    794   content::WindowedNotificationObserver hosted_app_observer(
    795       chrome::NOTIFICATION_EXTENSION_INSTALLED,
    796       base::Bind(DoesInstallSuccessReferToId, kHostedAppID));
    797   content::WindowedNotificationObserver extension_observer(
    798       chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR,
    799       base::Bind(DoesInstallFailureReferToId, kGoodExtensionID));
    800 
    801   // Start login into the device-local account.
    802   host->StartSignInScreen(LoginScreenContext());
    803   chromeos::ExistingUserController* controller =
    804       chromeos::ExistingUserController::current_controller();
    805   ASSERT_TRUE(controller);
    806   controller->LoginAsPublicAccount(user_id_1_);
    807 
    808   // Wait for the hosted app installation to succeed and the extension
    809   // installation to fail.
    810   hosted_app_observer.Wait();
    811   extension_observer.Wait();
    812 
    813   // Verify that the hosted app was installed.
    814   Profile* profile = GetProfileForTest();
    815   ASSERT_TRUE(profile);
    816   ExtensionService* extension_service =
    817       extensions::ExtensionSystem::Get(profile)->extension_service();
    818   EXPECT_TRUE(extension_service->GetExtensionById(kHostedAppID, true));
    819 
    820   // Verify that the extension was not installed.
    821   EXPECT_FALSE(extension_service->GetExtensionById(kGoodExtensionID, true));
    822 
    823   // Verify that the app is still in the account's extension cache.
    824   EXPECT_TRUE(PathExists(cached_hosted_app));
    825 
    826   // Verify that the extension was removed from the account's extension cache.
    827   EXPECT_FALSE(PathExists(cached_extension));
    828 }
    829 
    830 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, ExternalData) {
    831   // chromeos::UserImageManagerImpl requests an external data fetch whenever the
    832   // key::kUserAvatarImage policy is set. Since this test wants to verify that
    833   // the underlying policy subsystem will start a fetch without this request as
    834   // well, the chromeos::UserImageManagerImpl must be prevented from seeing the
    835   // policy change.
    836   reinterpret_cast<chromeos::UserImageManagerImpl*>(
    837       chromeos::UserManager::Get()->GetUserImageManager())->
    838           StopPolicyObserverForTesting();
    839 
    840   UploadDeviceLocalAccountPolicy();
    841   AddPublicSessionToDevicePolicy(kAccountId1);
    842 
    843   // This observes the display name becoming available as this indicates
    844   // device-local account policy is fully loaded.
    845   content::WindowedNotificationObserver(
    846       chrome::NOTIFICATION_USER_LIST_CHANGED,
    847       base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait();
    848 
    849   // Start serving external data at |kExternalDataURL|.
    850   scoped_ptr<base::RunLoop> run_loop(new base::RunLoop);
    851   scoped_ptr<net::FakeURLFetcherFactory> fetcher_factory(
    852       new net::FakeURLFetcherFactory(
    853           NULL,
    854           base::Bind(&RunCallbackAndReturnFakeURLFetcher,
    855                      base::MessageLoopProxy::current(),
    856                      run_loop->QuitClosure())));
    857   fetcher_factory->SetFakeResponse(GURL(kExternalDataURL),
    858                                    kExternalData,
    859                                    net::HTTP_OK,
    860                                    net::URLRequestStatus::SUCCESS);
    861 
    862   // Specify an external data reference for the key::kUserAvatarImage policy.
    863   scoped_ptr<base::DictionaryValue> metadata =
    864       test::ConstructExternalDataReference(kExternalDataURL, kExternalData);
    865   std::string policy;
    866   base::JSONWriter::Write(metadata.get(), &policy);
    867   device_local_account_policy_.payload().mutable_useravatarimage()->set_value(
    868       policy);
    869   UploadAndInstallDeviceLocalAccountPolicy();
    870   DeviceLocalAccountPolicyBroker* broker =
    871       g_browser_process->browser_policy_connector()->
    872           GetDeviceLocalAccountPolicyService()->GetBrokerForUser(user_id_1_);
    873   ASSERT_TRUE(broker);
    874   broker->core()->store()->Load();
    875 
    876   // The external data should be fetched and cached automatically. Wait for this
    877   // fetch.
    878   run_loop->Run();
    879 
    880   // Stop serving external data at |kExternalDataURL|.
    881   fetcher_factory.reset();
    882 
    883   const PolicyMap::Entry* policy_entry =
    884       broker->core()->store()->policy_map().Get(key::kUserAvatarImage);
    885   ASSERT_TRUE(policy_entry);
    886   ASSERT_TRUE(policy_entry->external_data_fetcher);
    887 
    888   // Retrieve the external data. Although the data is no longer being served at
    889   // |kExternalDataURL|, the retrieval should succeed because the data has been
    890   // cached.
    891   run_loop.reset(new base::RunLoop);
    892   scoped_ptr<std::string> fetched_external_data;
    893   policy_entry->external_data_fetcher->Fetch(base::Bind(
    894       &test::ExternalDataFetchCallback,
    895       &fetched_external_data,
    896       run_loop->QuitClosure()));
    897   run_loop->Run();
    898 
    899   ASSERT_TRUE(fetched_external_data);
    900   EXPECT_EQ(kExternalData, *fetched_external_data);
    901 
    902   // Wait for the login UI to be ready.
    903   chromeos::LoginDisplayHostImpl* host =
    904       reinterpret_cast<chromeos::LoginDisplayHostImpl*>(
    905           chromeos::LoginDisplayHostImpl::default_host());
    906   ASSERT_TRUE(host);
    907   chromeos::OobeUI* oobe_ui = host->GetOobeUI();
    908   ASSERT_TRUE(oobe_ui);
    909   run_loop.reset(new base::RunLoop);
    910   const bool oobe_ui_ready = oobe_ui->IsJSReady(run_loop->QuitClosure());
    911   if (!oobe_ui_ready)
    912     run_loop->Run();
    913 
    914   // Ensure that the browser stays alive, even though no windows are opened
    915   // during session start.
    916   chrome::StartKeepAlive();
    917 
    918   // Start login into the device-local account.
    919   host->StartSignInScreen(LoginScreenContext());
    920   chromeos::ExistingUserController* controller =
    921       chromeos::ExistingUserController::current_controller();
    922   ASSERT_TRUE(controller);
    923   controller->LoginAsPublicAccount(user_id_1_);
    924 
    925   // Wait for the session to start.
    926   content::WindowedNotificationObserver(chrome::NOTIFICATION_SESSION_STARTED,
    927                                         base::Bind(IsSessionStarted)).Wait();
    928 
    929   // Verify that the external data reference has propagated to the device-local
    930   // account's ProfilePolicyConnector.
    931   ProfilePolicyConnector* policy_connector =
    932       ProfilePolicyConnectorFactory::GetForProfile(GetProfileForTest());
    933   ASSERT_TRUE(policy_connector);
    934   const PolicyMap& policies = policy_connector->policy_service()->GetPolicies(
    935       PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()));
    936   policy_entry = policies.Get(key::kUserAvatarImage);
    937   ASSERT_TRUE(policy_entry);
    938   EXPECT_TRUE(base::Value::Equals(metadata.get(), policy_entry->value));
    939   ASSERT_TRUE(policy_entry->external_data_fetcher);
    940 
    941   // Retrieve the external data via the ProfilePolicyConnector. The retrieval
    942   // should succeed because the data has been cached.
    943   run_loop.reset(new base::RunLoop);
    944   fetched_external_data.reset();
    945   policy_entry->external_data_fetcher->Fetch(base::Bind(
    946       &test::ExternalDataFetchCallback,
    947       &fetched_external_data,
    948       run_loop->QuitClosure()));
    949   run_loop->Run();
    950 
    951   ASSERT_TRUE(fetched_external_data);
    952   EXPECT_EQ(kExternalData, *fetched_external_data);
    953 }
    954 
    955 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, UserAvatarImage) {
    956   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
    957 
    958   UploadDeviceLocalAccountPolicy();
    959   AddPublicSessionToDevicePolicy(kAccountId1);
    960 
    961   // This observes the display name becoming available as this indicates
    962   // device-local account policy is fully loaded.
    963   content::WindowedNotificationObserver(
    964       chrome::NOTIFICATION_USER_LIST_CHANGED,
    965       base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait();
    966 
    967   base::FilePath test_dir;
    968   ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir));
    969   std::string image_data;
    970   ASSERT_TRUE(base::ReadFileToString(
    971       test_dir.Append(chromeos::test::kUserAvatarImage1RelativePath),
    972       &image_data));
    973 
    974   std::string policy;
    975   base::JSONWriter::Write(test::ConstructExternalDataReference(
    976       embedded_test_server()->GetURL(std::string("/") +
    977           chromeos::test::kUserAvatarImage1RelativePath).spec(),
    978       image_data).get(),
    979       &policy);
    980   device_local_account_policy_.payload().mutable_useravatarimage()->set_value(
    981       policy);
    982   UploadAndInstallDeviceLocalAccountPolicy();
    983   DeviceLocalAccountPolicyBroker* broker =
    984       g_browser_process->browser_policy_connector()->
    985           GetDeviceLocalAccountPolicyService()->GetBrokerForUser(user_id_1_);
    986   ASSERT_TRUE(broker);
    987 
    988   run_loop_.reset(new base::RunLoop);
    989   chromeos::UserManager::Get()->AddObserver(this);
    990   broker->core()->store()->Load();
    991   run_loop_->Run();
    992   chromeos::UserManager::Get()->RemoveObserver(this);
    993 
    994   scoped_ptr<gfx::ImageSkia> policy_image = chromeos::test::ImageLoader(
    995       test_dir.Append(chromeos::test::kUserAvatarImage1RelativePath)).Load();
    996   ASSERT_TRUE(policy_image);
    997 
    998   const chromeos::User* user =
    999       chromeos::UserManager::Get()->FindUser(user_id_1_);
   1000   ASSERT_TRUE(user);
   1001 
   1002   base::FilePath user_data_dir;
   1003   ASSERT_TRUE(PathService::Get(chrome::DIR_USER_DATA, &user_data_dir));
   1004   const base::FilePath saved_image_path =
   1005       user_data_dir.Append(user_id_1_).AddExtension("jpg");
   1006 
   1007   EXPECT_FALSE(user->HasDefaultImage());
   1008   EXPECT_EQ(chromeos::User::kExternalImageIndex, user->image_index());
   1009   EXPECT_TRUE(chromeos::test::AreImagesEqual(*policy_image, user->image()));
   1010   const base::DictionaryValue* images_pref =
   1011       g_browser_process->local_state()->GetDictionary("user_image_info");
   1012   ASSERT_TRUE(images_pref);
   1013   const base::DictionaryValue* image_properties;
   1014   ASSERT_TRUE(images_pref->GetDictionaryWithoutPathExpansion(
   1015       user_id_1_,
   1016       &image_properties));
   1017   int image_index;
   1018   std::string image_path;
   1019   ASSERT_TRUE(image_properties->GetInteger("index", &image_index));
   1020   ASSERT_TRUE(image_properties->GetString("path", &image_path));
   1021   EXPECT_EQ(chromeos::User::kExternalImageIndex, image_index);
   1022   EXPECT_EQ(saved_image_path.value(), image_path);
   1023 
   1024   scoped_ptr<gfx::ImageSkia> saved_image =
   1025       chromeos::test::ImageLoader(saved_image_path).Load();
   1026   ASSERT_TRUE(saved_image);
   1027 
   1028   // Check image dimensions. Images can't be compared since JPEG is lossy.
   1029   EXPECT_EQ(policy_image->width(), saved_image->width());
   1030   EXPECT_EQ(policy_image->height(), saved_image->height());
   1031 }
   1032 
   1033 class TermsOfServiceTest : public DeviceLocalAccountTest,
   1034                            public testing::WithParamInterface<bool> {
   1035 };
   1036 
   1037 IN_PROC_BROWSER_TEST_P(TermsOfServiceTest, TermsOfServiceScreen) {
   1038   // Specify Terms of Service URL.
   1039   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
   1040   device_local_account_policy_.payload().mutable_termsofserviceurl()->set_value(
   1041       embedded_test_server()->GetURL(
   1042             std::string("/") +
   1043                 (GetParam() ? kExistentTermsOfServicePath
   1044                             : kNonexistentTermsOfServicePath)).spec());
   1045   UploadAndInstallDeviceLocalAccountPolicy();
   1046   AddPublicSessionToDevicePolicy(kAccountId1);
   1047 
   1048   // Wait for the device-local account policy to be fully loaded.
   1049   content::WindowedNotificationObserver(
   1050       chrome::NOTIFICATION_USER_LIST_CHANGED,
   1051       base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait();
   1052 
   1053   // Wait for the login UI to be ready.
   1054   chromeos::LoginDisplayHostImpl* host =
   1055       reinterpret_cast<chromeos::LoginDisplayHostImpl*>(
   1056           chromeos::LoginDisplayHostImpl::default_host());
   1057   ASSERT_TRUE(host);
   1058   chromeos::OobeUI* oobe_ui = host->GetOobeUI();
   1059   ASSERT_TRUE(oobe_ui);
   1060   base::RunLoop oobe_ui_wait_run_loop;
   1061   const bool oobe_ui_ready =
   1062       oobe_ui->IsJSReady(oobe_ui_wait_run_loop.QuitClosure());
   1063   if (!oobe_ui_ready)
   1064     oobe_ui_wait_run_loop.Run();
   1065 
   1066   // Start login into the device-local account.
   1067   host->StartSignInScreen(LoginScreenContext());
   1068   chromeos::ExistingUserController* controller =
   1069       chromeos::ExistingUserController::current_controller();
   1070   ASSERT_TRUE(controller);
   1071   controller->LoginAsPublicAccount(user_id_1_);
   1072 
   1073   // Set up an observer that will quit the message loop when login has succeeded
   1074   // and the first wizard screen, if any, is being shown.
   1075   base::RunLoop login_wait_run_loop;
   1076   chromeos::MockConsumer login_status_consumer;
   1077   EXPECT_CALL(login_status_consumer, OnLoginSuccess(_))
   1078       .Times(1)
   1079       .WillOnce(InvokeWithoutArgs(&login_wait_run_loop, &base::RunLoop::Quit));
   1080 
   1081   // Spin the loop until the observer fires. Then, unregister the observer.
   1082   controller->set_login_status_consumer(&login_status_consumer);
   1083   login_wait_run_loop.Run();
   1084   controller->set_login_status_consumer(NULL);
   1085 
   1086   // Verify that the Terms of Service screen is being shown.
   1087   chromeos::WizardController* wizard_controller =
   1088         chromeos::WizardController::default_controller();
   1089   ASSERT_TRUE(wizard_controller);
   1090   ASSERT_TRUE(wizard_controller->current_screen());
   1091   EXPECT_EQ(chromeos::WizardController::kTermsOfServiceScreenName,
   1092             wizard_controller->current_screen()->GetName());
   1093 
   1094   // Wait for the Terms of Service to finish downloading, then get the status of
   1095   // the screen's UI elements.
   1096   chromeos::WebUILoginView* web_ui_login_view = host->GetWebUILoginView();
   1097   ASSERT_TRUE(web_ui_login_view);
   1098   content::WebUI* web_ui = web_ui_login_view->GetWebUI();
   1099   ASSERT_TRUE(web_ui);
   1100   content::WebContents* contents = web_ui->GetWebContents();
   1101   ASSERT_TRUE(contents);
   1102   std::string json;
   1103   ASSERT_TRUE(content::ExecuteScriptAndExtractString(contents,
   1104       "var screen = document.getElementById('terms-of-service');"
   1105       "function SendReplyIfDownloadDone() {"
   1106       "  if (screen.classList.contains('tos-loading'))"
   1107       "    return false;"
   1108       "  var status = {};"
   1109       "  status.heading = document.getElementById('tos-heading').textContent;"
   1110       "  status.subheading ="
   1111       "      document.getElementById('tos-subheading').textContent;"
   1112       "  status.contentHeading ="
   1113       "      document.getElementById('tos-content-heading').textContent;"
   1114       "  status.content ="
   1115       "      document.getElementById('tos-content-main').textContent;"
   1116       "  status.error = screen.classList.contains('error');"
   1117       "  status.acceptEnabled ="
   1118       "      !document.getElementById('tos-accept-button').disabled;"
   1119       "  domAutomationController.send(JSON.stringify(status));"
   1120       "  observer.disconnect();"
   1121       "  return true;"
   1122       "}"
   1123       "var observer = new MutationObserver(SendReplyIfDownloadDone);"
   1124       "if (!SendReplyIfDownloadDone()) {"
   1125       "  var options = { attributes: true, attributeFilter: [ 'class' ] };"
   1126       "  observer.observe(screen, options);"
   1127       "}",
   1128       &json));
   1129   scoped_ptr<base::Value> value_ptr(base::JSONReader::Read(json));
   1130   const base::DictionaryValue* status = NULL;
   1131   ASSERT_TRUE(value_ptr.get());
   1132   ASSERT_TRUE(value_ptr->GetAsDictionary(&status));
   1133   std::string heading;
   1134   EXPECT_TRUE(status->GetString("heading", &heading));
   1135   std::string subheading;
   1136   EXPECT_TRUE(status->GetString("subheading", &subheading));
   1137   std::string content_heading;
   1138   EXPECT_TRUE(status->GetString("contentHeading", &content_heading));
   1139   std::string content;
   1140   EXPECT_TRUE(status->GetString("content", &content));
   1141   bool error;
   1142   EXPECT_TRUE(status->GetBoolean("error", &error));
   1143   bool accept_enabled;
   1144   EXPECT_TRUE(status->GetBoolean("acceptEnabled", &accept_enabled));
   1145 
   1146   // Verify that the screen's headings have been set correctly.
   1147   EXPECT_EQ(
   1148       l10n_util::GetStringFUTF8(IDS_TERMS_OF_SERVICE_SCREEN_HEADING,
   1149                                 UTF8ToUTF16(kDomain)),
   1150       heading);
   1151   EXPECT_EQ(
   1152       l10n_util::GetStringFUTF8(IDS_TERMS_OF_SERVICE_SCREEN_SUBHEADING,
   1153                                 UTF8ToUTF16(kDomain)),
   1154       subheading);
   1155   EXPECT_EQ(
   1156       l10n_util::GetStringFUTF8(IDS_TERMS_OF_SERVICE_SCREEN_CONTENT_HEADING,
   1157                                 UTF8ToUTF16(kDomain)),
   1158       content_heading);
   1159 
   1160   if (!GetParam()) {
   1161     // The Terms of Service URL was invalid. Verify that the screen is showing
   1162     // an error and the accept button is disabled.
   1163     EXPECT_TRUE(error);
   1164     EXPECT_FALSE(accept_enabled);
   1165     return;
   1166   }
   1167 
   1168   // The Terms of Service URL was valid. Verify that the screen is showing the
   1169   // downloaded Terms of Service and the accept button is enabled.
   1170   base::FilePath test_dir;
   1171   ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir));
   1172   std::string terms_of_service;
   1173   ASSERT_TRUE(base::ReadFileToString(
   1174       test_dir.Append(kExistentTermsOfServicePath), &terms_of_service));
   1175   EXPECT_EQ(terms_of_service, content);
   1176   EXPECT_FALSE(error);
   1177   EXPECT_TRUE(accept_enabled);
   1178 
   1179   // Click the accept button.
   1180   ASSERT_TRUE(content::ExecuteScript(contents,
   1181                                      "$('tos-accept-button').click();"));
   1182 
   1183   // Wait for the session to start.
   1184   if (!IsSessionStarted()) {
   1185     content::WindowedNotificationObserver(chrome::NOTIFICATION_SESSION_STARTED,
   1186                                           base::Bind(IsSessionStarted)).Wait();
   1187   }
   1188 }
   1189 
   1190 INSTANTIATE_TEST_CASE_P(TermsOfServiceTestInstance,
   1191                         TermsOfServiceTest, testing::Bool());
   1192 
   1193 }  // namespace policy
   1194