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