1 // Copyright 2014 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 "chrome/browser/chromeos/login/lock/screen_locker_tester.h" 6 7 #include <string> 8 9 #include "base/strings/string_util.h" 10 #include "base/strings/stringprintf.h" 11 #include "base/strings/utf_string_conversions.h" 12 #include "base/values.h" 13 #include "chrome/browser/chromeos/login/lock/screen_locker.h" 14 #include "chrome/browser/chromeos/login/lock/webui_screen_locker.h" 15 #include "chrome/test/base/ui_test_utils.h" 16 #include "chromeos/login/auth/auth_status_consumer.h" 17 #include "chromeos/login/auth/fake_extended_authenticator.h" 18 #include "chromeos/login/auth/mock_authenticator.h" 19 #include "content/public/browser/render_frame_host.h" 20 #include "content/public/browser/render_view_host.h" 21 #include "content/public/browser/web_contents.h" 22 #include "content/public/browser/web_ui.h" 23 #include "content/public/test/test_utils.h" 24 #include "ui/views/controls/button/button.h" 25 #include "ui/views/controls/label.h" 26 #include "ui/views/controls/textfield/textfield.h" 27 #include "ui/views/widget/root_view.h" 28 29 using content::WebContents; 30 31 namespace { 32 33 // This class is used to observe state of the global ScreenLocker instance, 34 // which can go away as a result of a successful authentication. As such, 35 // it needs to directly reference the global ScreenLocker. 36 class LoginAttemptObserver : public chromeos::AuthStatusConsumer { 37 public: 38 LoginAttemptObserver(); 39 virtual ~LoginAttemptObserver(); 40 41 void WaitForAttempt(); 42 43 // Overridden from AuthStatusConsumer: 44 virtual void OnAuthFailure(const chromeos::AuthFailure& error) OVERRIDE { 45 LoginAttempted(); 46 } 47 48 virtual void OnAuthSuccess( 49 const chromeos::UserContext& credentials) OVERRIDE { 50 LoginAttempted(); 51 } 52 53 private: 54 void LoginAttempted(); 55 56 bool login_attempted_; 57 bool waiting_; 58 59 DISALLOW_COPY_AND_ASSIGN(LoginAttemptObserver); 60 }; 61 62 LoginAttemptObserver::LoginAttemptObserver() 63 : chromeos::AuthStatusConsumer(), login_attempted_(false), waiting_(false) { 64 chromeos::ScreenLocker::default_screen_locker()->SetLoginStatusConsumer(this); 65 } 66 67 LoginAttemptObserver::~LoginAttemptObserver() { 68 chromeos::ScreenLocker* global_locker = 69 chromeos::ScreenLocker::default_screen_locker(); 70 if (global_locker) 71 global_locker->SetLoginStatusConsumer(NULL); 72 } 73 74 void LoginAttemptObserver::WaitForAttempt() { 75 if (!login_attempted_) { 76 waiting_ = true; 77 content::RunMessageLoop(); 78 waiting_ = false; 79 } 80 ASSERT_TRUE(login_attempted_); 81 } 82 83 void LoginAttemptObserver::LoginAttempted() { 84 login_attempted_ = true; 85 if (waiting_) 86 base::MessageLoopForUI::current()->Quit(); 87 } 88 89 } // anyonymous namespace 90 91 namespace chromeos { 92 93 namespace test { 94 95 class WebUIScreenLockerTester : public ScreenLockerTester { 96 public: 97 // ScreenLockerTester overrides: 98 virtual void SetPassword(const std::string& password) OVERRIDE; 99 virtual std::string GetPassword() OVERRIDE; 100 virtual void EnterPassword(const std::string& password) OVERRIDE; 101 virtual void EmulateWindowManagerReady() OVERRIDE; 102 virtual views::Widget* GetWidget() const OVERRIDE; 103 virtual views::Widget* GetChildWidget() const OVERRIDE; 104 105 private: 106 friend class chromeos::ScreenLocker; 107 108 WebUIScreenLockerTester() {} 109 110 content::RenderViewHost* RenderViewHost() const; 111 112 // Returns the ScreenLockerWebUI object. 113 WebUIScreenLocker* webui_screen_locker() const; 114 115 // Returns the WebUI object from the screen locker. 116 content::WebUI* webui() const; 117 118 DISALLOW_COPY_AND_ASSIGN(WebUIScreenLockerTester); 119 }; 120 121 void WebUIScreenLockerTester::SetPassword(const std::string& password) { 122 webui()->GetWebContents()->GetMainFrame()->ExecuteJavaScript( 123 base::ASCIIToUTF16(base::StringPrintf( 124 "$('pod-row').pods[0].passwordElement.value = '%s';", 125 password.c_str()))); 126 } 127 128 std::string WebUIScreenLockerTester::GetPassword() { 129 std::string result; 130 scoped_ptr<base::Value> v = content::ExecuteScriptAndGetValue( 131 RenderViewHost()->GetMainFrame(), 132 "$('pod-row').pods[0].passwordElement.value;"); 133 CHECK(v->GetAsString(&result)); 134 return result; 135 } 136 137 void WebUIScreenLockerTester::EnterPassword(const std::string& password) { 138 bool result; 139 SetPassword(password); 140 141 // Verify password is set. 142 ASSERT_EQ(password, GetPassword()); 143 144 // Verify that "signin" button is hidden. 145 scoped_ptr<base::Value> v = content::ExecuteScriptAndGetValue( 146 RenderViewHost()->GetMainFrame(), 147 "window.getComputedStyle(" 148 " $('pod-row').pods[0].querySelector('.signin-button-container'))" 149 " .display == 'none'"); 150 ASSERT_TRUE(v->GetAsBoolean(&result)); 151 ASSERT_TRUE(result); 152 153 // Attempt to sign in. 154 LoginAttemptObserver login; 155 v = content::ExecuteScriptAndGetValue( 156 RenderViewHost()->GetMainFrame(), 157 "$('pod-row').pods[0].activate();"); 158 ASSERT_TRUE(v->GetAsBoolean(&result)); 159 ASSERT_TRUE(result); 160 161 // Wait for login attempt. 162 login.WaitForAttempt(); 163 } 164 165 void WebUIScreenLockerTester::EmulateWindowManagerReady() { 166 } 167 168 views::Widget* WebUIScreenLockerTester::GetWidget() const { 169 return webui_screen_locker()->lock_window_; 170 } 171 172 views::Widget* WebUIScreenLockerTester::GetChildWidget() const { 173 return webui_screen_locker()->lock_window_; 174 } 175 176 content::RenderViewHost* WebUIScreenLockerTester::RenderViewHost() const { 177 return webui()->GetWebContents()->GetRenderViewHost(); 178 } 179 180 WebUIScreenLocker* WebUIScreenLockerTester::webui_screen_locker() const { 181 DCHECK(ScreenLocker::screen_locker_); 182 return static_cast<WebUIScreenLocker*>( 183 ScreenLocker::screen_locker_->delegate_.get()); 184 } 185 186 content::WebUI* WebUIScreenLockerTester::webui() const { 187 DCHECK(webui_screen_locker()->webui_ready_); 188 content::WebUI* webui = webui_screen_locker()->GetWebUI(); 189 DCHECK(webui); 190 return webui; 191 } 192 193 ScreenLockerTester::ScreenLockerTester() { 194 } 195 196 ScreenLockerTester::~ScreenLockerTester() { 197 } 198 199 bool ScreenLockerTester::IsLocked() { 200 return ScreenLocker::screen_locker_ && 201 ScreenLocker::screen_locker_->locked_; 202 } 203 204 void ScreenLockerTester::InjectMockAuthenticator( 205 const UserContext& user_context) { 206 DCHECK(ScreenLocker::screen_locker_); 207 ScreenLocker::screen_locker_->SetAuthenticator( 208 new MockAuthenticator(ScreenLocker::screen_locker_, user_context)); 209 ScreenLocker::screen_locker_->extended_authenticator_ = 210 new FakeExtendedAuthenticator(ScreenLocker::screen_locker_, user_context); 211 } 212 213 } // namespace test 214 215 test::ScreenLockerTester* ScreenLocker::GetTester() { 216 return new test::WebUIScreenLockerTester(); 217 } 218 219 } // namespace chromeos 220