- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / api / dial / dial_registry.h
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_EXTENSIONS_API_DIAL_DIAL_REGISTRY_H_
6 #define CHROME_BROWSER_EXTENSIONS_API_DIAL_DIAL_REGISTRY_H_
7
8 #include <map>
9 #include <string>
10 #include <vector>
11
12 #include "base/basictypes.h"
13 #include "base/containers/hash_tables.h"
14 #include "base/gtest_prod_util.h"
15 #include "base/memory/linked_ptr.h"
16 #include "base/memory/ref_counted.h"
17 #include "base/threading/thread_checker.h"
18 #include "base/time/time.h"
19 #include "base/timer/timer.h"
20 #include "chrome/browser/extensions/api/dial/dial_service.h"
21 #include "chrome/browser/profiles/profile.h"
22 #include "net/base/network_change_notifier.h"
23
24 namespace extensions {
25
26 // Keeps track of devices that have responded to discovery requests and notifies
27 // the observer with an updated, complete set of active devices.  The registry's
28 // observer (i.e., the Dial API) owns the registry instance.
29 class DialRegistry : public DialService::Observer,
30                      public net::NetworkChangeNotifier::NetworkChangeObserver {
31  public:
32   typedef std::vector<DialDeviceData> DeviceList;
33
34   enum DialErrorCode {
35     DIAL_NO_LISTENERS = 0,
36     DIAL_NO_INTERFACES,
37     DIAL_NETWORK_DISCONNECTED,
38     DIAL_CELLULAR_NETWORK,
39     DIAL_SOCKET_ERROR,
40     DIAL_UNKNOWN
41   };
42
43   class Observer {
44    public:
45     // Methods invoked on the IO thread when a new device is discovered, an
46     // update is triggered by dial.discoverNow or an error occured.
47     virtual void OnDialDeviceEvent(const DeviceList& devices) = 0;
48     virtual void OnDialError(DialErrorCode type) = 0;
49
50    protected:
51     virtual ~Observer() {}
52   };
53
54   // Create the DIAL registry and pass a reference to allow it to notify on
55   // DIAL device events.
56   DialRegistry(Observer* dial_api,
57                const base::TimeDelta& refresh_interval,
58                const base::TimeDelta& expiration,
59                const size_t max_devices);
60
61   virtual ~DialRegistry();
62
63   // Called by the DIAL API when event listeners are added or removed. The dial
64   // service is started after the first listener is added and stopped after the
65   // last listener is removed.
66   void OnListenerAdded();
67   void OnListenerRemoved();
68
69   // Called by the DIAL API to try to kickoff a discovery if there is not one
70   // already active.
71   bool DiscoverNow();
72
73  protected:
74   // Returns a new instance of the DIAL service.  Overridden by tests.
75   virtual DialService* CreateDialService();
76   virtual void ClearDialService();
77
78   // Returns the current time.  Overridden by tests.
79   virtual base::Time Now() const;
80
81  protected:
82   // The DIAL service. Periodic discovery is active when this is not NULL.
83   scoped_ptr<DialService> dial_;
84
85  private:
86   typedef base::hash_map<std::string, linked_ptr<DialDeviceData> >
87       DeviceByIdMap;
88   typedef std::map<std::string, linked_ptr<DialDeviceData> > DeviceByLabelMap;
89
90   // DialService::Observer:
91   virtual void OnDiscoveryRequest(DialService* service) OVERRIDE;
92   virtual void OnDeviceDiscovered(DialService* service,
93                                   const DialDeviceData& device) OVERRIDE;
94   virtual void OnDiscoveryFinished(DialService* service) OVERRIDE;
95   virtual void OnError(DialService* service,
96                        const DialService::DialServiceErrorCode& code) OVERRIDE;
97
98   // net::NetworkChangeObserver:
99   virtual void OnNetworkChanged(
100       net::NetworkChangeNotifier::ConnectionType type) OVERRIDE;
101
102   // Starts and stops periodic discovery.  Periodic discovery is done when there
103   // are registered event listeners.
104   void StartPeriodicDiscovery();
105   void StopPeriodicDiscovery();
106
107   // Check whether we are in a state ready to discover and dispatch error
108   // notifications if not.
109   bool ReadyToDiscover();
110
111   // Purge our whole registry. We may need to do this occasionally, e.g. when
112   // the network status changes.  Increments the registry generation.
113   void Clear();
114
115   // The repeating timer schedules discoveries with this method.
116   void DoDiscovery();
117
118   // Attempts to add a newly discovered device to the registry.  Returns true if
119   // successful.
120   bool MaybeAddDevice(const linked_ptr<DialDeviceData>& device_data);
121
122   // Remove devices from the registry that have expired, i.e. not responded
123   // after some time.  Returns true if the registry was modified.
124   bool PruneExpiredDevices();
125
126   // Returns true if the device has expired and should be removed from the
127   // active set.
128   bool IsDeviceExpired(const DialDeviceData& device) const;
129
130   // Notify clients with the current device list if necessary.
131   void MaybeSendEvent();
132
133   // Returns the next label to use for a newly-seen device.
134   std::string NextLabel();
135
136   // The current number of event listeners attached to this registry.
137   int num_listeners_;
138
139   // Incremented each time we DoDiscovery().
140   int discovery_generation_;
141
142   // Incremented each time we modify the registry of active devices.
143   int registry_generation_;
144
145   // The discovery generation associated with the last time we sent an event.
146   // Used to ensure that we generate at least one event per round of discovery.
147   int last_event_discovery_generation_;
148
149   // The registry generation associated with the last time we sent an event.
150   // Used to suppress events with duplicate device lists.
151   int last_event_registry_generation_;
152
153   // Counter to generate device labels.
154   int label_count_;
155
156   // Registry parameters
157   base::TimeDelta refresh_interval_delta_;
158   base::TimeDelta expiration_delta_;
159   size_t max_devices_;
160
161   // A map used to track known devices by their device_id.
162   DeviceByIdMap device_by_id_map_;
163
164   // A map used to track known devices sorted by label.  We iterate over this to
165   // construct the device list sent to API clients.
166   DeviceByLabelMap device_by_label_map_;
167
168   // Timer used to manage periodic discovery requests.
169   base::RepeatingTimer<DialRegistry> repeating_timer_;
170
171   // Interface from which the DIAL API is notified of DIAL device events. the
172   // DIAL API owns this DIAL registry.
173   Observer* const dial_api_;
174
175   // Thread checker.
176   base::ThreadChecker thread_checker_;
177
178   FRIEND_TEST_ALL_PREFIXES(DialRegistryTest, TestAddRemoveListeners);
179   FRIEND_TEST_ALL_PREFIXES(DialRegistryTest, TestNoDevicesDiscovered);
180   FRIEND_TEST_ALL_PREFIXES(DialRegistryTest, TestDevicesDiscovered);
181   FRIEND_TEST_ALL_PREFIXES(DialRegistryTest, TestDeviceExpires);
182   FRIEND_TEST_ALL_PREFIXES(DialRegistryTest, TestExpiredDeviceIsRediscovered);
183   FRIEND_TEST_ALL_PREFIXES(DialRegistryTest,
184                            TestRemovingListenerDoesNotClearList);
185   FRIEND_TEST_ALL_PREFIXES(DialRegistryTest, TestNetworkEventConnectionLost);
186   FRIEND_TEST_ALL_PREFIXES(DialRegistryTest,
187                            TestNetworkEventConnectionRestored);
188   DISALLOW_COPY_AND_ASSIGN(DialRegistry);
189 };
190
191 }  // namespace extensions
192
193 #endif  // CHROME_BROWSER_EXTENSIONS_API_DIAL_DIAL_REGISTRY_H_