1// Copyright 2014 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// An invalidator that uses p2p invalidations based on XMPP push
6// notifications.  Used only for sync integration tests.
7
8#ifndef COMPONENTS_INVALIDATION_P2P_INVALIDATOR_H_
9#define COMPONENTS_INVALIDATION_P2P_INVALIDATOR_H_
10
11#include <string>
12
13#include "base/compiler_specific.h"
14#include "base/memory/ref_counted.h"
15#include "base/memory/scoped_ptr.h"
16#include "base/memory/weak_ptr.h"
17#include "base/observer_list.h"
18#include "base/threading/thread_checker.h"
19#include "components/invalidation/invalidation_export.h"
20#include "components/invalidation/invalidator.h"
21#include "components/invalidation/invalidator_registrar.h"
22#include "components/invalidation/invalidator_state.h"
23#include "components/invalidation/object_id_invalidation_map.h"
24#include "jingle/notifier/base/notifier_options.h"
25#include "jingle/notifier/listener/push_client.h"
26#include "jingle/notifier/listener/push_client_observer.h"
27
28namespace notifier {
29class PushClient;
30}  // namespace notifier
31
32namespace syncer {
33
34// The channel to use for sync notifications.
35INVALIDATION_EXPORT extern const char kSyncP2PNotificationChannel[];
36
37// The intended recipient(s) of a P2P notification.
38enum P2PNotificationTarget {
39  NOTIFY_SELF,
40  FIRST_NOTIFICATION_TARGET = NOTIFY_SELF,
41  NOTIFY_OTHERS,
42  NOTIFY_ALL,
43  LAST_NOTIFICATION_TARGET = NOTIFY_ALL
44};
45
46INVALIDATION_EXPORT_PRIVATE std::string P2PNotificationTargetToString(
47    P2PNotificationTarget target);
48
49// If |target_str| can't be parsed, assumes NOTIFY_SELF.
50INVALIDATION_EXPORT_PRIVATE P2PNotificationTarget
51P2PNotificationTargetFromString(const std::string& target_str);
52
53// Helper notification data class that can be serialized to and
54// deserialized from a string.
55class INVALIDATION_EXPORT_PRIVATE P2PNotificationData {
56 public:
57  // Initializes with an empty sender ID, target set to NOTIFY_SELF,
58  // and empty changed types.
59  P2PNotificationData();
60  P2PNotificationData(const std::string& sender_id,
61                      P2PNotificationTarget target,
62                      const ObjectIdInvalidationMap& invalidation_map);
63
64  ~P2PNotificationData();
65
66  // Returns true if the given ID is targeted by this notification.
67  bool IsTargeted(const std::string& id) const;
68
69  const ObjectIdInvalidationMap& GetIdInvalidationMap() const;
70
71  bool Equals(const P2PNotificationData& other) const;
72
73  std::string ToString() const;
74
75  // Returns whether parsing |str| was successful.  If parsing was
76  // unsuccessful, the state of the notification is undefined.
77  bool ResetFromString(const std::string& str);
78
79 private:
80  // The unique ID of the client that sent the notification.
81  std::string sender_id_;
82  // The intendent recipient(s) of the notification.
83  P2PNotificationTarget target_;
84  // The invalidation map for the notification.
85  ObjectIdInvalidationMap invalidation_map_;
86};
87
88class INVALIDATION_EXPORT_PRIVATE P2PInvalidator
89    : public Invalidator,
90      public NON_EXPORTED_BASE(notifier::PushClientObserver) {
91 public:
92  // The |send_notification_target| parameter was added to allow us to send
93  // self-notifications in some cases, but not others.  The value should be
94  // either NOTIFY_ALL to send notifications to all clients, or NOTIFY_OTHERS
95  // to send notifications to all clients except for the one that triggered the
96  // notification.  See crbug.com/97780.
97  P2PInvalidator(scoped_ptr<notifier::PushClient> push_client,
98                 const std::string& invalidator_client_id,
99                 P2PNotificationTarget send_notification_target);
100
101  virtual ~P2PInvalidator();
102
103  // Invalidator implementation.
104  virtual void RegisterHandler(InvalidationHandler* handler) OVERRIDE;
105  virtual void UpdateRegisteredIds(InvalidationHandler* handler,
106                                   const ObjectIdSet& ids) OVERRIDE;
107  virtual void UnregisterHandler(InvalidationHandler* handler) OVERRIDE;
108  virtual InvalidatorState GetInvalidatorState() const OVERRIDE;
109  virtual void UpdateCredentials(
110      const std::string& email, const std::string& token) OVERRIDE;
111  virtual void RequestDetailedStatus(
112      base::Callback<void(const base::DictionaryValue&)> callback) const
113      OVERRIDE;
114
115  // PushClientObserver implementation.
116  virtual void OnNotificationsEnabled() OVERRIDE;
117  virtual void OnNotificationsDisabled(
118      notifier::NotificationsDisabledReason reason) OVERRIDE;
119  virtual void OnIncomingNotification(
120      const notifier::Notification& notification) OVERRIDE;
121
122  void SendInvalidation(const ObjectIdSet& ids);
123
124  void SendNotificationDataForTest(
125      const P2PNotificationData& notification_data);
126
127 private:
128  void SendNotificationData(const P2PNotificationData& notification_data);
129
130  base::ThreadChecker thread_checker_;
131
132  InvalidatorRegistrar registrar_;
133
134  // The push client.
135  scoped_ptr<notifier::PushClient> push_client_;
136  // Our unique ID.
137  std::string invalidator_client_id_;
138  // Whether we have called UpdateCredentials() yet.
139  bool logged_in_;
140  bool notifications_enabled_;
141  // Which set of clients should be sent notifications.
142  P2PNotificationTarget send_notification_target_;
143
144  DISALLOW_COPY_AND_ASSIGN(P2PInvalidator);
145};
146
147}  // namespace syncer
148
149#endif  // COMPONENTS_INVALIDATION_P2P_INVALIDATOR_H_
150