Index: components/proximity_auth/bluetooth_throttler.h |
diff --git a/components/proximity_auth/bluetooth_throttler.h b/components/proximity_auth/bluetooth_throttler.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..6b0d244c5c5b8cf9fa2c6f8921a786ea5424fd3b |
--- /dev/null |
+++ b/components/proximity_auth/bluetooth_throttler.h |
@@ -0,0 +1,113 @@ |
+// Copyright 2014 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 COMPONENTS_PROXIMITY_AUTH_BLUETOOTH_THROTTLER_H |
+#define COMPONENTS_PROXIMITY_AUTH_BLUETOOTH_THROTTLER_H |
+ |
+#include "base/macros.h" |
+#include "base/memory/ref_counted.h" |
+#include "base/memory/scoped_ptr.h" |
+#include "base/time/default_tick_clock.h" |
+#include "base/time/time.h" |
+#include "components/proximity_auth/connection_finder.h" |
+#include "components/proximity_auth/connection_observer.h" |
+#include "components/proximity_auth/remote_device.h" |
+ |
+namespace base { |
+class TaskRunner; |
+class TickClock; |
+} |
+ |
+namespace device { |
+class BluetoothUUID; |
+} |
+ |
+namespace proximity_auth { |
+ |
+class Connection; |
+ |
+// This class throttles repeated connection attempts to the same device. This |
+// throttling is necessary to prevent a kernel race condition when connecting |
+// before the previous connection fully closes, putting the connection in a |
+// corrupted, and unrecoverable state. http://crbug.com/345232 |
Tim Song
2014/10/27 17:49:25
This is actually not entirely true now that this i
Ilya Sherman
2014/10/28 00:40:47
Hmm, but is that a valid thing to do? What if the
Tim Song
2014/11/20 23:00:09
That's true. Maybe disconnect also works. I'll hav
|
+class BluetoothThrottler : public ConnectionObserver { |
+ public: |
+ // Creates a throttler for connections to the |remote_device|. |
+ BluetoothThrottler(const RemoteDevice& remote_device); |
+ virtual ~BluetoothThrottler(); |
+ |
+ // Attempts to find a connection to the service with the given |uuid| running |
+ // on the |remote_device| passed to the constructor. This is similar to |
+ // calling |BluetoothConnectionFinder::Find()|, but the connections will be |
+ // throttled to prevent hitting a kernel race condition. Will continue to try |
+ // to find the connection indefinitely until |StopFindingConnections()| is |
+ // called. Calls |connection_callback| with the open connection once the |
+ // remote device is connected. |
+ // Note: This method must not be called a second time prior to calling |
+ // StopFindingConnections(). |
+ void FindConnection( |
+ const device::BluetoothUUID& uuid, |
+ const ConnectionFinder::ConnectionCallback& connection_callback); |
+ |
+ // Cancels any running or pending connection searches. |
+ void StopFindingConnections(); |
+ |
+ protected: |
+ // Creates a connection finder targeting the service with the given |uuid| on |
+ // the |remote_device_|. Exposed for overriding in tests. |
+ virtual scoped_ptr<ConnectionFinder> CreateConnectionFinder( |
+ const device::BluetoothUUID& uuid); |
+ |
+ // Returns the duration to wait before reattempting a connection to the |
+ // |remote_device_|. Exposed for testing. |
+ base::TimeDelta GetCooldownTimeDelta() const; |
+ |
+ // Returns the task runner to use for posting delayed tasks. |
+ // Exposed for overriding in tests. |
+ virtual scoped_refptr<base::TaskRunner> GetTaskRunner() const; |
+ |
+ // Returns the clock to use for computing time ticks. |
+ // Exposed for overriding in tests. |
+ virtual base::TickClock* GetTickClock(); |
+ |
+ private: |
+ // Callback for a connection. |
+ void OnConnection( |
+ const ConnectionFinder::ConnectionCallback& connection_callback, |
+ scoped_ptr<Connection> connection); |
+ |
+ // ConnectionObserver: |
+ virtual void OnConnectionStatusChanged( |
+ const Connection& connection, |
+ Connection::Status old_status, |
+ Connection::Status new_status) override; |
+ |
+ // The device to connect to. |
+ const RemoteDevice remote_device_; |
+ |
+ // Tracks the last seen disconnect time for the |remote_device_|. |
+ base::TimeTicks last_disconnect_time_; |
+ |
+ // The currently running connection finder; null iff there is no currently |
+ // running connection finder. |
+ scoped_ptr<ConnectionFinder> connection_finder_; |
+ |
+ // The most current connection; null iff there is no current connection. |
+ // Stored as a weak reference, which is safe because |this| instance is |
+ // registered as an observer, and will unregister when the connection |
+ // disconnects, which is guaranteed to occur before the connection is |
+ // destroyed. |
+ Connection* connection_; |
+ |
+ // Default time source; overridable by tests. |
+ base::DefaultTickClock clock_; |
+ |
+ base::WeakPtrFactory<BluetoothThrottler> weak_ptr_factory_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(BluetoothThrottler); |
+}; |
+ |
+} // namespace proximity_auth |
+ |
+#endif // COMPONENTS_PROXIMITY_AUTH_BLUETOOTH_THROTTLER_H |