summaryrefslogtreecommitdiffstats
path: root/chrome/browser/chromeos/contacts/google_contact_store.h
blob: 877372251a59f7117c1d789511e4223610ffc34d (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
// Copyright (c) 2012 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.

#ifndef CHROME_BROWSER_CHROMEOS_CONTACTS_GOOGLE_CONTACT_STORE_H_
#define CHROME_BROWSER_CHROMEOS_CONTACTS_GOOGLE_CONTACT_STORE_H_

#include "chrome/browser/chromeos/contacts/contact_store.h"

#include <map>
#include <string>
#include <vector>

#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "chrome/browser/chromeos/contacts/contact_map.h"
#include "net/base/network_change_notifier.h"

class Profile;

namespace net {
class URLRequestContextGetter;
}  // namespace net

namespace contacts {

class Contact;
class ContactDatabaseInterface;
class GDataContactsServiceInterface;
class UpdateMetadata;

// A collection of contacts from a Google account.
class GoogleContactStore
    : public ContactStore,
      public net::NetworkChangeNotifier::ConnectionTypeObserver {
 public:
  class TestAPI {
   public:
    explicit TestAPI(GoogleContactStore* store);
    ~TestAPI();

    bool update_scheduled() { return store_->update_timer_.IsRunning(); }
    base::Time last_contact_update_time() const {
      return store_->last_contact_update_time_;
    }
    void set_current_time(const base::Time& time) {
      store_->current_time_for_testing_ = time;
    }

    // Takes ownership of |db|. Must be called before Init().
    void SetDatabase(ContactDatabaseInterface* db);

    // Takes ownership of |service|. Must be called before Init(). The caller is
    // responsible for calling |service|'s Initialize() method.
    void SetGDataService(GDataContactsServiceInterface* service);

    // Triggers an update, similar to what happens when the update timer fires.
    void DoUpdate();

    // Notifies the store that the system has gone online or offline.
    void NotifyAboutNetworkStateChange(bool online);

    // Returns pointers to all of the contacts in the store's |contacts_|
    // member.
    scoped_ptr<ContactPointers> GetLoadedContacts();

   private:
    GoogleContactStore* store_;  // not owned

    DISALLOW_COPY_AND_ASSIGN(TestAPI);
  };

  GoogleContactStore(
      net::URLRequestContextGetter* url_request_context_getter,
      Profile* profile);
  virtual ~GoogleContactStore();

  // ContactStore implementation:
  virtual void Init() OVERRIDE;
  virtual void AppendContacts(ContactPointers* contacts_out) OVERRIDE;
  virtual const Contact* GetContactById(const std::string& contact_id) OVERRIDE;
  virtual void AddObserver(ContactStoreObserver* observer) OVERRIDE;
  virtual void RemoveObserver(ContactStoreObserver* observer) OVERRIDE;

  // net::NetworkChangeNotifier::ConnectionTypeObserver implementation:
  virtual void OnConnectionTypeChanged(
      net::NetworkChangeNotifier::ConnectionType type) OVERRIDE;

 private:
  // Returns the current time. Uses |current_time_for_testing_| instead if it's
  // set.
  base::Time GetCurrentTime() const;

  // Destroys |db_| if non-NULL and resets the pointer.
  // The underlying data is preserved on-disk.
  void DestroyDatabase();

  // Asynchronously downloads updated contacts and merges them into |contacts_|.
  void UpdateContacts();

  // Starts |update_timer_| so UpdateContacts() will be run.
  void ScheduleUpdate(bool last_update_was_successful);

  // Moves |updated_contacts| into |contacts_| and updates
  // |last_contact_update_time_|.
  void MergeContacts(bool is_full_update,
                     scoped_ptr<ScopedVector<Contact> > updated_contacts);

  // Handles a successful download, merging |updated_contacts| and saving the
  // updated contacts to |db_|.
  void OnDownloadSuccess(bool is_full_update,
                         const base::Time& update_start_time,
                         scoped_ptr<ScopedVector<Contact> > updated_contacts);

  // Handles a failed update. A new update is scheduled.
  void OnDownloadFailure();

  // Handles |db_|'s initialization. On success, we start loading the contacts
  // from the database; otherwise, we throw out the database and schedule an
  // update.
  void OnDatabaseInitialized(bool success);

  // Handles contacts being loaded from |db_|. On success, we merge the loaded
  // contacts. No matter what, we call UpdateContacts().
  void OnDatabaseContactsLoaded(bool success,
                                scoped_ptr<ScopedVector<Contact> > contacts,
                                scoped_ptr<UpdateMetadata> metadata);

  // Handles contacts being saved to |db_|. Now that the contacts are no longer
  // being accessed by the database, we schedule an update.
  void OnDatabaseContactsSaved(bool success);

  net::URLRequestContextGetter* url_request_context_getter_;  // not owned

  Profile* profile_;  // not owned

  ObserverList<ContactStoreObserver> observers_;

  // Owns the pointed-to Contact values.
  ContactMap contacts_;

  // Most-recent time that an entry in |contacts_| has been updated (as reported
  // by Google).
  base::Time last_contact_update_time_;

  // Used to download contacts.
  scoped_ptr<GDataContactsServiceInterface> gdata_service_;

  // Used to save contacts to disk and load them at startup. Owns the object.
  ContactDatabaseInterface* db_;

  // Used to schedule calls to UpdateContacts().
  base::OneShotTimer<GoogleContactStore> update_timer_;

  // Time at which the last successful update was started.
  base::Time last_successful_update_start_time_;

  // Amount of time that we'll wait before retrying the next time that an update
  // fails.
  base::TimeDelta update_delay_on_next_failure_;

  // Do we believe that it's likely that we'll be able to make network
  // connections?
  bool is_online_;

  // Should we call UpdateContacts() when |is_online_| becomes true?  Set when
  // UpdateContacts() is called while we're offline.
  bool should_update_when_online_;

  // If non-null, used in place of base::Time::Now() when the current time is
  // needed.
  base::Time current_time_for_testing_;

  // Note: This should remain the last member so it'll be destroyed and
  // invalidate its weak pointers before any other members are destroyed.
  base::WeakPtrFactory<GoogleContactStore> weak_ptr_factory_;

  DISALLOW_COPY_AND_ASSIGN(GoogleContactStore);
};

// ContactStoreFactory implementation that returns GoogleContactStores.
class GoogleContactStoreFactory : public ContactStoreFactory {
 public:
  GoogleContactStoreFactory();
  virtual ~GoogleContactStoreFactory();

  // ContactStoreFactory implementation:
  virtual bool CanCreateContactStoreForProfile(Profile* profile) OVERRIDE;
  virtual ContactStore* CreateContactStore(Profile* profile) OVERRIDE;

 private:
  DISALLOW_COPY_AND_ASSIGN(GoogleContactStoreFactory);
};

}  // namespace contacts

#endif  // CHROME_BROWSER_CHROMEOS_CONTACTS_GOOGLE_CONTACT_STORE_H_