1// Copyright (c) 2011 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#ifndef CHROME_BROWSER_PASSWORD_MANAGER_PASSWORD_STORE_H_
6#define CHROME_BROWSER_PASSWORD_MANAGER_PASSWORD_STORE_H_
7#pragma once
8
9#include <vector>
10
11#include "base/callback.h"
12#include "base/memory/ref_counted.h"
13#include "base/observer_list.h"
14#include "base/threading/thread.h"
15#include "base/time.h"
16#include "content/browser/cancelable_request.h"
17
18class PasswordStoreConsumer;
19class Task;
20
21namespace browser_sync {
22class PasswordDataTypeController;
23class PasswordModelAssociator;
24class PasswordModelWorker;
25};
26
27namespace webkit_glue {
28struct PasswordForm;
29};
30
31// Interface for storing form passwords in a platform-specific secure way.
32// The login request/manipulation API is not threadsafe and must be used
33// from the UI thread.
34class PasswordStore
35    : public base::RefCountedThreadSafe<PasswordStore>,
36      public CancelableRequestProvider {
37 public:
38  typedef Callback2<Handle,
39                    const std::vector<webkit_glue::PasswordForm*>&>::Type
40      GetLoginsCallback;
41
42  // PasswordForm vector elements are meant to be owned by the
43  // PasswordStoreConsumer. However, if the request is canceled after the
44  // allocation, then the request must take care of the deletion.
45  // TODO(scr) If we can convert vector<PasswordForm*> to
46  // ScopedVector<PasswordForm>, then we can move the following class to merely
47  // a typedef. At the moment, a subclass of CancelableRequest1 is required to
48  // provide a destructor, which cleans up after canceled requests by deleting
49  // vector elements.
50  class GetLoginsRequest : public CancelableRequest1<
51    GetLoginsCallback, std::vector<webkit_glue::PasswordForm*> > {
52   public:
53    explicit GetLoginsRequest(GetLoginsCallback* callback);
54    virtual ~GetLoginsRequest();
55
56   private:
57    DISALLOW_COPY_AND_ASSIGN(GetLoginsRequest);
58  };
59
60  // An interface used to notify clients (observers) of this object that data in
61  // the password store has changed. Register the observer via
62  // PasswordStore::SetObserver.
63  class Observer {
64   public:
65    // Notifies the observer that password data changed in some way.
66    virtual void OnLoginsChanged() = 0;
67
68   protected:
69    virtual ~Observer() {}
70  };
71
72  PasswordStore();
73
74  // Reimplement this to add custom initialization. Always call this too.
75  virtual bool Init();
76
77  // Invoked from the profiles destructor to shutdown the PasswordStore.
78  virtual void Shutdown();
79
80  // Adds the given PasswordForm to the secure password store asynchronously.
81  virtual void AddLogin(const webkit_glue::PasswordForm& form);
82
83  // Updates the matching PasswordForm in the secure password store (async).
84  void UpdateLogin(const webkit_glue::PasswordForm& form);
85
86  // Removes the matching PasswordForm from the secure password store (async).
87  void RemoveLogin(const webkit_glue::PasswordForm& form);
88
89  // Removes all logins created in the given date range.
90  void RemoveLoginsCreatedBetween(const base::Time& delete_begin,
91                                  const base::Time& delete_end);
92
93  // Searches for a matching PasswordForm and returns a handle so the async
94  // request can be tracked. Implement the PasswordStoreConsumer interface to be
95  // notified on completion.
96  virtual Handle GetLogins(const webkit_glue::PasswordForm& form,
97                           PasswordStoreConsumer* consumer);
98
99  // Gets the complete list of PasswordForms that are not blacklist entries--and
100  // are thus auto-fillable--and returns a handle so the async request can be
101  // tracked. Implement the PasswordStoreConsumer interface to be notified on
102  // completion.
103  Handle GetAutofillableLogins(PasswordStoreConsumer* consumer);
104
105  // Gets the complete list of PasswordForms that are blacklist entries, and
106  // returns a handle so the async request can be tracked. Implement the
107  // PasswordStoreConsumer interface to be notified on completion.
108  Handle GetBlacklistLogins(PasswordStoreConsumer* consumer);
109
110  // Reports usage metrics for the database.
111  void ReportMetrics();
112
113  // Adds an observer to be notified when the password store data changes.
114  void AddObserver(Observer* observer);
115
116  // Removes |observer| from the observer list.
117  void RemoveObserver(Observer* observer);
118
119 protected:
120  friend class base::RefCountedThreadSafe<PasswordStore>;
121  friend class browser_sync::PasswordDataTypeController;
122  friend class browser_sync::PasswordModelAssociator;
123  friend class browser_sync::PasswordModelWorker;
124  friend class LivePasswordsSyncTest;
125
126  virtual ~PasswordStore();
127
128  // Provided to allow subclasses to extend GetLoginsRequest if additional info
129  // is needed between a call and its Impl.
130  virtual GetLoginsRequest* NewGetLoginsRequest(GetLoginsCallback* callback);
131
132  // Schedule the given |task| to be run in the PasswordStore's own thread.
133  virtual void ScheduleTask(Task* task);
134
135  // These will be run in PasswordStore's own thread.
136  // Synchronous implementation that reports usage metrics.
137  virtual void ReportMetricsImpl() = 0;
138  // Synchronous implementation to add the given login.
139  virtual void AddLoginImpl(const webkit_glue::PasswordForm& form) = 0;
140  // Synchronous implementation to update the given login.
141  virtual void UpdateLoginImpl(const webkit_glue::PasswordForm& form) = 0;
142  // Synchronous implementation to remove the given login.
143  virtual void RemoveLoginImpl(const webkit_glue::PasswordForm& form) = 0;
144  // Synchronous implementation to remove the given logins.
145  virtual void RemoveLoginsCreatedBetweenImpl(const base::Time& delete_begin,
146                                              const base::Time& delete_end) = 0;
147  // Should find all PasswordForms with the same signon_realm. The results
148  // will then be scored by the PasswordFormManager. Once they are found
149  // (or not), the consumer should be notified.
150  virtual void GetLoginsImpl(GetLoginsRequest* request,
151                             const webkit_glue::PasswordForm& form) = 0;
152  // Finds all non-blacklist PasswordForms, and notifies the consumer.
153  virtual void GetAutofillableLoginsImpl(GetLoginsRequest* request) = 0;
154  // Finds all blacklist PasswordForms, and notifies the consumer.
155  virtual void GetBlacklistLoginsImpl(GetLoginsRequest* request) = 0;
156
157  // Finds all non-blacklist PasswordForms, and fills the vector.
158  virtual bool FillAutofillableLogins(
159      std::vector<webkit_glue::PasswordForm*>* forms) = 0;
160  // Finds all blacklist PasswordForms, and fills the vector.
161  virtual bool FillBlacklistLogins(
162      std::vector<webkit_glue::PasswordForm*>* forms) = 0;
163
164  // Dispatches the result to the PasswordStoreConsumer on the original caller's
165  // thread so the callback can be executed there.  This should be the UI
166  // thread.
167  virtual void ForwardLoginsResult(GetLoginsRequest* request);
168
169  // Schedule the given |func| to be run in the PasswordStore's own thread with
170  // responses delivered to |consumer| on the current thread.
171  template<typename BackendFunc>
172  Handle Schedule(BackendFunc func, PasswordStoreConsumer* consumer);
173
174  // Schedule the given |func| to be run in the PasswordStore's own thread with
175  // argument |a| and responses delivered to |consumer| on the current thread.
176  template<typename BackendFunc, typename ArgA>
177  Handle Schedule(BackendFunc func, PasswordStoreConsumer* consumer,
178                  const ArgA& a);
179
180 private:
181  // Wrapper method called on the destination thread (DB for non-mac) that calls
182  // the method specified in |task| and then calls back into the source thread
183  // to notify observers that the password store may have been modified via
184  // NotifyLoginsChanged(). Note that there is no guarantee that the called
185  // method will actually modify the password store data. |task| may not be
186  // NULL. This method owns and will delete |task|.
187  void WrapModificationTask(Task* task);
188
189  // Post a message to the UI thread to run NotifyLoginsChanged(). Called by
190  // WrapModificationTask() above, and split out as a separate method so that
191  // password sync can call it as well after synchronously updating the password
192  // store.
193  void PostNotifyLoginsChanged();
194
195  // Called by WrapModificationTask() once the underlying data-modifying
196  // operation has been performed. Notifies observers that password store data
197  // may have been changed.
198  void NotifyLoginsChanged();
199
200  // The observers.
201  ObserverList<Observer> observers_;
202
203  DISALLOW_COPY_AND_ASSIGN(PasswordStore);
204};
205
206#endif  // CHROME_BROWSER_PASSWORD_MANAGER_PASSWORD_STORE_H_
207