diff options
14 files changed, 155 insertions, 45 deletions
diff --git a/chrome/browser/automation/automation_provider.cc b/chrome/browser/automation/automation_provider.cc index 33b7733..b2c838c 100644 --- a/chrome/browser/automation/automation_provider.cc +++ b/chrome/browser/automation/automation_provider.cc @@ -111,7 +111,8 @@ AutomationProvider::AutomationProvider(Profile* profile) switches::kAutomationReinitializeOnChannelError)), is_connected_(false), initial_tab_loads_complete_(false), - network_library_initialized_(true) { + network_library_initialized_(true), + login_webui_ready_(true) { TRACE_EVENT_BEGIN_ETW("AutomationProvider::AutomationProvider", 0, ""); DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); @@ -167,6 +168,12 @@ bool AutomationProvider::InitializeChannel(const std::string& channel_id) { channel_->AddFilter(automation_resource_message_filter_); #if defined(OS_CHROMEOS) + // Wait for webui login to be ready. + // Observer will delete itself. + if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kWebUILogin)) { + login_webui_ready_ = false; + new LoginWebuiReadyObserver(this); + } // Wait for the network manager to initialize. // The observer will delete itself when done. network_library_initialized_ = false; @@ -202,13 +209,20 @@ void AutomationProvider::SetExpectedTabCount(size_t expected_tabs) { void AutomationProvider::OnInitialTabLoadsComplete() { initial_tab_loads_complete_ = true; - if (is_connected_ && network_library_initialized_) + if (is_connected_ && network_library_initialized_ && login_webui_ready_) Send(new AutomationMsg_InitialLoadsComplete()); } void AutomationProvider::OnNetworkLibraryInit() { network_library_initialized_ = true; - if (is_connected_ && initial_tab_loads_complete_) + if (is_connected_ && initial_tab_loads_complete_ && login_webui_ready_) + Send(new AutomationMsg_InitialLoadsComplete()); +} + +void AutomationProvider::OnLoginWebuiReady() { + login_webui_ready_ = true; + if (is_connected_ && initial_tab_loads_complete_ && + network_library_initialized_) Send(new AutomationMsg_InitialLoadsComplete()); } @@ -302,7 +316,8 @@ void AutomationProvider::OnChannelConnected(int pid) { // Send a hello message with our current automation protocol version. channel_->Send(new AutomationMsg_Hello(GetProtocolVersion())); - if (initial_tab_loads_complete_ && network_library_initialized_) + if (initial_tab_loads_complete_ && network_library_initialized_ && + login_webui_ready_) Send(new AutomationMsg_InitialLoadsComplete()); } diff --git a/chrome/browser/automation/automation_provider.h b/chrome/browser/automation/automation_provider.h index 6efe17d..af3f830 100644 --- a/chrome/browser/automation/automation_provider.h +++ b/chrome/browser/automation/automation_provider.h @@ -112,6 +112,9 @@ class AutomationProvider // Called when the ChromeOS network library has finished its first update. void OnNetworkLibraryInit(); + // Called when the chromeos WebUI login is ready. + void OnLoginWebuiReady(); + // Get the index of a particular NavigationController object // in the given parent window. This method uses // TabStrip::GetIndexForNavigationController to get the index. @@ -386,6 +389,9 @@ class AutomationProvider // True iff the Chrome OS network library finished initialization. bool network_library_initialized_; + // True iff ChromeOS webui login ui is ready. + bool login_webui_ready_; + // ID of automation channel. std::string channel_id_; diff --git a/chrome/browser/automation/automation_provider_observers.h b/chrome/browser/automation/automation_provider_observers.h index 668dd0b..4aa04b0 100644 --- a/chrome/browser/automation/automation_provider_observers.h +++ b/chrome/browser/automation/automation_provider_observers.h @@ -133,6 +133,22 @@ class NetworkManagerInitObserver DISALLOW_COPY_AND_ASSIGN(NetworkManagerInitObserver); }; + +// Observes when webui login becomes ready on chromeos. +class LoginWebuiReadyObserver : public NotificationObserver { + public: + explicit LoginWebuiReadyObserver(AutomationProvider* automation); + virtual ~LoginWebuiReadyObserver(); + virtual void Observe(int type, + const NotificationSource& source, + const NotificationDetails& details); + + private: + NotificationRegistrar registrar_; + base::WeakPtr<AutomationProvider> automation_; + + DISALLOW_COPY_AND_ASSIGN(LoginWebuiReadyObserver); +}; #endif // defined(OS_CHROMEOS) // Watches for NewTabUI page loads for performance timing purposes. @@ -715,8 +731,7 @@ class InfoBarCountObserver : public NotificationObserver { }; #if defined(OS_CHROMEOS) -class LoginObserver : public chromeos::LoginStatusConsumer, - public NotificationObserver { +class LoginObserver : public chromeos::LoginStatusConsumer { public: LoginObserver(chromeos::ExistingUserController* controller, AutomationProvider* automation, @@ -733,13 +748,8 @@ class LoginObserver : public chromeos::LoginStatusConsumer, bool pending_requests, bool using_oauth); - virtual void Observe(int type, - const NotificationSource& source, - const NotificationDetails& details); - private: chromeos::ExistingUserController* controller_; - NotificationRegistrar registrar_; base::WeakPtr<AutomationProvider> automation_; scoped_ptr<IPC::Message> reply_message_; diff --git a/chrome/browser/automation/automation_provider_observers_chromeos.cc b/chrome/browser/automation/automation_provider_observers_chromeos.cc index f6e1592..16dd144 100644 --- a/chrome/browser/automation/automation_provider_observers_chromeos.cc +++ b/chrome/browser/automation/automation_provider_observers_chromeos.cc @@ -46,6 +46,24 @@ void NetworkManagerInitObserver::OnNetworkManagerChanged(NetworkLibrary* obj) { } } +LoginWebuiReadyObserver::LoginWebuiReadyObserver( + AutomationProvider* automation) + : automation_(automation->AsWeakPtr()) { + registrar_.Add(this, chrome::NOTIFICATION_LOGIN_WEBUI_READY, + NotificationService::AllSources()); +} + +LoginWebuiReadyObserver::~LoginWebuiReadyObserver() { +} + +void LoginWebuiReadyObserver::Observe(int type, + const NotificationSource& source, + const NotificationDetails& details) { + DCHECK(type == chrome::NOTIFICATION_LOGIN_WEBUI_READY); + automation_->OnLoginWebuiReady(); + delete this; +} + LoginObserver::LoginObserver(chromeos::ExistingUserController* controller, AutomationProvider* automation, IPC::Message* reply_message) @@ -53,8 +71,6 @@ LoginObserver::LoginObserver(chromeos::ExistingUserController* controller, automation_(automation->AsWeakPtr()), reply_message_(reply_message) { controller_->set_login_status_consumer(this); - registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CREATED, - NotificationService::AllSources()); } LoginObserver::~LoginObserver() { @@ -76,11 +92,6 @@ void LoginObserver::OnLoginSuccess( bool pending_requests, bool using_oauth) { controller_->set_login_status_consumer(NULL); -} - -void LoginObserver::Observe(int type, - const NotificationSource& source, - const NotificationDetails& details) { AutomationJSONReply(automation_, reply_message_.release()).SendSuccess(NULL); delete this; } @@ -412,7 +423,7 @@ void PhotoCaptureObserver::OnCapturingStopped( take_photo_dialog->Accept(); const SkBitmap& photo = take_photo_view->GetImage(); chromeos::UserManager* user_manager = chromeos::UserManager::Get(); - if(!user_manager) { + if (!user_manager) { AutomationJSONReply(automation_, reply_message_.release()).SendError( "No user manager"); @@ -421,7 +432,7 @@ void PhotoCaptureObserver::OnCapturingStopped( } const chromeos::UserManager::User& user = user_manager->logged_in_user(); - if(user.email().empty()) { + if (user.email().empty()) { AutomationJSONReply(automation_, reply_message_.release()).SendError( "User email is not set"); diff --git a/chrome/browser/automation/testing_automation_provider_chromeos.cc b/chrome/browser/automation/testing_automation_provider_chromeos.cc index 47da2b5..d2dc2df 100644 --- a/chrome/browser/automation/testing_automation_provider_chromeos.cc +++ b/chrome/browser/automation/testing_automation_provider_chromeos.cc @@ -4,6 +4,7 @@ #include "chrome/browser/automation/testing_automation_provider.h" +#include "base/command_line.h" #include "base/i18n/time_formatting.h" #include "base/stringprintf.h" #include "base/time.h" @@ -22,6 +23,7 @@ #include "chrome/browser/chromeos/login/login_display.h" #include "chrome/browser/chromeos/login/login_display_host.h" #include "chrome/browser/chromeos/login/screen_locker.h" +#include "chrome/browser/chromeos/login/webui_login_display.h" #include "chrome/browser/chromeos/login/wizard_controller.h" #include "chrome/browser/chromeos/network_state_notifier.h" #include "chrome/browser/chromeos/options/take_photo_dialog.h" @@ -35,6 +37,7 @@ #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/views/window.h" +#include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" #include "policy/policy_constants.h" #include "views/widget/widget.h" @@ -218,6 +221,11 @@ void TestingAutomationProvider::GetLoginInfo(DictionaryValue* args, const chromeos::ScreenLocker* screen_locker = chromeos::ScreenLocker::default_screen_locker(); + return_value->SetString( + "login_ui_type", + CommandLine::ForCurrentProcess()->HasSwitch(switches::kWebUILogin)? + "webui": "nativeui"); + return_value->SetBoolean("is_owner", user_manager->current_user_is_owner()); return_value->SetBoolean("is_logged_in", user_manager->user_is_logged_in()); return_value->SetBoolean("is_screen_locked", screen_locker); @@ -262,10 +270,20 @@ void TestingAutomationProvider::Login(DictionaryValue* args, chromeos::ExistingUserController* controller = chromeos::ExistingUserController::current_controller(); - controller->login_display()->SelectPod(0); + // Set up an observer (it will delete itself). new LoginObserver(controller, this, reply_message); - controller->Login(username, password); + + if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kWebUILogin)) { + // WebUI login. + chromeos::WebUILoginDisplay* webui_login_display = + chromeos::WebUILoginDisplay::GetInstance(); + webui_login_display->ShowSigninScreenForCreds(username, password); + } else { + // Native UI login. + controller->login_display()->SelectPod(0); + controller->Login(username, password); + } } void TestingAutomationProvider::LockScreen(DictionaryValue* args, diff --git a/chrome/browser/chromeos/login/existing_user_controller.cc b/chrome/browser/chromeos/login/existing_user_controller.cc index c06b1a0..cfe8c01 100644 --- a/chrome/browser/chromeos/login/existing_user_controller.cc +++ b/chrome/browser/chromeos/login/existing_user_controller.cc @@ -366,11 +366,6 @@ void ExistingUserController::OnLoginSuccess( this); - if (login_status_consumer_) - login_status_consumer_->OnLoginSuccess(username, password, - credentials, pending_requests, - using_oauth); - // Notifiy LoginDisplay to allow it provide visual feedback to user. login_display_->OnLoginSuccess(username); } @@ -426,6 +421,11 @@ void ExistingUserController::OnProfilePrepared(Profile* profile) { #endif } else { LoginUtils::DoBrowserLaunch(profile, host_); + // Inform |login_status_consumer_| about successful login after + // browser launch. Set most params to empty since they're not needed. + if (login_status_consumer_) + login_status_consumer_->OnLoginSuccess( + "", "", GaiaAuthConsumer::ClientLoginResult(), false, false); host_ = NULL; } login_display_->OnFadeOut(); diff --git a/chrome/browser/chromeos/login/parallel_authenticator.cc b/chrome/browser/chromeos/login/parallel_authenticator.cc index e75be93..74975dd 100644 --- a/chrome/browser/chromeos/login/parallel_authenticator.cc +++ b/chrome/browser/chromeos/login/parallel_authenticator.cc @@ -135,13 +135,24 @@ bool ParallelAuthenticator::CompleteLogin(Profile* profile, BrowserThread::UI, FROM_HERE, NewRunnableMethod(mounter_.get(), &CryptohomeOp::Initiate)); - // For login completion from extension, we just need to resolve the current - // auth attempt state, the rest of OAuth related tasks will be done in - // parallel. - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - NewRunnableMethod(this, - &ParallelAuthenticator::ResolveLoginCompletionStatus)); + if (!using_oauth_) { + // Test automation needs to disable oauth, but that leads to other + // services not being able to fetch a token, leading to browser crashes. + // So initiate ClientLogin-based post authentication. + // TODO(xiyuan): This should not be required. + current_online_ = new OnlineAttempt(using_oauth_, + current_state_.get(), + this); + current_online_->Initiate(profile); + } else { + // For login completion from extension, we just need to resolve the current + // auth attempt state, the rest of OAuth related tasks will be done in + // parallel. + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + NewRunnableMethod(this, + &ParallelAuthenticator::ResolveLoginCompletionStatus)); + } BrowserThread::PostTask( BrowserThread::FILE, FROM_HERE, diff --git a/chrome/browser/chromeos/login/webui_login_display.cc b/chrome/browser/chromeos/login/webui_login_display.cc index 427a6df..ad3fe20 100644 --- a/chrome/browser/chromeos/login/webui_login_display.cc +++ b/chrome/browser/chromeos/login/webui_login_display.cc @@ -179,6 +179,13 @@ void WebUILoginDisplay::SetWebUIHandler( webui_handler_ = webui_handler; } +void WebUILoginDisplay::ShowSigninScreenForCreds( + const std::string& username, + const std::string& password) { + DCHECK(webui_handler_); + webui_handler_->ShowSigninScreenForCreds(username, password); +} + // WebUILoginDisplay, private: ------------------------------------------------- // Singleton implementation: --------------------------------------------------- diff --git a/chrome/browser/chromeos/login/webui_login_display.h b/chrome/browser/chromeos/login/webui_login_display.h index c5c84d1..ef969df 100644 --- a/chrome/browser/chromeos/login/webui_login_display.h +++ b/chrome/browser/chromeos/login/webui_login_display.h @@ -80,6 +80,8 @@ class WebUILoginDisplay : public LoginDisplay, virtual void ShowEnterpriseEnrollmentScreen() OVERRIDE; virtual void SetWebUIHandler( LoginDisplayWebUIHandler* webui_handler) OVERRIDE; + virtual void ShowSigninScreenForCreds(const std::string& username, + const std::string& password) OVERRIDE; void set_login_window(views::Widget* login_window) { login_window_ = login_window; diff --git a/chrome/browser/resources/chromeos/login/screen_gaia_signin.js b/chrome/browser/resources/chromeos/login/screen_gaia_signin.js index 4ee3d61..fda77b0 100644 --- a/chrome/browser/resources/chromeos/login/screen_gaia_signin.js +++ b/chrome/browser/resources/chromeos/login/screen_gaia_signin.js @@ -137,6 +137,7 @@ cr.define('login', function() { this.loading = true; } else if (msg.method == 'loginUILoaded' && this.isAuthExtMessage_(e)) { this.loading = false; + chrome.send('loginWebuiReady'); } }, diff --git a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc index eb8d9a4..3b68bb1 100644 --- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc @@ -16,9 +16,11 @@ #include "chrome/browser/chromeos/login/webui_login_display.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/chromeos/user_cros_settings_provider.h" +#include "chrome/common/chrome_notification_types.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/url_constants.h" #include "content/browser/tab_contents/tab_contents.h" +#include "content/common/notification_service.h" #include "grit/generated_resources.h" #include "net/base/dnsrr_resolver.h" #include "ui/base/l10n/l10n_util.h" @@ -220,6 +222,8 @@ void SigninScreenHandler::RegisterMessages() { NewCallback(this, &SigninScreenHandler::HandleLaunchHelpApp)); web_ui_->RegisterMessageCallback("createAccount", NewCallback(this, &SigninScreenHandler::HandleCreateAccount)); + web_ui_->RegisterMessageCallback("loginWebuiReady", + NewCallback(this, &SigninScreenHandler::HandleLoginWebuiReady)); } void SigninScreenHandler::HandleGetUsers(const base::ListValue* args) { @@ -271,6 +275,13 @@ void SigninScreenHandler::OnDnsCleared() { void SigninScreenHandler::ShowSigninScreenIfReady() { if (!dns_cleared_ || !cookies_cleared_) return; + ShowSigninScreenForCreds("", ""); +} + +void SigninScreenHandler::ShowSigninScreenForCreds( + const std::string& username, + const std::string& password) { + VLOG(2) << "ShowSigninScreenForCreds " << username << " " << password; DictionaryValue params; params.SetString("startUrl", kGaiaExtStartPage); @@ -288,16 +299,10 @@ void SigninScreenHandler::ShowSigninScreenIfReady() { // Test automation data: const CommandLine* command_line = CommandLine::ForCurrentProcess(); if (command_line->HasSwitch(switches::kAuthExtensionPath)) { - if (command_line->HasSwitch(switches::kTestAuthEmail)) { - params.SetString("test_email", - command_line->GetSwitchValueASCII( - switches::kTestAuthEmail)); - } - if (command_line->HasSwitch(switches::kTestAuthPassword)) { - params.SetString("test_password", - command_line->GetSwitchValueASCII( - switches::kTestAuthPassword)); - } + if (!username.empty()) + params.SetString("test_email", username); + if (!password.empty()) + params.SetString("test_password", password); } ShowScreen(kGaiaSigninScreen, ¶ms); } @@ -449,6 +454,13 @@ void SigninScreenHandler::SendUserList(bool animated) { users_list, animated_value); } +void SigninScreenHandler::HandleLoginWebuiReady(const base::ListValue* args) { + NotificationService::current()->Notify( + chrome::NOTIFICATION_LOGIN_WEBUI_READY, + NotificationService::AllSources(), + NotificationService::NoDetails()); +} + void SigninScreenHandler::HandleCreateAccount(const base::ListValue* args) { delegate_->CreateAccount(); } diff --git a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h index 1dd4d94..af72d4cd 100644 --- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h +++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h @@ -33,6 +33,9 @@ class LoginDisplayWebUIHandler { const std::string& error_text, const std::string& help_link_text, HelpAppLauncher::HelpTopic help_topic_id) = 0; + // Show siginin screen for the given credentials. + virtual void ShowSigninScreenForCreds(const std::string& username, + const std::string& password) = 0; protected: virtual ~LoginDisplayWebUIHandler() {} }; @@ -101,6 +104,8 @@ class SigninScreenHandler : public BaseScreenHandler, const std::string& error_text, const std::string& help_link_text, HelpAppLauncher::HelpTopic help_topic_id) OVERRIDE; + virtual void ShowSigninScreenForCreds(const std::string& username, + const std::string& password) OVERRIDE; // BrowsingDataRemover::Observer overrides. virtual void OnBrowsingDataRemoverDone() OVERRIDE; @@ -139,6 +144,9 @@ class SigninScreenHandler : public BaseScreenHandler, // Handle 'createAccount' request. void HandleCreateAccount(const base::ListValue* args); + // Handle 'loginWebuiReady' request. + void HandleLoginWebuiReady(const base::ListValue* args); + // Sends user list to account picker. void SendUserList(bool animated); diff --git a/chrome/common/chrome_notification_types.h b/chrome/common/chrome_notification_types.h index f1101cc..60f62ea 100644 --- a/chrome/common/chrome_notification_types.h +++ b/chrome/common/chrome_notification_types.h @@ -756,6 +756,9 @@ enum NotificationType { // all and the details are AuthenticationNotificationDetails. NOTIFICATION_LOGIN_AUTHENTICATION, + // Sent when webui login screen is ready and gaia iframe has loaded. + NOTIFICATION_LOGIN_WEBUI_READY, + // Sent when a panel state changed. NOTIFICATION_PANEL_STATE_CHANGED, diff --git a/chrome/test/pyautolib/pyauto.py b/chrome/test/pyautolib/pyauto.py index 16749d3..4113b3a 100644 --- a/chrome/test/pyautolib/pyauto.py +++ b/chrome/test/pyautolib/pyauto.py @@ -233,6 +233,8 @@ class PyUITest(pyautolib.PyUITestBase, unittest.TestCase): '--enable-file-cookies', '--dom-automation', '--skip-oauth-login', + # Enables injection of test content script for webui login automation + '--auth-ext-path=/usr/share/chromeos-assets/gaia_auth', ] else: return [] @@ -2947,6 +2949,7 @@ class PyUITest(pyautolib.PyUITestBase, unittest.TestCase): u'is_owner': True, u'email': u'example@gmail.com', u'is_screen_locked': False, + u'login_ui_type': 'nativeui', # or 'webui' u'is_logged_in': True} Raises: @@ -3021,9 +3024,12 @@ class PyUITest(pyautolib.PyUITestBase, unittest.TestCase): def Login(self, username, password): """Login to chromeos. - Waits until logged in. + Waits until logged in and browser is ready. Should be displaying the login screen to work. + Note that in case of webui auth-extension-based login, gaia auth errors + will not be noticed here, because the browser has no knowledge of it. + Returns: An error string if an error occured. None otherwise. |