| OLD | NEW |
| 1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 // | 4 // |
| 5 // AuthWatcher watches authentication events and user open and close | 5 // AuthWatcher watches authentication events and user open and close |
| 6 // events and accordingly opens and closes shares. | 6 // events and accordingly opens and closes shares. |
| 7 | 7 |
| 8 #ifndef CHROME_BROWSER_SYNC_ENGINE_AUTH_WATCHER_H_ | 8 #ifndef CHROME_BROWSER_SYNC_ENGINE_AUTH_WATCHER_H_ |
| 9 #define CHROME_BROWSER_SYNC_ENGINE_AUTH_WATCHER_H_ | 9 #define CHROME_BROWSER_SYNC_ENGINE_AUTH_WATCHER_H_ |
| 10 | 10 |
| 11 #include <map> | 11 #include <map> |
| 12 #include <string> | 12 #include <string> |
| 13 | 13 |
| 14 #include "base/atomicops.h" | 14 #include "base/atomicops.h" |
| 15 #include "base/ref_counted.h" |
| 15 #include "base/scoped_ptr.h" | 16 #include "base/scoped_ptr.h" |
| 17 #include "base/thread.h" |
| 16 #include "chrome/browser/sync/engine/net/gaia_authenticator.h" | 18 #include "chrome/browser/sync/engine/net/gaia_authenticator.h" |
| 19 #include "chrome/browser/sync/protocol/service_constants.h" |
| 17 #include "chrome/browser/sync/util/event_sys.h" | 20 #include "chrome/browser/sync/util/event_sys.h" |
| 18 #include "chrome/browser/sync/util/pthread_helpers.h" | |
| 19 #include "chrome/browser/sync/util/sync_types.h" | 21 #include "chrome/browser/sync/util/sync_types.h" |
| 22 #include "testing/gtest/include/gtest/gtest_prod.h" // For FRIEND_TEST |
| 20 | 23 |
| 21 namespace syncable { | 24 namespace syncable { |
| 22 struct DirectoryManagerEvent; | 25 struct DirectoryManagerEvent; |
| 23 class DirectoryManager; | 26 class DirectoryManager; |
| 24 } | 27 } |
| 25 | 28 |
| 26 namespace browser_sync { | 29 namespace browser_sync { |
| 27 | 30 |
| 28 class AllStatus; | 31 class AllStatus; |
| 29 class AuthWatcher; | 32 class AuthWatcher; |
| (...skipping 28 matching lines...) Expand all Loading... |
| 58 | 61 |
| 59 // How was this auth attempt initiated? | 62 // How was this auth attempt initiated? |
| 60 enum AuthenticationTrigger { | 63 enum AuthenticationTrigger { |
| 61 USER_INITIATED = 0, // default value. | 64 USER_INITIATED = 0, // default value. |
| 62 EXPIRED_CREDENTIALS, | 65 EXPIRED_CREDENTIALS, |
| 63 }; | 66 }; |
| 64 | 67 |
| 65 AuthenticationTrigger trigger; | 68 AuthenticationTrigger trigger; |
| 66 }; | 69 }; |
| 67 | 70 |
| 68 class AuthWatcher { | 71 // The mother-class of Authentication for the sync backend. Handles both gaia |
| 72 // and sync service authentication via asynchronous Authenticate* methods, |
| 73 // raising AuthWatcherEvents on success/failure. The implementation currently |
| 74 // runs its own backend thread for the actual auth processing, which means |
| 75 // the AuthWatcherEvents can be raised on a different thread than the one that |
| 76 // invoked authentication. |
| 77 class AuthWatcher : public base::RefCountedThreadSafe<AuthWatcher> { |
| 78 friend class AuthWatcherTest; |
| 79 FRIEND_TEST(AuthWatcherTest, Construction); |
| 69 public: | 80 public: |
| 70 // Normal progression is local -> gaia -> token. | 81 // Normal progression is local -> gaia -> token. |
| 71 enum Status { LOCALLY_AUTHENTICATED, GAIA_AUTHENTICATED, NOT_AUTHENTICATED }; | 82 enum Status { LOCALLY_AUTHENTICATED, GAIA_AUTHENTICATED, NOT_AUTHENTICATED }; |
| 72 typedef syncable::DirectoryManagerEvent DirectoryManagerEvent; | 83 typedef syncable::DirectoryManagerEvent DirectoryManagerEvent; |
| 73 typedef syncable::DirectoryManager DirectoryManager; | 84 typedef syncable::DirectoryManager DirectoryManager; |
| 74 | 85 |
| 75 AuthWatcher(DirectoryManager* dirman, | 86 AuthWatcher(DirectoryManager* dirman, |
| 76 ServerConnectionManager* scm, | 87 ServerConnectionManager* scm, |
| 77 AllStatus* allstatus, | 88 AllStatus* allstatus, |
| 78 const std::string& user_agent, | 89 const std::string& user_agent, |
| 79 const std::string& service_id, | 90 const std::string& service_id, |
| 80 const std::string& gaia_url, | 91 const std::string& gaia_url, |
| 81 UserSettings* user_settings, | 92 UserSettings* user_settings, |
| 82 GaiaAuthenticator* gaia_auth, | 93 GaiaAuthenticator* gaia_auth, |
| 83 TalkMediator* talk_mediator); | 94 TalkMediator* talk_mediator); |
| 84 ~AuthWatcher(); | 95 ~AuthWatcher(); |
| 85 | 96 |
| 86 // Returns true if the open share has gotten zero updates from the sync | 97 // Returns true if the open share has gotten zero updates from the sync |
| 87 // server (initial sync complete). | 98 // server (initial sync complete). |
| 88 bool LoadDirectoryListAndOpen(const PathString& login); | 99 bool LoadDirectoryListAndOpen(const PathString& login); |
| 89 | 100 |
| 90 typedef EventChannel<AuthWatcherEvent, Lock> Channel; | 101 typedef EventChannel<AuthWatcherEvent, Lock> Channel; |
| 91 | 102 |
| 92 inline Channel* channel() const { | 103 inline Channel* channel() const { |
| 93 return channel_.get(); | 104 return channel_.get(); |
| 94 } | 105 } |
| 95 | 106 |
| 107 // The following 3 flavors of authentication routines are asynchronous and can |
| 108 // be called from any thread. |
| 96 void Authenticate(const std::string& email, const std::string& password, | 109 void Authenticate(const std::string& email, const std::string& password, |
| 97 const std::string& captcha_token, const std::string& captcha_value, | 110 const std::string& captcha_token, const std::string& captcha_value, |
| 98 bool persist_creds_to_disk); | 111 bool persist_creds_to_disk); |
| 99 | 112 |
| 100 void Authenticate(const std::string& email, const std::string& password, | 113 void Authenticate(const std::string& email, const std::string& password, |
| 101 bool persist_creds_to_disk) { | 114 bool persist_creds_to_disk) { |
| 102 Authenticate(email, password, "", "", persist_creds_to_disk); | 115 Authenticate(email, password, "", "", persist_creds_to_disk); |
| 103 } | 116 } |
| 104 | 117 |
| 105 // Retrieves an auth token for a named service for which a long-lived token | 118 // Use this version when you don't need the gaia authentication step because |
| 106 // was obtained at login time. Returns true if a long-lived token can be | 119 // you already have a valid token for |gaia_email|. |
| 107 // found, false otherwise. | 120 void AuthenticateWithToken(const std::string& gaia_email, |
| 108 bool GetAuthTokenForService(const std::string& service_name, | 121 const std::string& auth_token); |
| 109 std::string* service_token); | 122 |
| 123 // Joins on the backend thread. The AuthWatcher is useless after this and |
| 124 // should be destroyed. |
| 125 void Shutdown() { auth_backend_thread_.Stop(); } |
| 110 | 126 |
| 111 std::string email() const; | 127 std::string email() const; |
| 112 syncable::DirectoryManager* dirman() const { return dirman_; } | 128 syncable::DirectoryManager* dirman() const { return dirman_; } |
| 113 ServerConnectionManager* scm() const { return scm_; } | 129 ServerConnectionManager* scm() const { return scm_; } |
| 114 AllStatus* allstatus() const { return allstatus_; } | 130 AllStatus* allstatus() const { return allstatus_; } |
| 115 UserSettings* settings() const { return user_settings_; } | 131 UserSettings* settings() const { return user_settings_; } |
| 116 Status status() const { return (Status)status_; } | 132 Status status() const { return (Status)status_; } |
| 117 | 133 |
| 118 void Logout(); | |
| 119 | |
| 120 // For synchronizing other destructors. | |
| 121 void WaitForAuthThreadFinish(); | |
| 122 | |
| 123 bool AuthenticateWithToken(const std::string& email, | |
| 124 const std::string& auth_token); | |
| 125 | |
| 126 protected: | 134 protected: |
| 127 void Reset(); | |
| 128 void ClearAuthenticationData(); | 135 void ClearAuthenticationData(); |
| 129 | 136 |
| 130 void NotifyAuthSucceeded(const std::string& email); | 137 void NotifyAuthSucceeded(const std::string& email); |
| 131 bool StartNewAuthAttempt(const std::string& email, | |
| 132 const std::string& password, | |
| 133 const std::string& auth_token, const std::string& captcha_token, | |
| 134 const std::string& captcha_value, bool persist_creds_to_disk, | |
| 135 AuthWatcherEvent::AuthenticationTrigger trigger); | |
| 136 void HandleServerConnectionEvent(const ServerConnectionEvent& event); | 138 void HandleServerConnectionEvent(const ServerConnectionEvent& event); |
| 137 | 139 |
| 138 void SaveUserSettings(const std::string& username, | 140 void SaveUserSettings(const std::string& username, |
| 139 const std::string& auth_token, | 141 const std::string& auth_token, |
| 140 const bool save_credentials); | 142 const bool save_credentials); |
| 141 | 143 |
| 144 MessageLoop* message_loop() { return auth_backend_thread_.message_loop(); } |
| 145 |
| 146 private: |
| 142 // These two helpers should only be called from the auth function. | 147 // These two helpers should only be called from the auth function. |
| 143 // Returns false iff we had problems and should try GAIA_AUTH again. | 148 // Called when authentication with gaia succeeds, to save credential info. |
| 144 bool ProcessGaiaAuthSuccess(); | 149 void PersistCredentials(); |
| 150 // Called when authentication with gaia fails. |
| 145 void ProcessGaiaAuthFailure(); | 151 void ProcessGaiaAuthFailure(); |
| 146 | 152 |
| 147 // Just checks that the user has at least one local share cache. | 153 // Just checks that the user has at least one local share cache. |
| 148 bool AuthenticateLocally(std::string email); | 154 bool AuthenticateLocally(std::string email); |
| 149 // Also checks the user's password against stored password hash. | 155 // Also checks the user's password against stored password hash. |
| 150 bool AuthenticateLocally(std::string email, const std::string& password); | 156 bool AuthenticateLocally(std::string email, const std::string& password); |
| 151 | 157 |
| 152 // Sets the trigger member of the event and sends the event on channel_. | 158 // Sets the trigger member of the event and sends the event on channel_. |
| 153 void NotifyListeners(AuthWatcherEvent* event); | 159 void NotifyListeners(AuthWatcherEvent* event); |
| 154 | 160 |
| 155 const std::string& sync_service_token() const { return sync_service_token_; } | 161 inline std::string FormatAsEmailAddress(const std::string& email) const { |
| 162 std::string mail(email); |
| 163 if (email.find('@') == std::string::npos) { |
| 164 mail.push_back('@'); |
| 165 // TODO(chron): Should this be done only at the UI level? |
| 166 mail.append(DEFAULT_SIGNIN_DOMAIN); |
| 167 } |
| 168 return mail; |
| 169 } |
| 156 | 170 |
| 157 typedef PThreadScopedLock<PThreadMutex> MutexLock; | 171 // A struct to marshal various data across to the auth_backend_thread_ on |
| 158 | 172 // Authenticate() and AuthenticateWithToken calls. |
| 159 // Passed to newly created threads. | 173 struct AuthRequest { |
| 160 struct ThreadParams { | 174 std::string email; |
| 161 AuthWatcher* self; | 175 std::string password; |
| 162 std::string email; | 176 std::string auth_token; |
| 163 std::string password; | 177 std::string captcha_token; |
| 164 std::string auth_token; | 178 std::string captcha_value; |
| 165 std::string captcha_token; | 179 bool persist_creds_to_disk; |
| 166 std::string captcha_value; | 180 AuthWatcherEvent::AuthenticationTrigger trigger; |
| 167 bool persist_creds_to_disk; | |
| 168 AuthWatcherEvent::AuthenticationTrigger trigger; | |
| 169 }; | 181 }; |
| 170 | 182 |
| 171 // Initial function passed to pthread_create. | 183 // The public interface Authenticate methods are proxies to these, which |
| 172 static void* AuthenticationThreadStartRoutine(void* arg); | 184 // can only be called from |auth_backend_thread_|. |
| 173 // Member function called by AuthenticationThreadStartRoutine. | 185 void DoAuthenticate(const AuthRequest& request); |
| 174 void* AuthenticationThreadMain(struct ThreadParams* arg); | 186 void DoAuthenticateWithToken(const std::string& email, |
| 187 const std::string& auth_token); |
| 188 |
| 189 // The public HandleServerConnectionEvent method proxies to this method, which |
| 190 // can only be called on |auth_backend_thread_|. |
| 191 void DoHandleServerConnectionEvent( |
| 192 const ServerConnectionEvent& event, |
| 193 const std::string& auth_token_snapshot); |
| 175 | 194 |
| 176 scoped_ptr<GaiaAuthenticator> const gaia_; | 195 scoped_ptr<GaiaAuthenticator> const gaia_; |
| 177 syncable::DirectoryManager* const dirman_; | 196 syncable::DirectoryManager* const dirman_; |
| 178 ServerConnectionManager* const scm_; | 197 ServerConnectionManager* const scm_; |
| 179 scoped_ptr<EventListenerHookup> connmgr_hookup_; | 198 scoped_ptr<EventListenerHookup> connmgr_hookup_; |
| 180 AllStatus* const allstatus_; | 199 AllStatus* const allstatus_; |
| 181 // TODO(chron): It is incorrect to make assignments to AtomicWord. | 200 Status status_; |
| 182 volatile base::subtle::AtomicWord status_; | |
| 183 UserSettings* const user_settings_; | 201 UserSettings* const user_settings_; |
| 184 TalkMediator* talk_mediator_; // Interface to the notifications engine. | 202 TalkMediator* talk_mediator_; // Interface to the notifications engine. |
| 185 scoped_ptr<Channel> channel_; | 203 scoped_ptr<Channel> channel_; |
| 186 | 204 |
| 187 // We store our service token in memory as a workaround to the fact that we | 205 base::Thread auth_backend_thread_; |
| 188 // don't persist it when the user unchecks "remember me". | |
| 189 // We also include it on outgoing requests. | |
| 190 std::string sync_service_token_; | |
| 191 | 206 |
| 192 PThreadMutex mutex_; | |
| 193 // All members below are protected by the above mutex | |
| 194 pthread_t thread_; | |
| 195 bool thread_handle_valid_; | |
| 196 bool authenticating_now_; | |
| 197 AuthWatcherEvent::AuthenticationTrigger current_attempt_trigger_; | 207 AuthWatcherEvent::AuthenticationTrigger current_attempt_trigger_; |
| 198 DISALLOW_COPY_AND_ASSIGN(AuthWatcher); | 208 DISALLOW_COPY_AND_ASSIGN(AuthWatcher); |
| 199 }; | 209 }; |
| 200 | 210 |
| 201 } // namespace browser_sync | 211 } // namespace browser_sync |
| 202 | 212 |
| 203 #endif // CHROME_BROWSER_SYNC_ENGINE_AUTH_WATCHER_H_ | 213 #endif // CHROME_BROWSER_SYNC_ENGINE_AUTH_WATCHER_H_ |
| OLD | NEW |