Home | History | Annotate | Download | only in lock
      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