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