summaryrefslogtreecommitdiffstats
path: root/chrome/browser/notifications/sync_notifier/chrome_notifier_service.h
blob: 356448fbd1dd1eabbd87edb8a5b6763d4bd38c31 (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
// 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_NOTIFICATIONS_SYNC_NOTIFIER_CHROME_NOTIFIER_SERVICE_H_
#define CHROME_BROWSER_NOTIFICATIONS_SYNC_NOTIFIER_CHROME_NOTIFIER_SERVICE_H_

#include <string>

#include "base/basictypes.h"
#include "base/memory/scoped_vector.h"
#include "base/prefs/pref_member.h"
#include "base/threading/non_thread_safe.h"
#include "chrome/browser/notifications/sync_notifier/synced_notification.h"
#include "components/browser_context_keyed_service/browser_context_keyed_service.h"
#include "sync/api/syncable_service.h"

class NotificationUIManager;
class Profile;

namespace user_prefs {
class PrefRegistrySyncable;
}

namespace message_center {
struct Notifier;
}

namespace notifier {

extern const char kFirstSyncedNotificationServiceId[];
extern const char kServiceEnabledOnce[];
extern const char kSyncedNotificationFirstRun[];

enum ChromeNotifierServiceActionType {
  CHROME_NOTIFIER_SERVICE_ACTION_UNKNOWN,
  CHROME_NOTIFIER_SERVICE_ACTION_FIRST_SERVICE_ENABLED,
  CHROME_NOTIFIER_SERVICE_ACTION_FIRST_SERVICE_DISABLED,
  // NOTE: Add new action types only immediately above this line. Also,
  // make sure the enum list in tools/histogram/histograms.xml is
  // updated with any change in here.
  CHROME_NOTIFIER_SERVICE_ACTION_COUNT
};

// The ChromeNotifierService holds notifications which represent the state of
// delivered notifications for chrome. These are obtained from the sync service
// and kept up to date.
class ChromeNotifierService : public syncer::SyncableService,
                              public BrowserContextKeyedService {
 public:
  ChromeNotifierService(Profile* profile, NotificationUIManager* manager);
  virtual ~ChromeNotifierService();

  // Methods from BrowserContextKeyedService.
  virtual void Shutdown() OVERRIDE;

  // syncer::SyncableService implementation.
  virtual syncer::SyncMergeResult MergeDataAndStartSyncing(
      syncer::ModelType type,
      const syncer::SyncDataList& initial_sync_data,
      scoped_ptr<syncer::SyncChangeProcessor> sync_processor,
      scoped_ptr<syncer::SyncErrorFactory> error_handler) OVERRIDE;
  virtual void StopSyncing(syncer::ModelType type) OVERRIDE;
  virtual syncer::SyncDataList GetAllSyncData(
      syncer::ModelType type) const OVERRIDE;
  virtual syncer::SyncError ProcessSyncChanges(
      const tracked_objects::Location& from_here,
      const syncer::SyncChangeList& change_list) OVERRIDE;

  // Convert from internal representation to SyncData representation.
  static syncer::SyncData CreateSyncDataFromNotification(
      const SyncedNotification& notification);

  // Convert from SyncData representation to internal representation.
  static scoped_ptr<SyncedNotification> CreateNotificationFromSyncData(
      const syncer::SyncData& sync_data);

  // Get a pointer to a notification.  ChromeNotifierService owns this pointer.
  virtual notifier::SyncedNotification* FindNotificationById(
      const std::string& notification_id);

  // Get the list of synced notification services and fill their meta data to
  // |notifiers|.
  void GetSyncedNotificationServices(
      std::vector<message_center::Notifier*>* notifiers);

  // Called when we dismiss a notification.  This is virtual so that test
  // subclasses can override it.
  virtual void MarkNotificationAsRead(const std::string& id);

  // Called when a notier is enabled or disabled.
  void OnSyncedNotificationServiceEnabled(
      const std::string& notifier_id,
      bool enabled);

  // Register the preferences we use to save state.
  static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);

  Profile* profile() const { return profile_; }

  // Functions for test.
  void AddForTest(scoped_ptr<notifier::SyncedNotification> notification);

  // If we allow the tests to do bitmap fetching, they will attempt to fetch
  // a URL from the web, which will fail.  We can already test the majority
  // of what we want without also trying to fetch bitmaps.  Other tests will
  // cover bitmap fetching.
  static void set_avoid_bitmap_fetching_for_test(bool avoid) {
    avoid_bitmap_fetching_for_test_ = avoid;
  }

  // Initialize the preferences we use for the ChromeNotificationService.
  void InitializePrefs();

 private:
  // Add a notification to our list.  This takes ownership of the pointer.
  void Add(scoped_ptr<notifier::SyncedNotification> notification);

  // Display this notification in the notification center, or remove it.
  void UpdateInMessageCenter(notifier::SyncedNotification* notification);

  // Display a notification in the notification center (eventually).
  void Display(notifier::SyncedNotification* notification);

  // Remove a notification from our store.
  void FreeNotificationById(const std::string& notification_id);

  // When a service it turned on, scan our cache for any notifications
  // for that service, and display them if they are unread.
  void DisplayUnreadNotificationsFromSource(const std::string& notifier_id);

  // When a service it turned off, scan our cache for any notifications
  // for that service, and remove them from the message center.
  void RemoveUnreadNotificationsFromSource(const std::string& notifier_id);

  // When we turn a sending service on or off, collect statistics about
  // how often users turn it on or off.
  void CollectPerServiceEnablingStatistics(const std::string& notifier_id,
                                           bool enabled);

  // When we start up or hear of a new service, turn it on by default.
  void AddNewSendingServices();

  // Called when the string list pref has been changed.
  void OnEnabledSendingServiceListPrefChanged(std::set<std::string>* ids_field);

  // Called when the string list pref has been changed.
  void OnInitializedSendingServiceListPrefChanged(
      std::set<std::string>* ids_field);

  // Called when our "first run" boolean pref has been changed.
  void OnSyncedNotificationFirstRunBooleanPrefChanged(bool* new_value);

  // Convert our internal set of strings to a list value.
  // The second param is an outparam which the function fills in.
  void BuildServiceListValueInplace(
      std::set<std::string> services, base::ListValue* list_value);

  // Preferences for storing which SyncedNotificationServices are enabled
  StringListPrefMember enabled_sending_services_prefs_;
  StringListPrefMember initialized_sending_services_prefs_;

  // Preferences to avoid toasting on SyncedNotification first run.
  BooleanPrefMember synced_notification_first_run_prefs_;

  // Back pointer to the owning profile.
  Profile* const profile_;
  NotificationUIManager* const notification_manager_;
  scoped_ptr<syncer::SyncChangeProcessor> sync_processor_;
  std::set<std::string> enabled_sending_services_;
  std::set<std::string> initialized_sending_services_;
  bool synced_notification_first_run_;
  static bool avoid_bitmap_fetching_for_test_;

  // TODO(petewil): Consider whether a map would better suit our data.
  // If there are many entries, lookup time may trump locality of reference.
  ScopedVector<notifier::SyncedNotification> notification_data_;

  friend class ChromeNotifierServiceTest;
  FRIEND_TEST_ALL_PREFIXES(ChromeNotifierServiceTest, ServiceEnabledTest);
  FRIEND_TEST_ALL_PREFIXES(ChromeNotifierServiceTest,
                           AddNewSendingServicesTest);
  FRIEND_TEST_ALL_PREFIXES(ChromeNotifierServiceTest,
                           GetEnabledSendingServicesFromPreferencesTest);


  DISALLOW_COPY_AND_ASSIGN(ChromeNotifierService);
};

}  // namespace notifier

#endif  // CHROME_BROWSER_NOTIFICATIONS_SYNC_NOTIFIER_CHROME_NOTIFIER_SERVICE_H_