1// Copyright (c) 2012 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_NATIVE_BACKEND_GNOME_X_H_
6#define CHROME_BROWSER_PASSWORD_MANAGER_NATIVE_BACKEND_GNOME_X_H_
7
8// libgnome-keyring has been deprecated in favor of libsecret.
9// See: https://mail.gnome.org/archives/commits-list/2013-October/msg08876.html
10//
11// The define below turns off the deprecations, in order to avoid build
12// failures with Gnome 3.12. When we move to libsecret, the define can be
13// removed, together with the include below it.
14//
15// The porting is tracked in http://crbug.com/355223
16#define GNOME_KEYRING_DEPRECATED
17#define GNOME_KEYRING_DEPRECATED_FOR(x)
18#include <gnome-keyring.h>
19
20#include <string>
21
22#include "base/basictypes.h"
23#include "base/time/time.h"
24#include "chrome/browser/password_manager/password_store_factory.h"
25#include "chrome/browser/password_manager/password_store_x.h"
26#include "chrome/browser/profiles/profile.h"
27
28namespace autofill {
29struct PasswordForm;
30}
31
32// Many of the gnome_keyring_* functions use variable arguments, which makes
33// them difficult if not impossible to truly wrap in C. Therefore, we use
34// appropriately-typed function pointers and scoping to make the fact that we
35// might be dynamically loading the library almost invisible. As a bonus, we
36// also get a simple way to mock the library for testing. Classes that inherit
37// from GnomeKeyringLoader will use its versions of the gnome_keyring_*
38// functions. Note that it has only static fields.
39class GnomeKeyringLoader {
40 protected:
41  static bool LoadGnomeKeyring();
42
43// Call a given parameter with the name of each function we use from GNOME
44// Keyring. Make sure to adjust the unit test if you change these.
45// The list of functions is divided into those we plan to mock in the unittest,
46// and those which we use without mocking in the test.
47#define GNOME_KEYRING_FOR_EACH_MOCKED_FUNC(F)      \
48  F(is_available)                                  \
49  F(store_password)                                \
50  F(delete_password)                               \
51  F(find_items)                                    \
52  F(result_to_message)
53#define GNOME_KEYRING_FOR_EACH_NON_MOCKED_FUNC(F)  \
54  F(attribute_list_free)                           \
55  F(attribute_list_new)                            \
56  F(attribute_list_append_string)                  \
57  F(attribute_list_append_uint32)
58#define GNOME_KEYRING_FOR_EACH_FUNC(F)             \
59  GNOME_KEYRING_FOR_EACH_NON_MOCKED_FUNC(F)        \
60  GNOME_KEYRING_FOR_EACH_MOCKED_FUNC(F)
61
62// Declare the actual function pointers that we'll use in client code.
63#define GNOME_KEYRING_DECLARE_POINTER(name) \
64    static typeof(&::gnome_keyring_##name) gnome_keyring_##name;
65  GNOME_KEYRING_FOR_EACH_FUNC(GNOME_KEYRING_DECLARE_POINTER)
66#undef GNOME_KEYRING_DECLARE_POINTER
67
68  // Set to true if LoadGnomeKeyring() has already succeeded.
69  static bool keyring_loaded;
70
71 private:
72#if defined(DLOPEN_GNOME_KEYRING)
73  struct FunctionInfo {
74    const char* name;
75    void** pointer;
76  };
77
78  // Make it easy to initialize the function pointers in LoadGnomeKeyring().
79  static const FunctionInfo functions[];
80#endif  // defined(DLOPEN_GNOME_KEYRING)
81};
82
83// NativeBackend implementation using GNOME Keyring.
84class NativeBackendGnome : public PasswordStoreX::NativeBackend,
85                           public GnomeKeyringLoader {
86 public:
87  explicit NativeBackendGnome(LocalProfileId id);
88
89  virtual ~NativeBackendGnome();
90
91  virtual bool Init() OVERRIDE;
92
93  // Implements NativeBackend interface.
94  virtual password_manager::PasswordStoreChangeList AddLogin(
95      const autofill::PasswordForm& form) OVERRIDE;
96  virtual bool UpdateLogin(
97      const autofill::PasswordForm& form,
98      password_manager::PasswordStoreChangeList* changes) OVERRIDE;
99  virtual bool RemoveLogin(const autofill::PasswordForm& form) OVERRIDE;
100  virtual bool RemoveLoginsCreatedBetween(
101      base::Time delete_begin,
102      base::Time delete_end,
103      password_manager::PasswordStoreChangeList* changes) OVERRIDE;
104  virtual bool RemoveLoginsSyncedBetween(
105      base::Time delete_begin,
106      base::Time delete_end,
107      password_manager::PasswordStoreChangeList* changes) OVERRIDE;
108  virtual bool GetLogins(const autofill::PasswordForm& form,
109                         PasswordFormList* forms) OVERRIDE;
110  virtual bool GetAutofillableLogins(PasswordFormList* forms) OVERRIDE;
111  virtual bool GetBlacklistLogins(PasswordFormList* forms) OVERRIDE;
112
113 private:
114  enum TimestampToCompare {
115    CREATION_TIMESTAMP,
116    SYNC_TIMESTAMP,
117  };
118
119  // Adds a login form without checking for one to replace first.
120  bool RawAddLogin(const autofill::PasswordForm& form);
121
122  // Reads PasswordForms from the keyring with the given autofillability state.
123  bool GetLoginsList(PasswordFormList* forms, bool autofillable);
124
125  // Helper for GetLoginsCreatedBetween().
126  bool GetAllLogins(PasswordFormList* forms);
127
128  // Retrieves password created/synced in the time interval. Returns |true| if
129  // the operation succeeded.
130  bool GetLoginsBetween(base::Time get_begin,
131                        base::Time get_end,
132                        TimestampToCompare date_to_compare,
133                        PasswordFormList* forms);
134
135  // Removes password created/synced in the time interval. Returns |true| if the
136  // operation succeeded. |changes| will contain the changes applied.
137  bool RemoveLoginsBetween(base::Time get_begin,
138                           base::Time get_end,
139                           TimestampToCompare date_to_compare,
140                           password_manager::PasswordStoreChangeList* changes);
141
142  // Generates a profile-specific app string based on profile_id_.
143  std::string GetProfileSpecificAppString() const;
144
145  // The local profile id, used to generate the app string.
146  const LocalProfileId profile_id_;
147
148  // The app string, possibly based on the local profile id.
149  std::string app_string_;
150
151  DISALLOW_COPY_AND_ASSIGN(NativeBackendGnome);
152};
153
154#endif  // CHROME_BROWSER_PASSWORD_MANAGER_NATIVE_BACKEND_GNOME_X_H_
155