summaryrefslogtreecommitdiffstats
path: root/chrome/browser/sync/engine/auth_watcher.h
blob: f1bd424d6d7f57117054ef86fcf35913561ff8b1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// AuthWatcher watches authentication events and user open and close
// events and accordingly opens and closes shares.

#ifndef CHROME_BROWSER_SYNC_ENGINE_AUTH_WATCHER_H_
#define CHROME_BROWSER_SYNC_ENGINE_AUTH_WATCHER_H_

#include <map>
#include <string>

#include "base/atomicops.h"
#include "base/scoped_ptr.h"
#include "chrome/browser/sync/engine/net/gaia_authenticator.h"
#include "chrome/browser/sync/util/event_sys.h"
#include "chrome/browser/sync/util/pthread_helpers.h"
#include "chrome/browser/sync/util/sync_types.h"

namespace syncable {
struct DirectoryManagerEvent;
class DirectoryManager;
}

namespace browser_sync {
class AllStatus;
class AuthWatcher;
class ServerConnectionManager;
class TalkMediator;
class URLFactory;
class UserSettings;
struct ServerConnectionEvent;

struct AuthWatcherEvent {
  enum WhatHappened {
    AUTHENTICATION_ATTEMPT_START,
    AUTHWATCHER_DESTROYED,
    AUTH_SUCCEEDED,
    GAIA_AUTH_FAILED,
    SERVICE_USER_NOT_SIGNED_UP,
    SERVICE_AUTH_FAILED,
    SERVICE_CONNECTION_FAILED,
    // Used in a safety check in AuthWatcher::AuthenticateWithToken()
    ILLEGAL_VALUE,
  };
  WhatHappened what_happened;
  const GaiaAuthenticator::AuthResults* auth_results;
  // use AuthWatcherEvent as its own traits type in hookups.
  typedef AuthWatcherEvent EventType;
  static inline bool IsChannelShutdownEvent(const AuthWatcherEvent& event) {
    return event.what_happened == AUTHWATCHER_DESTROYED;
  }

  // Used for AUTH_SUCCEEDED notification
  std::string user_email;

  // How was this auth attempt initiated?
  enum AuthenticationTrigger {
    USER_INITIATED = 0,  // default value.
    EXPIRED_CREDENTIALS,
  };

  AuthenticationTrigger trigger;
};

class AuthWatcher {
 public:
  // Normal progression is local -> gaia -> token
  enum Status { LOCALLY_AUTHENTICATED, GAIA_AUTHENTICATED, NOT_AUTHENTICATED };
  typedef syncable::DirectoryManagerEvent DirectoryManagerEvent;
  typedef syncable::DirectoryManager DirectoryManager;
  typedef TalkMediator TalkMediator;

  AuthWatcher(DirectoryManager* dirman,
              ServerConnectionManager* scm,
              AllStatus* allstatus,
              const std::string& user_agent,
              const std::string& service_id,
              const std::string& gaia_url,
              UserSettings* user_settings,
              GaiaAuthenticator* gaia_auth,
              TalkMediator* talk_mediator);
  ~AuthWatcher();

  // Returns true if the open share has gotten zero
  // updates from the sync server (initial sync complete.)
  bool LoadDirectoryListAndOpen(const PathString& login);

  typedef EventChannel<AuthWatcherEvent, PThreadMutex> Channel;

  inline Channel* channel() const {
    return channel_.get();
  }

  void Authenticate(const std::string& email, const std::string& password,
      const std::string& captcha_token, const std::string& captcha_value,
      bool persist_creds_to_disk);

  void Authenticate(const std::string& email, const std::string& password,
      bool persist_creds_to_disk) {
    Authenticate(email, password, "", "", persist_creds_to_disk);
  }

  // Retrieves an auth token for a named service for which a long-lived token
  // was obtained at login time. Returns true if a long-lived token can be
  // found, false otherwise.
  bool GetAuthTokenForService(const std::string& service_name,
                              std::string* service_token);

  std::string email() const;
  syncable::DirectoryManager* dirman() const { return dirman_; }
  ServerConnectionManager* scm() const { return scm_; }
  AllStatus* allstatus() const { return allstatus_; }
  UserSettings* settings() const { return user_settings_; }
  Status status() const { return (Status)status_; }

  void Logout();

  // For synchronizing other destructors.
  void WaitForAuthThreadFinish();

 protected:
  void Reset();
  void ClearAuthenticationData();

  void NotifyAuthSucceeded(const std::string& email);
  bool StartNewAuthAttempt(const std::string& email,
      const std::string& password,
      const std::string& auth_token, const std::string& captcha_token,
      const std::string& captcha_value, bool persist_creds_to_disk,
      AuthWatcherEvent::AuthenticationTrigger trigger);
  void HandleServerConnectionEvent(const ServerConnectionEvent& event);

  void SaveUserSettings(const std::string& username,
                        const std::string& auth_token,
                        const bool save_credentials);

  // These two helpers should only be called from the auth function.
  // returns false iff we had problems and should try GAIA_AUTH again.
  bool ProcessGaiaAuthSuccess();
  void ProcessGaiaAuthFailure();

  // Just checks that the user has at least one local share cache.
  bool AuthenticateLocally(std::string email);
  // Also checks the user's password against stored password hash.
  bool AuthenticateLocally(std::string email, const std::string& password);

  // Sets the trigger member of the event and sends the event on channel_.
  void NotifyListeners(AuthWatcherEvent* event);

  const std::string& sync_service_token() const { return sync_service_token_; }

 public:
  bool AuthenticateWithToken(const std::string& email,
                             const std::string& auth_token);

 protected:
  typedef PThreadScopedLock<PThreadMutex> MutexLock;

  // Passed to newly created threads.
  struct ThreadParams {
    AuthWatcher* self;
    std::string email;
    std::string password;
    std::string auth_token;
    std::string captcha_token;
    std::string captcha_value;
    bool persist_creds_to_disk;
    AuthWatcherEvent::AuthenticationTrigger trigger;
  };

  // Initial function passed to pthread_create.
  static void* AuthenticationThreadStartRoutine(void* arg);
  // Member function called by AuthenticationThreadStartRoutine.
  void* AuthenticationThreadMain(struct ThreadParams* arg);

  scoped_ptr<GaiaAuthenticator> const gaia_;
  syncable::DirectoryManager* const dirman_;
  ServerConnectionManager* const scm_;
  scoped_ptr<EventListenerHookup> connmgr_hookup_;
  AllStatus* const allstatus_;
  // TODO(chron): It is incorrect to make assignments to AtomicWord.
  volatile base::subtle::AtomicWord status_;
  UserSettings* user_settings_;
  TalkMediator* talk_mediator_;  // Interface to the notifications engine.
  scoped_ptr<Channel> channel_;

  // We store our service token in memory as a workaround to the fact that we
  // don't persist it when the user unchecks "remember me".
  // We also include it on outgoing requests.
  std::string sync_service_token_;

  PThreadMutex mutex_;
  // All members below are protected by the above mutex
  pthread_t thread_;
  bool thread_handle_valid_;
  bool authenticating_now_;
  AuthWatcherEvent::AuthenticationTrigger current_attempt_trigger_;
};

}  // namespace browser_sync

#endif  // CHROME_BROWSER_SYNC_ENGINE_AUTH_WATCHER_H_