Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / extensions / api / dial / dial_registry.h
blob83caa382a15ca60b4c4404de06fe06e1b22a7981
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.
5 #ifndef CHROME_BROWSER_EXTENSIONS_API_DIAL_DIAL_REGISTRY_H_
6 #define CHROME_BROWSER_EXTENSIONS_API_DIAL_DIAL_REGISTRY_H_
8 #include <map>
9 #include <string>
10 #include <vector>
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"
24 namespace extensions {
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;
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
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;
50 protected:
51 virtual ~Observer() {}
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);
61 ~DialRegistry() override;
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();
69 // Called by the DIAL API to try to kickoff a discovery if there is not one
70 // already active.
71 bool DiscoverNow();
73 protected:
74 // Returns a new instance of the DIAL service. Overridden by tests.
75 virtual DialService* CreateDialService();
76 virtual void ClearDialService();
78 // Returns the current time. Overridden by tests.
79 virtual base::Time Now() const;
81 protected:
82 // The DIAL service. Periodic discovery is active when this is not NULL.
83 scoped_ptr<DialService> dial_;
85 private:
86 typedef base::hash_map<std::string, linked_ptr<DialDeviceData> >
87 DeviceByIdMap;
88 typedef std::map<std::string, linked_ptr<DialDeviceData> > DeviceByLabelMap;
90 // DialService::Observer:
91 void OnDiscoveryRequest(DialService* service) override;
92 void OnDeviceDiscovered(DialService* service,
93 const DialDeviceData& device) override;
94 void OnDiscoveryFinished(DialService* service) override;
95 void OnError(DialService* service,
96 const DialService::DialServiceErrorCode& code) override;
98 // net::NetworkChangeObserver:
99 void OnNetworkChanged(
100 net::NetworkChangeNotifier::ConnectionType type) override;
102 // Starts and stops periodic discovery. Periodic discovery is done when there
103 // are registered event listeners.
104 void StartPeriodicDiscovery();
105 void StopPeriodicDiscovery();
107 // Check whether we are in a state ready to discover and dispatch error
108 // notifications if not.
109 bool ReadyToDiscover();
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();
115 // The repeating timer schedules discoveries with this method.
116 void DoDiscovery();
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);
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();
126 // Returns true if the device has expired and should be removed from the
127 // active set.
128 bool IsDeviceExpired(const DialDeviceData& device) const;
130 // Notify clients with the current device list if necessary.
131 void MaybeSendEvent();
133 // Returns the next label to use for a newly-seen device.
134 std::string NextLabel();
136 // The current number of event listeners attached to this registry.
137 int num_listeners_;
139 // Incremented each time we DoDiscovery().
140 int discovery_generation_;
142 // Incremented each time we modify the registry of active devices.
143 int registry_generation_;
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_;
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_;
153 // Counter to generate device labels.
154 int label_count_;
156 // Registry parameters
157 base::TimeDelta refresh_interval_delta_;
158 base::TimeDelta expiration_delta_;
159 size_t max_devices_;
161 // A map used to track known devices by their device_id.
162 DeviceByIdMap device_by_id_map_;
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_;
168 // Timer used to manage periodic discovery requests.
169 base::RepeatingTimer<DialRegistry> repeating_timer_;
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_;
175 // Thread checker.
176 base::ThreadChecker thread_checker_;
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);
191 } // namespace extensions
193 #endif // CHROME_BROWSER_EXTENSIONS_API_DIAL_DIAL_REGISTRY_H_