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