- add sources.
[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/memory/scoped_ptr.h"
18 #include "base/message_loop/message_loop.h"
19 #include "base/path_service.h"
20 #include "base/run_loop.h"
21 #include "base/strings/string_number_conversions.h"
22 #include "base/strings/string_util.h"
23 #include "base/strings/stringprintf.h"
24 #include "base/strings/utf_string_conversions.h"
25 #include "base/test/scoped_path_override.h"
26 #include "base/values.h"
27 #include "chrome/browser/browser_process.h"
28 #include "chrome/browser/chrome_notification_types.h"
29 #include "chrome/browser/chromeos/login/existing_user_controller.h"
30 #include "chrome/browser/chromeos/login/login_display_host.h"
31 #include "chrome/browser/chromeos/login/login_display_host_impl.h"
32 #include "chrome/browser/chromeos/login/mock_login_status_consumer.h"
33 #include "chrome/browser/chromeos/login/screens/wizard_screen.h"
34 #include "chrome/browser/chromeos/login/user.h"
35 #include "chrome/browser/chromeos/login/user_manager.h"
36 #include "chrome/browser/chromeos/login/webui_login_view.h"
37 #include "chrome/browser/chromeos/login/wizard_controller.h"
38 #include "chrome/browser/chromeos/policy/device_local_account.h"
39 #include "chrome/browser/chromeos/policy/device_policy_builder.h"
40 #include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h"
41 #include "chrome/browser/extensions/extension_service.h"
42 #include "chrome/browser/extensions/extension_system.h"
43 #include "chrome/browser/lifetime/application_lifetime.h"
44 #include "chrome/browser/policy/cloud/cloud_policy_constants.h"
45 #include "chrome/browser/policy/cloud/policy_builder.h"
46 #include "chrome/browser/policy/policy_service.h"
47 #include "chrome/browser/policy/proto/chromeos/chrome_device_policy.pb.h"
48 #include "chrome/browser/policy/test/local_policy_test_server.h"
49 #include "chrome/browser/prefs/session_startup_pref.h"
50 #include "chrome/browser/profiles/profile.h"
51 #include "chrome/browser/profiles/profile_manager.h"
52 #include "chrome/browser/ui/browser.h"
53 #include "chrome/browser/ui/browser_commands.h"
54 #include "chrome/browser/ui/browser_finder.h"
55 #include "chrome/browser/ui/browser_list.h"
56 #include "chrome/browser/ui/browser_window.h"
57 #include "chrome/browser/ui/host_desktop.h"
58 #include "chrome/browser/ui/tabs/tab_strip_model.h"
59 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
60 #include "chrome/common/chrome_paths.h"
61 #include "chrome/common/chrome_switches.h"
62 #include "chrome/common/extensions/extension.h"
63 #include "chromeos/chromeos_paths.h"
64 #include "chromeos/chromeos_switches.h"
65 #include "chromeos/dbus/cryptohome_client.h"
66 #include "chromeos/dbus/dbus_method_call_status.h"
67 #include "chromeos/dbus/fake_session_manager_client.h"
68 #include "chromeos/dbus/session_manager_client.h"
69 #include "content/public/browser/notification_details.h"
70 #include "content/public/browser/notification_source.h"
71 #include "content/public/browser/web_contents.h"
72 #include "content/public/browser/web_ui.h"
73 #include "content/public/test/browser_test_utils.h"
74 #include "content/public/test/test_utils.h"
75 #include "crypto/rsa_private_key.h"
76 #include "grit/chromium_strings.h"
77 #include "grit/generated_resources.h"
78 #include "net/base/url_util.h"
79 #include "net/http/http_status_code.h"
80 #include "net/test/embedded_test_server/embedded_test_server.h"
81 #include "net/test/embedded_test_server/http_request.h"
82 #include "net/test/embedded_test_server/http_response.h"
83 #include "testing/gmock/include/gmock/gmock.h"
84 #include "third_party/cros_system_api/dbus/service_constants.h"
85 #include "ui/base/l10n/l10n_util.h"
86 #include "url/gurl.h"
87
88 namespace em = enterprise_management;
89
90 using testing::InvokeWithoutArgs;
91 using testing::Return;
92 using testing::_;
93
94 namespace policy {
95
96 namespace {
97
98 const char kDomain[] = "example.com";
99 const char kAccountId1[] = "dla1@example.com";
100 const char kAccountId2[] = "dla2@example.com";
101 const char kDisplayName[] = "display name";
102 const char* kStartupURLs[] = {
103   "chrome://policy",
104   "chrome://about",
105 };
106 const char kExistentTermsOfServicePath[] = "chromeos/enterprise/tos.txt";
107 const char kNonexistentTermsOfServicePath[] = "chromeos/enterprise/tos404.txt";
108 const char kRelativeUpdateURL[] = "/service/update2/crx";
109 const char kUpdateManifestHeader[] =
110     "<?xml version='1.0' encoding='UTF-8'?>\n"
111     "<gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'>\n";
112 const char kUpdateManifestTemplate[] =
113     "  <app appid='%s'>\n"
114     "    <updatecheck codebase='%s' version='%s' />\n"
115     "  </app>\n";
116 const char kUpdateManifestFooter[] =
117     "</gupdate>\n";
118 const char kHostedAppID[] = "kbmnembihfiondgfjekmnmcbddelicoi";
119 const char kHostedAppCRXPath[] = "extensions/hosted_app.crx";
120 const char kHostedAppVersion[] = "1.0.0.0";
121 const char kGoodExtensionID[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf";
122 const char kGoodExtensionCRXPath[] = "extensions/good.crx";
123 const char kGoodExtensionVersion[] = "1.0";
124
125 // Helper that serves extension update manifests to Chrome.
126 class TestingUpdateManifestProvider {
127  public:
128
129   // Update manifests will be served at |relative_update_url|.
130   explicit TestingUpdateManifestProvider(
131       const std::string& relative_update_url);
132   ~TestingUpdateManifestProvider();
133
134   // When an update manifest is requested for the given extension |id|, indicate
135   // that |version| of the extension can be downloaded at |crx_url|.
136   void AddUpdate(const std::string& id,
137                  const std::string& version,
138                  const GURL& crx_url);
139
140   // This method must be registered with the test's EmbeddedTestServer to start
141   // serving update manifests.
142   scoped_ptr<net::test_server::HttpResponse> HandleRequest(
143       const net::test_server::HttpRequest& request);
144
145  private:
146   struct Update {
147    public:
148     Update(const std::string& version, const GURL& crx_url);
149     Update();
150
151     std::string version;
152     GURL crx_url;
153   };
154   typedef std::map<std::string, Update> UpdateMap;
155   UpdateMap updates_;
156
157   const std::string relative_update_url_;
158
159   DISALLOW_COPY_AND_ASSIGN(TestingUpdateManifestProvider);
160 };
161
162 TestingUpdateManifestProvider::Update::Update(const std::string& version,
163                                               const GURL& crx_url)
164     : version(version),
165       crx_url(crx_url) {
166 }
167
168 TestingUpdateManifestProvider::Update::Update() {
169 }
170
171 TestingUpdateManifestProvider::TestingUpdateManifestProvider(
172     const std::string& relative_update_url)
173     : relative_update_url_(relative_update_url) {
174 }
175
176 TestingUpdateManifestProvider::~TestingUpdateManifestProvider() {
177 }
178
179 void TestingUpdateManifestProvider::AddUpdate(const std::string& id,
180                                               const std::string& version,
181                                               const GURL& crx_url) {
182   updates_[id] = Update(version, crx_url);
183 }
184
185 scoped_ptr<net::test_server::HttpResponse>
186     TestingUpdateManifestProvider::HandleRequest(
187         const net::test_server::HttpRequest& request) {
188   const GURL url("http://localhost" + request.relative_url);
189   if (url.path() != relative_update_url_)
190     return scoped_ptr<net::test_server::HttpResponse>();
191
192   std::string content = kUpdateManifestHeader;
193   for (net::QueryIterator it(url); !it.IsAtEnd(); it.Advance()) {
194     if (it.GetKey() != "x")
195       continue;
196     // Extract the extension id from the subquery. Since GetValueForKeyInQuery()
197     // expects a complete URL, dummy scheme and host must be prepended.
198     std::string id;
199     net::GetValueForKeyInQuery(GURL("http://dummy?" + it.GetUnescapedValue()),
200                                "id", &id);
201     UpdateMap::const_iterator entry = updates_.find(id);
202     if (entry != updates_.end()) {
203       content += base::StringPrintf(kUpdateManifestTemplate,
204                                     id.c_str(),
205                                     entry->second.crx_url.spec().c_str(),
206                                     entry->second.version.c_str());
207     }
208   }
209   content += kUpdateManifestFooter;
210   scoped_ptr<net::test_server::BasicHttpResponse>
211       http_response(new net::test_server::BasicHttpResponse);
212   http_response->set_code(net::HTTP_OK);
213   http_response->set_content(content);
214   http_response->set_content_type("text/xml");
215   return http_response.PassAs<net::test_server::HttpResponse>();
216 }
217
218 bool DoesInstallSuccessReferToId(const std::string& id,
219                                  const content::NotificationSource& source,
220                                  const content::NotificationDetails& details) {
221   return content::Details<const extensions::InstalledExtensionInfo>(details)->
222       extension->id() == id;
223 }
224
225 bool DoesInstallFailureReferToId(const std::string& id,
226                                  const content::NotificationSource& source,
227                                  const content::NotificationDetails& details) {
228   return content::Details<const string16>(details)->find(UTF8ToUTF16(id)) !=
229       string16::npos;
230 }
231
232 }  // namespace
233
234 class DeviceLocalAccountTest : public DevicePolicyCrosBrowserTest {
235  protected:
236   DeviceLocalAccountTest()
237       : user_id_1_(GenerateDeviceLocalAccountUserId(
238             kAccountId1, DeviceLocalAccount::TYPE_PUBLIC_SESSION)),
239         user_id_2_(GenerateDeviceLocalAccountUserId(
240             kAccountId2, DeviceLocalAccount::TYPE_PUBLIC_SESSION)) {}
241
242   virtual ~DeviceLocalAccountTest() {}
243
244   virtual void SetUp() OVERRIDE {
245     // Configure and start the test server.
246     scoped_ptr<crypto::RSAPrivateKey> signing_key(
247         PolicyBuilder::CreateTestSigningKey());
248     ASSERT_TRUE(test_server_.SetSigningKey(signing_key.get()));
249     signing_key.reset();
250     test_server_.RegisterClient(PolicyBuilder::kFakeToken,
251                                 PolicyBuilder::kFakeDeviceId);
252     ASSERT_TRUE(test_server_.Start());
253
254     ASSERT_TRUE(extension_cache_root_dir_.CreateUniqueTempDir());
255     extension_cache_root_dir_override_.reset(new base::ScopedPathOverride(
256         chromeos::DIR_DEVICE_LOCAL_ACCOUNT_CACHE,
257         extension_cache_root_dir_.path()));
258
259     DevicePolicyCrosBrowserTest::SetUp();
260   }
261
262   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
263     command_line->AppendSwitch(chromeos::switches::kLoginManager);
264     command_line->AppendSwitch(chromeos::switches::kForceLoginManagerInTests);
265     command_line->AppendSwitchASCII(
266         switches::kDeviceManagementUrl, test_server_.GetServiceURL().spec());
267     command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile, "user");
268   }
269
270   virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
271     DevicePolicyCrosBrowserTest::SetUpInProcessBrowserTestFixture();
272
273     // Clear command-line arguments (but keep command-line switches) so the
274     // startup pages policy takes effect.
275     CommandLine* command_line = CommandLine::ForCurrentProcess();
276     CommandLine::StringVector argv(command_line->argv());
277     argv.erase(argv.begin() + argv.size() - command_line->GetArgs().size(),
278                argv.end());
279     command_line->InitFromArgv(argv);
280
281     InstallOwnerKey();
282     MarkAsEnterpriseOwned();
283
284     InitializePolicy();
285   }
286
287   virtual void CleanUpOnMainThread() OVERRIDE {
288     // This shuts down the login UI.
289     base::MessageLoop::current()->PostTask(FROM_HERE,
290                                            base::Bind(&chrome::AttemptExit));
291     base::RunLoop().RunUntilIdle();
292   }
293
294   void InitializePolicy() {
295     device_policy()->policy_data().set_public_key_version(1);
296     em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
297     proto.mutable_show_user_names()->set_show_user_names(true);
298
299     device_local_account_policy_.policy_data().set_policy_type(
300         dm_protocol::kChromePublicAccountPolicyType);
301     device_local_account_policy_.policy_data().set_username(kAccountId1);
302     device_local_account_policy_.policy_data().set_settings_entity_id(
303         kAccountId1);
304     device_local_account_policy_.policy_data().set_public_key_version(1);
305     device_local_account_policy_.payload().mutable_userdisplayname()->set_value(
306         kDisplayName);
307   }
308
309   void BuildDeviceLocalAccountPolicy() {
310     device_local_account_policy_.SetDefaultSigningKey();
311     device_local_account_policy_.Build();
312   }
313
314   void UploadDeviceLocalAccountPolicy() {
315     BuildDeviceLocalAccountPolicy();
316     ASSERT_TRUE(session_manager_client()->device_local_account_policy(
317         kAccountId1).empty());
318     test_server_.UpdatePolicy(
319         dm_protocol::kChromePublicAccountPolicyType, kAccountId1,
320         device_local_account_policy_.payload().SerializeAsString());
321   }
322
323   void UploadAndInstallDeviceLocalAccountPolicy() {
324     UploadDeviceLocalAccountPolicy();
325     session_manager_client()->set_device_local_account_policy(
326         kAccountId1, device_local_account_policy_.GetBlob());
327   }
328
329   void AddPublicSessionToDevicePolicy(const std::string& username) {
330     em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
331     em::DeviceLocalAccountInfoProto* account =
332         proto.mutable_device_local_accounts()->add_account();
333     account->set_account_id(username);
334     account->set_type(
335         em::DeviceLocalAccountInfoProto::ACCOUNT_TYPE_PUBLIC_SESSION);
336     RefreshDevicePolicy();
337     test_server_.UpdatePolicy(dm_protocol::kChromeDevicePolicyType,
338                               std::string(), proto.SerializeAsString());
339   }
340
341   void CheckPublicSessionPresent(const std::string& id) {
342     const chromeos::User* user = chromeos::UserManager::Get()->FindUser(id);
343     ASSERT_TRUE(user);
344     EXPECT_EQ(id, user->email());
345     EXPECT_EQ(chromeos::User::USER_TYPE_PUBLIC_ACCOUNT, user->GetType());
346   }
347
348   base::FilePath GetCacheDirectoryForAccountID(const std::string& account_id) {
349     return extension_cache_root_dir_.path()
350         .Append(base::HexEncode(account_id.c_str(), account_id.size()));
351   }
352
353   base::FilePath GetCacheCRXFile(const std::string& account_id,
354                                  const std::string& id,
355                                  const std::string& version) {
356     return GetCacheDirectoryForAccountID(account_id)
357         .Append(base::StringPrintf("%s-%s.crx", id.c_str(), version.c_str()));
358   }
359
360   const std::string user_id_1_;
361   const std::string user_id_2_;
362
363   base::ScopedTempDir extension_cache_root_dir_;
364   scoped_ptr<base::ScopedPathOverride> extension_cache_root_dir_override_;
365
366   UserPolicyBuilder device_local_account_policy_;
367   LocalPolicyTestServer test_server_;
368 };
369
370 static bool IsKnownUser(const std::string& account_id) {
371   return chromeos::UserManager::Get()->IsKnownUser(account_id);
372 }
373
374 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, LoginScreen) {
375   AddPublicSessionToDevicePolicy(kAccountId1);
376   AddPublicSessionToDevicePolicy(kAccountId2);
377
378   content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED,
379                                         base::Bind(&IsKnownUser, user_id_1_))
380       .Wait();
381   content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED,
382                                         base::Bind(&IsKnownUser, user_id_2_))
383       .Wait();
384
385   CheckPublicSessionPresent(user_id_1_);
386   CheckPublicSessionPresent(user_id_2_);
387 }
388
389 static bool DisplayNameMatches(const std::string& account_id,
390                                const std::string& display_name) {
391   const chromeos::User* user =
392       chromeos::UserManager::Get()->FindUser(account_id);
393   if (!user || user->display_name().empty())
394     return false;
395   EXPECT_EQ(UTF8ToUTF16(display_name), user->display_name());
396   return true;
397 }
398
399 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, DisplayName) {
400   UploadAndInstallDeviceLocalAccountPolicy();
401   AddPublicSessionToDevicePolicy(kAccountId1);
402
403   content::WindowedNotificationObserver(
404       chrome::NOTIFICATION_USER_LIST_CHANGED,
405       base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait();
406 }
407
408 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, PolicyDownload) {
409   UploadDeviceLocalAccountPolicy();
410   AddPublicSessionToDevicePolicy(kAccountId1);
411
412   // Policy for the account is not installed in session_manager_client. Because
413   // of this, the presence of the display name (which comes from policy) can be
414   // used as a signal that indicates successful policy download.
415   content::WindowedNotificationObserver(
416       chrome::NOTIFICATION_USER_LIST_CHANGED,
417       base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait();
418
419   // Sanity check: The policy should be present now.
420   ASSERT_FALSE(session_manager_client()->device_local_account_policy(
421       kAccountId1).empty());
422 }
423
424 static bool IsNotKnownUser(const std::string& account_id) {
425   return !IsKnownUser(account_id);
426 }
427
428 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, DevicePolicyChange) {
429   AddPublicSessionToDevicePolicy(kAccountId1);
430   AddPublicSessionToDevicePolicy(kAccountId2);
431
432   // Wait until the login screen is up.
433   content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED,
434                                         base::Bind(&IsKnownUser, user_id_1_))
435       .Wait();
436   content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED,
437                                         base::Bind(&IsKnownUser, user_id_2_))
438       .Wait();
439
440   // Update policy to remove kAccountId2.
441   em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
442   proto.mutable_device_local_accounts()->clear_account();
443   AddPublicSessionToDevicePolicy(kAccountId1);
444
445   em::ChromeDeviceSettingsProto policy;
446   policy.mutable_show_user_names()->set_show_user_names(true);
447   em::DeviceLocalAccountInfoProto* account1 =
448       policy.mutable_device_local_accounts()->add_account();
449   account1->set_account_id(kAccountId1);
450   account1->set_type(
451       em::DeviceLocalAccountInfoProto::ACCOUNT_TYPE_PUBLIC_SESSION);
452
453   test_server_.UpdatePolicy(dm_protocol::kChromeDevicePolicyType, std::string(),
454                             policy.SerializeAsString());
455   g_browser_process->policy_service()->RefreshPolicies(base::Closure());
456
457   // Make sure the second device-local account disappears.
458   content::WindowedNotificationObserver(
459       chrome::NOTIFICATION_USER_LIST_CHANGED,
460       base::Bind(&IsNotKnownUser, user_id_2_)).Wait();
461 }
462
463 static bool IsSessionStarted() {
464   return chromeos::UserManager::Get()->IsSessionStarted();
465 }
466
467 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, StartSession) {
468   // Specify startup pages.
469   device_local_account_policy_.payload().mutable_restoreonstartup()->set_value(
470       SessionStartupPref::kPrefValueURLs);
471   em::StringListPolicyProto* startup_urls_proto =
472       device_local_account_policy_.payload().mutable_restoreonstartupurls();
473   for (size_t i = 0; i < arraysize(kStartupURLs); ++i)
474     startup_urls_proto->mutable_value()->add_entries(kStartupURLs[i]);
475   UploadAndInstallDeviceLocalAccountPolicy();
476   AddPublicSessionToDevicePolicy(kAccountId1);
477
478   // This observes the display name becoming available as this indicates
479   // device-local account policy is fully loaded, which is a prerequisite for
480   // successful login.
481   content::WindowedNotificationObserver(
482       chrome::NOTIFICATION_USER_LIST_CHANGED,
483       base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait();
484
485   // Wait for the login UI to be ready.
486   chromeos::LoginDisplayHostImpl* host =
487       reinterpret_cast<chromeos::LoginDisplayHostImpl*>(
488           chromeos::LoginDisplayHostImpl::default_host());
489   ASSERT_TRUE(host);
490   chromeos::OobeUI* oobe_ui = host->GetOobeUI();
491   ASSERT_TRUE(oobe_ui);
492   base::RunLoop run_loop;
493   const bool oobe_ui_ready = oobe_ui->IsJSReady(run_loop.QuitClosure());
494   if (!oobe_ui_ready)
495     run_loop.Run();
496
497   // Start login into the device-local account.
498   host->StartSignInScreen();
499   chromeos::ExistingUserController* controller =
500       chromeos::ExistingUserController::current_controller();
501   ASSERT_TRUE(controller);
502   controller->LoginAsPublicAccount(user_id_1_);
503
504   // Wait for the session to start.
505   content::WindowedNotificationObserver(chrome::NOTIFICATION_SESSION_STARTED,
506                                         base::Bind(IsSessionStarted)).Wait();
507
508   // Check that the startup pages specified in policy were opened.
509   BrowserList* browser_list =
510     BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH);
511   EXPECT_EQ(1U, browser_list->size());
512   Browser* browser = browser_list->get(0);
513   ASSERT_TRUE(browser);
514
515   TabStripModel* tabs = browser->tab_strip_model();
516   ASSERT_TRUE(tabs);
517   int expected_tab_count = static_cast<int>(arraysize(kStartupURLs));
518   EXPECT_EQ(expected_tab_count, tabs->count());
519   for (int i = 0; i < expected_tab_count && i < tabs->count(); ++i) {
520     EXPECT_EQ(GURL(kStartupURLs[i]),
521               tabs->GetWebContentsAt(i)->GetVisibleURL());
522   }
523 }
524
525 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, FullscreenDisallowed) {
526   UploadAndInstallDeviceLocalAccountPolicy();
527   AddPublicSessionToDevicePolicy(kAccountId1);
528
529   // This observes the display name becoming available as this indicates
530   // device-local account policy is fully loaded, which is a prerequisite for
531   // successful login.
532   content::WindowedNotificationObserver(
533       chrome::NOTIFICATION_USER_LIST_CHANGED,
534       base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait();
535
536   // Wait for the login UI to be ready.
537   chromeos::LoginDisplayHostImpl* host =
538       reinterpret_cast<chromeos::LoginDisplayHostImpl*>(
539           chromeos::LoginDisplayHostImpl::default_host());
540   ASSERT_TRUE(host);
541   chromeos::OobeUI* oobe_ui = host->GetOobeUI();
542   ASSERT_TRUE(oobe_ui);
543   base::RunLoop run_loop;
544   const bool oobe_ui_ready = oobe_ui->IsJSReady(run_loop.QuitClosure());
545   if (!oobe_ui_ready)
546     run_loop.Run();
547
548   // Ensure that the browser stays alive, even though no windows are opened
549   // during session start.
550   chrome::StartKeepAlive();
551
552   // Start login into the device-local account.
553   host->StartSignInScreen();
554   chromeos::ExistingUserController* controller =
555       chromeos::ExistingUserController::current_controller();
556   ASSERT_TRUE(controller);
557   controller->LoginAsPublicAccount(user_id_1_);
558
559   // Wait for the session to start.
560   content::WindowedNotificationObserver(chrome::NOTIFICATION_SESSION_STARTED,
561                                         base::Bind(IsSessionStarted)).Wait();
562
563   // Open a browser window.
564   chrome::NewEmptyWindow(ProfileManager::GetDefaultProfile(),
565                          chrome::HOST_DESKTOP_TYPE_ASH);
566   BrowserList* browser_list =
567     BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH);
568   EXPECT_EQ(1U, browser_list->size());
569   Browser* browser = browser_list->get(0);
570   ASSERT_TRUE(browser);
571   BrowserWindow* browser_window = browser->window();
572   ASSERT_TRUE(browser_window);
573   chrome::EndKeepAlive();
574
575   // Verify that an attempt to enter fullscreen mode is denied.
576   EXPECT_FALSE(browser_window->IsFullscreen());
577   chrome::ToggleFullscreenMode(browser);
578   EXPECT_FALSE(browser_window->IsFullscreen());
579 }
580
581 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, ExtensionsUncached) {
582   // Make it possible to force-install a hosted app and an extension.
583   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
584   TestingUpdateManifestProvider testing_update_manifest_provider(
585       kRelativeUpdateURL);
586   testing_update_manifest_provider.AddUpdate(
587       kHostedAppID,
588       kHostedAppVersion,
589       embedded_test_server()->GetURL(std::string("/") + kHostedAppCRXPath));
590   testing_update_manifest_provider.AddUpdate(
591       kGoodExtensionID,
592       kGoodExtensionVersion,
593       embedded_test_server()->GetURL(std::string("/") + kGoodExtensionCRXPath));
594   embedded_test_server()->RegisterRequestHandler(
595       base::Bind(&TestingUpdateManifestProvider::HandleRequest,
596                  base::Unretained(&testing_update_manifest_provider)));
597
598   // Specify policy to force-install the hosted app and the extension.
599   em::StringList* forcelist = device_local_account_policy_.payload()
600       .mutable_extensioninstallforcelist()->mutable_value();
601   forcelist->add_entries(base::StringPrintf(
602       "%s;%s",
603       kHostedAppID,
604       embedded_test_server()->GetURL(kRelativeUpdateURL).spec().c_str()));
605   forcelist->add_entries(base::StringPrintf(
606       "%s;%s",
607       kGoodExtensionID,
608       embedded_test_server()->GetURL(kRelativeUpdateURL).spec().c_str()));
609
610   UploadAndInstallDeviceLocalAccountPolicy();
611   AddPublicSessionToDevicePolicy(kAccountId1);
612
613   // This observes the display name becoming available as this indicates
614   // device-local account policy is fully loaded, which is a prerequisite for
615   // successful login.
616   content::WindowedNotificationObserver(
617       chrome::NOTIFICATION_USER_LIST_CHANGED,
618       base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait();
619
620   // Wait for the login UI to be ready.
621   chromeos::LoginDisplayHostImpl* host =
622       reinterpret_cast<chromeos::LoginDisplayHostImpl*>(
623           chromeos::LoginDisplayHostImpl::default_host());
624   ASSERT_TRUE(host);
625   chromeos::OobeUI* oobe_ui = host->GetOobeUI();
626   ASSERT_TRUE(oobe_ui);
627   base::RunLoop run_loop;
628   const bool oobe_ui_ready = oobe_ui->IsJSReady(run_loop.QuitClosure());
629   if (!oobe_ui_ready)
630     run_loop.Run();
631
632   // Ensure that the browser stays alive, even though no windows are opened
633   // during session start.
634   chrome::StartKeepAlive();
635
636   // Start listening for app/extension installation results.
637   content::WindowedNotificationObserver hosted_app_observer(
638       chrome::NOTIFICATION_EXTENSION_INSTALLED,
639       base::Bind(DoesInstallSuccessReferToId, kHostedAppID));
640   content::WindowedNotificationObserver extension_observer(
641       chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR,
642       base::Bind(DoesInstallFailureReferToId, kGoodExtensionID));
643
644   // Start login into the device-local account.
645   host->StartSignInScreen();
646   chromeos::ExistingUserController* controller =
647       chromeos::ExistingUserController::current_controller();
648   ASSERT_TRUE(controller);
649   controller->LoginAsPublicAccount(user_id_1_);
650
651   // Wait for the hosted app installation to succeed and the extension
652   // installation to fail (because hosted apps are whitelisted for use in
653   // device-local accounts and extensions are not).
654   hosted_app_observer.Wait();
655   extension_observer.Wait();
656
657   // Verify that the hosted app was installed.
658   Profile* profile = ProfileManager::GetDefaultProfile();
659   ASSERT_TRUE(profile);
660   ExtensionService* extension_service =
661       extensions::ExtensionSystem::Get(profile)->extension_service();
662   EXPECT_TRUE(extension_service->GetExtensionById(kHostedAppID, true));
663
664   // Verify that the extension was not installed.
665   EXPECT_FALSE(extension_service->GetExtensionById(kGoodExtensionID, true));
666
667   // Verify that the app was copied to the account's extension cache.
668   base::FilePath test_dir;
669   ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir));
670   EXPECT_TRUE(ContentsEqual(
671           GetCacheCRXFile(kAccountId1, kHostedAppID, kHostedAppVersion),
672           test_dir.Append(kHostedAppCRXPath)));
673
674   // Verify that the extension was not copied to the account's extension cache.
675   EXPECT_FALSE(PathExists(GetCacheCRXFile(
676       kAccountId1, kGoodExtensionID, kGoodExtensionVersion)));
677 }
678
679 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, ExtensionsCached) {
680   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
681
682   // Pre-populate the device local account's extension cache with a hosted app
683   // and an extension.
684   EXPECT_TRUE(file_util::CreateDirectory(
685       GetCacheDirectoryForAccountID(kAccountId1)));
686   base::FilePath test_dir;
687   ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir));
688   const base::FilePath cached_hosted_app =
689       GetCacheCRXFile(kAccountId1, kHostedAppID, kHostedAppVersion);
690   EXPECT_TRUE(CopyFile(test_dir.Append(kHostedAppCRXPath),
691                        cached_hosted_app));
692   const base::FilePath cached_extension =
693       GetCacheCRXFile(kAccountId1, kGoodExtensionID, kGoodExtensionVersion);
694   EXPECT_TRUE(CopyFile(test_dir.Append(kGoodExtensionCRXPath),
695                        cached_extension));
696
697   // Specify policy to force-install the hosted app.
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   // Ensure that the browser stays alive, even though no windows are opened
732   // during session start.
733   chrome::StartKeepAlive();
734
735   // Start listening for app/extension installation results.
736   content::WindowedNotificationObserver hosted_app_observer(
737       chrome::NOTIFICATION_EXTENSION_INSTALLED,
738       base::Bind(DoesInstallSuccessReferToId, kHostedAppID));
739   content::WindowedNotificationObserver extension_observer(
740       chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR,
741       base::Bind(DoesInstallFailureReferToId, kGoodExtensionID));
742
743   // Start login into the device-local account.
744   host->StartSignInScreen();
745   chromeos::ExistingUserController* controller =
746       chromeos::ExistingUserController::current_controller();
747   ASSERT_TRUE(controller);
748   controller->LoginAsPublicAccount(user_id_1_);
749
750   // Wait for the hosted app installation to succeed and the extension
751   // installation to fail.
752   hosted_app_observer.Wait();
753   extension_observer.Wait();
754
755   // Verify that the hosted app was installed.
756   Profile* profile = ProfileManager::GetDefaultProfile();
757   ASSERT_TRUE(profile);
758   ExtensionService* extension_service =
759       extensions::ExtensionSystem::Get(profile)->extension_service();
760   EXPECT_TRUE(extension_service->GetExtensionById(kHostedAppID, true));
761
762   // Verify that the extension was not installed.
763   EXPECT_FALSE(extension_service->GetExtensionById(kGoodExtensionID, true));
764
765   // Verify that the app is still in the account's extension cache.
766   EXPECT_TRUE(PathExists(cached_hosted_app));
767
768   // Verify that the extension was removed from the account's extension cache.
769   EXPECT_FALSE(PathExists(cached_extension));
770 }
771
772 class TermsOfServiceTest : public DeviceLocalAccountTest,
773                            public testing::WithParamInterface<bool> {
774 };
775
776 IN_PROC_BROWSER_TEST_P(TermsOfServiceTest, TermsOfServiceScreen) {
777   // Specify Terms of Service URL.
778   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
779   device_local_account_policy_.payload().mutable_termsofserviceurl()->set_value(
780       embedded_test_server()->GetURL(
781             std::string("/") +
782                 (GetParam() ? kExistentTermsOfServicePath
783                             : kNonexistentTermsOfServicePath)).spec());
784   UploadAndInstallDeviceLocalAccountPolicy();
785   AddPublicSessionToDevicePolicy(kAccountId1);
786
787   // Wait for the device-local account policy to be fully loaded.
788   content::WindowedNotificationObserver(
789       chrome::NOTIFICATION_USER_LIST_CHANGED,
790       base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait();
791
792   // Wait for the login UI to be ready.
793   chromeos::LoginDisplayHostImpl* host =
794       reinterpret_cast<chromeos::LoginDisplayHostImpl*>(
795           chromeos::LoginDisplayHostImpl::default_host());
796   ASSERT_TRUE(host);
797   chromeos::OobeUI* oobe_ui = host->GetOobeUI();
798   ASSERT_TRUE(oobe_ui);
799   base::RunLoop oobe_ui_wait_run_loop;
800   const bool oobe_ui_ready =
801       oobe_ui->IsJSReady(oobe_ui_wait_run_loop.QuitClosure());
802   if (!oobe_ui_ready)
803     oobe_ui_wait_run_loop.Run();
804
805   // Start login into the device-local account.
806   host->StartSignInScreen();
807   chromeos::ExistingUserController* controller =
808       chromeos::ExistingUserController::current_controller();
809   ASSERT_TRUE(controller);
810   controller->LoginAsPublicAccount(user_id_1_);
811
812   // Set up an observer that will quit the message loop when login has succeeded
813   // and the first wizard screen, if any, is being shown.
814   base::RunLoop login_wait_run_loop;
815   chromeos::MockConsumer login_status_consumer;
816   EXPECT_CALL(login_status_consumer, OnLoginSuccess(_))
817       .Times(1)
818       .WillOnce(InvokeWithoutArgs(&login_wait_run_loop, &base::RunLoop::Quit));
819
820   // Spin the loop until the observer fires. Then, unregister the observer.
821   controller->set_login_status_consumer(&login_status_consumer);
822   login_wait_run_loop.Run();
823   controller->set_login_status_consumer(NULL);
824
825   // Verify that the Terms of Service screen is being shown.
826   chromeos::WizardController* wizard_controller =
827         chromeos::WizardController::default_controller();
828   ASSERT_TRUE(wizard_controller);
829   ASSERT_TRUE(wizard_controller->current_screen());
830   EXPECT_EQ(chromeos::WizardController::kTermsOfServiceScreenName,
831             wizard_controller->current_screen()->GetName());
832
833   // Wait for the Terms of Service to finish downloading, then get the status of
834   // the screen's UI elements.
835   chromeos::WebUILoginView* web_ui_login_view = host->GetWebUILoginView();
836   ASSERT_TRUE(web_ui_login_view);
837   content::WebUI* web_ui = web_ui_login_view->GetWebUI();
838   ASSERT_TRUE(web_ui);
839   content::WebContents* contents = web_ui->GetWebContents();
840   ASSERT_TRUE(contents);
841   std::string json;
842   ASSERT_TRUE(content::ExecuteScriptAndExtractString(contents,
843       "var screen = document.getElementById('terms-of-service');"
844       "function SendReplyIfDownloadDone() {"
845       "  if (screen.classList.contains('tos-loading'))"
846       "    return false;"
847       "  var status = {};"
848       "  status.heading = document.getElementById('tos-heading').textContent;"
849       "  status.subheading ="
850       "      document.getElementById('tos-subheading').textContent;"
851       "  status.contentHeading ="
852       "      document.getElementById('tos-content-heading').textContent;"
853       "  status.content ="
854       "      document.getElementById('tos-content-main').textContent;"
855       "  status.error = screen.classList.contains('error');"
856       "  status.acceptEnabled ="
857       "      !document.getElementById('tos-accept-button').disabled;"
858       "  domAutomationController.send(JSON.stringify(status));"
859       "  observer.disconnect();"
860       "  return true;"
861       "}"
862       "var observer = new MutationObserver(SendReplyIfDownloadDone);"
863       "if (!SendReplyIfDownloadDone()) {"
864       "  var options = { attributes: true, attributeFilter: [ 'class' ] };"
865       "  observer.observe(screen, options);"
866       "}",
867       &json));
868   scoped_ptr<base::Value> value_ptr(base::JSONReader::Read(json));
869   const base::DictionaryValue* status = NULL;
870   ASSERT_TRUE(value_ptr.get());
871   ASSERT_TRUE(value_ptr->GetAsDictionary(&status));
872   std::string heading;
873   EXPECT_TRUE(status->GetString("heading", &heading));
874   std::string subheading;
875   EXPECT_TRUE(status->GetString("subheading", &subheading));
876   std::string content_heading;
877   EXPECT_TRUE(status->GetString("contentHeading", &content_heading));
878   std::string content;
879   EXPECT_TRUE(status->GetString("content", &content));
880   bool error;
881   EXPECT_TRUE(status->GetBoolean("error", &error));
882   bool accept_enabled;
883   EXPECT_TRUE(status->GetBoolean("acceptEnabled", &accept_enabled));
884
885   // Verify that the screen's headings have been set correctly.
886   EXPECT_EQ(
887       l10n_util::GetStringFUTF8(IDS_TERMS_OF_SERVICE_SCREEN_HEADING,
888                                 UTF8ToUTF16(kDomain)),
889       heading);
890   EXPECT_EQ(
891       l10n_util::GetStringFUTF8(IDS_TERMS_OF_SERVICE_SCREEN_SUBHEADING,
892                                 UTF8ToUTF16(kDomain)),
893       subheading);
894   EXPECT_EQ(
895       l10n_util::GetStringFUTF8(IDS_TERMS_OF_SERVICE_SCREEN_CONTENT_HEADING,
896                                 UTF8ToUTF16(kDomain)),
897       content_heading);
898
899   if (!GetParam()) {
900     // The Terms of Service URL was invalid. Verify that the screen is showing
901     // an error and the accept button is disabled.
902     EXPECT_TRUE(error);
903     EXPECT_FALSE(accept_enabled);
904     return;
905   }
906
907   // The Terms of Service URL was valid. Verify that the screen is showing the
908   // downloaded Terms of Service and the accept button is enabled.
909   base::FilePath test_dir;
910   ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir));
911   std::string terms_of_service;
912   ASSERT_TRUE(base::ReadFileToString(
913       test_dir.Append(kExistentTermsOfServicePath), &terms_of_service));
914   EXPECT_EQ(terms_of_service, content);
915   EXPECT_FALSE(error);
916   EXPECT_TRUE(accept_enabled);
917
918   // Click the accept button.
919   ASSERT_TRUE(content::ExecuteScript(contents,
920                                      "$('tos-accept-button').click();"));
921
922   // Wait for the session to start.
923   if (!IsSessionStarted()) {
924     content::WindowedNotificationObserver(chrome::NOTIFICATION_SESSION_STARTED,
925                                           base::Bind(IsSessionStarted)).Wait();
926   }
927 }
928
929 INSTANTIATE_TEST_CASE_P(TermsOfServiceTestInstance,
930                         TermsOfServiceTest, testing::Bool());
931
932 }  // namespace policy