summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ash/DEPS1
-rw-r--r--ash/ash.gyp9
-rw-r--r--ash/ash_chromeos_strings.grdp18
-rw-r--r--ash/shell.cc3
-rw-r--r--ash/shell.h3
-rw-r--r--ash/system/chromeos/bluetooth/bluetooth_notification_controller.cc301
-rw-r--r--ash/system/chromeos/bluetooth/bluetooth_notification_controller.h89
-rw-r--r--ash/system/system_notifier.cc4
-rw-r--r--ash/system/system_notifier.h3
-rw-r--r--chromeos/dbus/fake_bluetooth_adapter_client.cc5
-rw-r--r--chromeos/dbus/fake_bluetooth_device_client.cc85
-rw-r--r--chromeos/dbus/fake_bluetooth_device_client.h6
-rw-r--r--device/bluetooth/bluetooth_device_chromeos.cc1
-rw-r--r--device/bluetooth/bluetooth_pairing_chromeos.cc44
-rw-r--r--device/bluetooth/bluetooth_pairing_chromeos.h4
15 files changed, 557 insertions, 19 deletions
diff --git a/ash/DEPS b/ash/DEPS
index a178653..aa8ff27 100644
--- a/ash/DEPS
+++ b/ash/DEPS
@@ -1,4 +1,5 @@
include_rules = [
+ "+device/bluetooth",
"+cc/debug",
"+chromeos",
"+gpu/config",
diff --git a/ash/ash.gyp b/ash/ash.gyp
index 00343ea..9da87bb 100644
--- a/ash/ash.gyp
+++ b/ash/ash.gyp
@@ -288,6 +288,8 @@
'system/chromeos/audio/tray_audio_delegate_chromeos.cc',
'system/chromeos/audio/tray_audio_delegate_chromeos.h',
'system/chromeos/enterprise/enterprise_domain_observer.h',
+ 'system/chromeos/bluetooth/bluetooth_notification_controller.cc',
+ 'system/chromeos/bluetooth/bluetooth_notification_controller.h',
'system/chromeos/brightness/brightness_controller_chromeos.cc',
'system/chromeos/brightness/brightness_controller_chromeos.h',
'system/chromeos/brightness/tray_brightness.cc',
@@ -668,6 +670,7 @@
'../chromeos/chromeos.gyp:chromeos',
# Ash #includes power_supply_properties.pb.h directly.
'../chromeos/chromeos.gyp:power_manager_proto',
+ '../device/bluetooth/bluetooth.gyp:device_bluetooth',
],
}, { # else: chromeos!=1
'sources/': [
@@ -1010,6 +1013,7 @@
['chromeos==1', {
'dependencies': [
'../chromeos/chromeos.gyp:power_manager_proto',
+ '../device/bluetooth/bluetooth.gyp:device_bluetooth',
],
'sources': [
'first_run/first_run_helper_unittest.cc',
@@ -1109,6 +1113,11 @@
'../sandbox/sandbox.gyp:sandbox',
],
}],
+ ['chromeos==1', {
+ 'dependencies': [
+ '../device/bluetooth/bluetooth.gyp:device_bluetooth',
+ ],
+ }],
],
},
],
diff --git a/ash/ash_chromeos_strings.grdp b/ash/ash_chromeos_strings.grdp
index 4040270..c6651e0 100644
--- a/ash/ash_chromeos_strings.grdp
+++ b/ash/ash_chromeos_strings.grdp
@@ -124,6 +124,24 @@
<message name="IDS_ASH_STATUS_TRAY_CELLULAR_SCANNING" desc="Message when scanning for cellular networks">
Searching for cellular networks...
</message>
+ <message name="IDS_ASH_STATUS_TRAY_BLUETOOTH_DISPLAY_PINCODE" desc="Bluetooth pairing message typically shown on a request from a 2.0 device that has a keyboard.">
+ Bluetooth device "<ph name="DEVICE_NAME">$1<ex>Nexus S</ex></ph>" would like permission to pair. Please enter this PIN code on that device: <ph name="PINCODE">$2<ex>123456</ex></ph>
+ </message>
+ <message name="IDS_ASH_STATUS_TRAY_BLUETOOTH_DISPLAY_PASSKEY" desc="Bluetooth pairing message typically shown on a request from a device that has a keyboard.">
+ Bluetooth device "<ph name="DEVICE_NAME">$1<ex>Nexus S</ex></ph>" would like permission to pair. Please enter this passkey on that device: <ph name="PASSKEY">$2<ex>123456</ex></ph>
+ </message>
+ <message name="IDS_ASH_STATUS_TRAY_BLUETOOTH_CONFIRM_PASSKEY" desc="Bluetooth pairing message typically shown on a request from a device that has a display.">
+ Bluetooth device "<ph name="DEVICE_NAME">$1<ex>Nexus S</ex></ph>" would like permission to pair. Before accepting, please confirm that this passkey is shown on that device: <ph name="PASSKEY">$2<ex>123456</ex></ph>
+ </message>
+ <message name="IDS_ASH_STATUS_TRAY_BLUETOOTH_AUTHORIZE_PAIRING" desc="Bluetooth pairing message typically shown on a request from a device without input or display.">
+ Bluetooth device "<ph name="DEVICE_NAME">$1<ex>Nexus S</ex></ph>" would like permission to pair.
+ </message>
+ <message name="IDS_ASH_STATUS_TRAY_BLUETOOTH_ACCEPT" desc="Message on button to accept Bluetooth pairing request.">
+ Accept
+ </message>
+ <message name="IDS_ASH_STATUS_TRAY_BLUETOOTH_REJECT" desc="Message on button to reject Bluetooth pairing request.">
+ Reject
+ </message>
<!-- Other Network UI strings -->
<message name="IDS_NETWORK_CONNECTION_ERROR_TITLE" desc="Title for network connection error notification">
diff --git a/ash/shell.cc b/ash/shell.cc
index f1a037b..b46ad3f 100644
--- a/ash/shell.cc
+++ b/ash/shell.cc
@@ -129,6 +129,7 @@
#endif // defined(USE_X11)
#include "ash/display/resolution_notification_controller.h"
#include "ash/sticky_keys/sticky_keys_controller.h"
+#include "ash/system/chromeos/bluetooth/bluetooth_notification_controller.h"
#include "ash/system/chromeos/brightness/brightness_controller_chromeos.h"
#include "ash/system/chromeos/power/power_event_observer.h"
#include "ash/system/chromeos/power/power_status.h"
@@ -998,6 +999,8 @@ void Shell::Init() {
new internal::UserActivityNotifier(user_activity_detector_.get()));
video_activity_notifier_.reset(
new internal::VideoActivityNotifier(video_detector_.get()));
+ bluetooth_notification_controller_.reset(
+ new internal::BluetoothNotificationController);
#endif
weak_display_manager_factory_.reset(
diff --git a/ash/shell.h b/ash/shell.h
index ae79a29..cdab1e0 100644
--- a/ash/shell.h
+++ b/ash/shell.h
@@ -118,6 +118,7 @@ class WindowSelectorController;
namespace internal {
class AcceleratorFilter;
class AppListController;
+class BluetoothNotificationController;
class CaptureController;
class DisplayChangeObserver;
class DisplayErrorObserver;
@@ -706,6 +707,8 @@ class ASH_EXPORT Shell
scoped_ptr<StickyKeysController> sticky_keys_controller_;
scoped_ptr<internal::ResolutionNotificationController>
resolution_notification_controller_;
+ scoped_ptr<internal::BluetoothNotificationController>
+ bluetooth_notification_controller_;
#if defined(USE_X11)
// Controls video output device state.
scoped_ptr<chromeos::OutputConfigurator> output_configurator_;
diff --git a/ash/system/chromeos/bluetooth/bluetooth_notification_controller.cc b/ash/system/chromeos/bluetooth/bluetooth_notification_controller.cc
new file mode 100644
index 0000000..1a3aae3
--- /dev/null
+++ b/ash/system/chromeos/bluetooth/bluetooth_notification_controller.cc
@@ -0,0 +1,301 @@
+// 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.
+
+#include "ash/system/chromeos/bluetooth/bluetooth_notification_controller.h"
+
+#include "ash/system/system_notifier.h"
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
+#include "device/bluetooth/bluetooth_adapter_factory.h"
+#include "device/bluetooth/bluetooth_device.h"
+#include "grit/ash_resources.h"
+#include "grit/ash_strings.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/message_center/message_center.h"
+#include "ui/message_center/notification.h"
+#include "ui/message_center/notification_delegate.h"
+#include "ui/message_center/notification_types.h"
+
+using device::BluetoothAdapter;
+using device::BluetoothAdapterFactory;
+using device::BluetoothDevice;
+using message_center::Notification;
+
+namespace {
+
+// Identifier for the pairing notification; the Bluetooth code ensures we
+// only receive one pairing request at a time, so a single id is sufficient and
+// means we "update" one notification if not handled rather than continually
+// bugging the user.
+const char kBluetoothDevicePairingNotificationId[] =
+ "chrome://settings/bluetooth/pairing";
+
+// The BluetoothPairingNotificationDelegate handles user interaction with the
+// pairing notification and sending the confirmation, rejection or cancellation
+// back to the underlying device.
+class BluetoothPairingNotificationDelegate
+ : public message_center::NotificationDelegate {
+ public:
+ BluetoothPairingNotificationDelegate(scoped_refptr<BluetoothAdapter> adapter,
+ const std::string& address);
+
+ protected:
+ virtual ~BluetoothPairingNotificationDelegate();
+
+ // message_center::NotificationDelegate overrides.
+ virtual void Display() OVERRIDE;
+ virtual void Error() OVERRIDE;
+ virtual void Close(bool by_user) OVERRIDE;
+ virtual bool HasClickedListener() OVERRIDE;
+ virtual void Click() OVERRIDE;
+ virtual void ButtonClick(int button_index) OVERRIDE;
+
+ private:
+ // Buttons that appear in notifications.
+ enum Button {
+ BUTTON_ACCEPT,
+ BUTTON_REJECT
+ };
+
+ // Reference to the underlying Bluetooth Adapter, holding onto this
+ // reference ensures the adapter object doesn't go out of scope while we have
+ // a pending request and user interaction.
+ scoped_refptr<BluetoothAdapter> adapter_;
+
+ // Address of the device being paired.
+ const std::string address_;
+
+ DISALLOW_COPY_AND_ASSIGN(BluetoothPairingNotificationDelegate);
+};
+
+BluetoothPairingNotificationDelegate::BluetoothPairingNotificationDelegate(
+ scoped_refptr<BluetoothAdapter> adapter,
+ const std::string& address)
+ : adapter_(adapter),
+ address_(address) {
+}
+
+BluetoothPairingNotificationDelegate::~BluetoothPairingNotificationDelegate() {
+}
+
+void BluetoothPairingNotificationDelegate::Display() {
+}
+
+void BluetoothPairingNotificationDelegate::Error() {
+}
+
+void BluetoothPairingNotificationDelegate::Close(bool by_user) {
+ VLOG(1) << "Pairing notification closed. by_user = " << by_user;
+ // Ignore notification closes generated as a result of pairing completion.
+ if (!by_user)
+ return;
+
+ // Cancel the pairing of the device, if the object still exists.
+ BluetoothDevice* device = adapter_->GetDevice(address_);
+ if (device)
+ device->CancelPairing();
+}
+
+bool BluetoothPairingNotificationDelegate::HasClickedListener() {
+ return false;
+}
+
+void BluetoothPairingNotificationDelegate::Click() {
+}
+
+void BluetoothPairingNotificationDelegate::ButtonClick(int button_index) {
+ VLOG(1) << "Pairing notification, button click: " << button_index;
+ // If the device object still exists, send the appropriate response either
+ // confirming or rejecting the pairing.
+ BluetoothDevice* device = adapter_->GetDevice(address_);
+ if (device) {
+ switch (button_index) {
+ case BUTTON_ACCEPT:
+ device->ConfirmPairing();
+ break;
+ case BUTTON_REJECT:
+ device->RejectPairing();
+ break;
+ }
+ }
+
+ // In any case, remove this pairing notification.
+ message_center::MessageCenter::Get()->RemoveNotification(
+ kBluetoothDevicePairingNotificationId, false /* by_user */);
+}
+
+} // namespace
+
+
+namespace ash {
+namespace internal {
+
+BluetoothNotificationController::BluetoothNotificationController()
+ : weak_ptr_factory_(this) {
+ BluetoothAdapterFactory::GetAdapter(
+ base::Bind(&BluetoothNotificationController::OnGetAdapter,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+BluetoothNotificationController::~BluetoothNotificationController() {
+ if (adapter_.get()) {
+ adapter_->RemoveObserver(this);
+ adapter_->RemovePairingDelegate(this);
+ adapter_ = NULL;
+ }
+}
+
+
+void BluetoothNotificationController::DeviceAdded(BluetoothAdapter* adapter,
+ BluetoothDevice* device) {
+ if (device->IsPaired()) {
+ paired_devices_.insert(device->GetAddress());
+ NotifyPairedDevice(device);
+ }
+}
+
+void BluetoothNotificationController::DeviceChanged(BluetoothAdapter* adapter,
+ BluetoothDevice* device) {
+ if (paired_devices_.find(device->GetAddress()) != paired_devices_.end())
+ return;
+
+ if (device->IsPaired()) {
+ paired_devices_.insert(device->GetAddress());
+ NotifyPairedDevice(device);
+ }
+}
+
+void BluetoothNotificationController::DeviceRemoved(BluetoothAdapter* adapter,
+ BluetoothDevice* device) {
+ paired_devices_.erase(device->GetAddress());
+}
+
+
+void BluetoothNotificationController::RequestPinCode(BluetoothDevice* device) {
+ // Cannot provide keyboard entry in a notification; these devices (old car
+ // audio systems for the most part) will need pairing to be initiated from
+ // the Chromebook.
+ device->CancelPairing();
+}
+
+void BluetoothNotificationController::RequestPasskey(BluetoothDevice* device) {
+ // Cannot provide keyboard entry in a notification; fortunately the spec
+ // doesn't allow for this to be an option when we're receiving the pairing
+ // request anyway.
+ device->CancelPairing();
+}
+
+void BluetoothNotificationController::DisplayPinCode(
+ BluetoothDevice* device,
+ const std::string& pincode) {
+ base::string16 message = l10n_util::GetStringFUTF16(
+ IDS_ASH_STATUS_TRAY_BLUETOOTH_DISPLAY_PINCODE,
+ device->GetName(), base::UTF8ToUTF16(pincode));
+
+ NotifyPairing(device, message, false);
+}
+
+void BluetoothNotificationController::DisplayPasskey(BluetoothDevice* device,
+ uint32 passkey) {
+ base::string16 message = l10n_util::GetStringFUTF16(
+ IDS_ASH_STATUS_TRAY_BLUETOOTH_DISPLAY_PASSKEY,
+ device->GetName(), base::UTF8ToUTF16(
+ base::StringPrintf("%06i", passkey)));
+
+ NotifyPairing(device, message, false);
+}
+
+void BluetoothNotificationController::KeysEntered(BluetoothDevice* device,
+ uint32 entered) {
+ // Ignored since we don't have CSS in the notification to update.
+}
+
+void BluetoothNotificationController::ConfirmPasskey(BluetoothDevice* device,
+ uint32 passkey) {
+ base::string16 message = l10n_util::GetStringFUTF16(
+ IDS_ASH_STATUS_TRAY_BLUETOOTH_CONFIRM_PASSKEY,
+ device->GetName(), base::UTF8ToUTF16(
+ base::StringPrintf("%06i", passkey)));
+
+ NotifyPairing(device, message, true);
+}
+
+void BluetoothNotificationController::AuthorizePairing(
+ BluetoothDevice* device) {
+ base::string16 message = l10n_util::GetStringFUTF16(
+ IDS_ASH_STATUS_TRAY_BLUETOOTH_AUTHORIZE_PAIRING,
+ device->GetName());
+
+ NotifyPairing(device, message, true);
+}
+
+
+void BluetoothNotificationController::OnGetAdapter(
+ scoped_refptr<BluetoothAdapter> adapter) {
+ DCHECK(!adapter_.get());
+ adapter_ = adapter;
+ adapter_->AddObserver(this);
+ adapter_->AddPairingDelegate(this,
+ BluetoothAdapter::PAIRING_DELEGATE_PRIORITY_LOW);
+
+ // Build a list of the currently paired devices; these don't receive
+ // notifications since it's assumed they were previously notified.
+ BluetoothAdapter::DeviceList devices = adapter_->GetDevices();
+ for (BluetoothAdapter::DeviceList::const_iterator iter = devices.begin();
+ iter != devices.end(); ++iter) {
+ const BluetoothDevice* device = *iter;
+ if (device->IsPaired())
+ paired_devices_.insert(device->GetAddress());
+ }
+}
+
+
+void BluetoothNotificationController::NotifyPairing(
+ BluetoothDevice* device,
+ const base::string16& message,
+ bool with_buttons) {
+ message_center::RichNotificationData optional;
+ if (with_buttons) {
+ optional.buttons.push_back(message_center::ButtonInfo(
+ l10n_util::GetStringUTF16(
+ IDS_ASH_STATUS_TRAY_BLUETOOTH_ACCEPT)));
+ optional.buttons.push_back(message_center::ButtonInfo(
+ l10n_util::GetStringUTF16(
+ IDS_ASH_STATUS_TRAY_BLUETOOTH_REJECT)));
+ }
+
+ ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
+
+ scoped_ptr<Notification> notification(new Notification(
+ message_center::NOTIFICATION_TYPE_SIMPLE,
+ kBluetoothDevicePairingNotificationId,
+ base::string16() /* title */,
+ message,
+ bundle.GetImageNamed(IDR_AURA_UBER_TRAY_BLUETOOTH),
+ base::string16() /* display source */,
+ message_center::NotifierId(
+ message_center::NotifierId::SYSTEM_COMPONENT,
+ system_notifier::kNotifierBluetooth),
+ optional,
+ new BluetoothPairingNotificationDelegate(adapter_,
+ device->GetAddress())));
+ message_center::MessageCenter::Get()->AddNotification(notification.Pass());
+}
+
+void BluetoothNotificationController::NotifyPairedDevice(
+ BluetoothDevice* device) {
+ // Remove the currently presented pairing notification; since only one
+ // pairing request is queued at a time, this is guaranteed to be the device
+ // that just became paired.
+ message_center::MessageCenter::Get()->RemoveNotification(
+ kBluetoothDevicePairingNotificationId, false /* by_user */);
+}
+
+} // namespace internal
+} // namespace ash
diff --git a/ash/system/chromeos/bluetooth/bluetooth_notification_controller.h b/ash/system/chromeos/bluetooth/bluetooth_notification_controller.h
new file mode 100644
index 0000000..dde8692
--- /dev/null
+++ b/ash/system/chromeos/bluetooth/bluetooth_notification_controller.h
@@ -0,0 +1,89 @@
+// 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 ASH_SYSTEM_CHROMEOS_BLUETOOTH_BLUETOOTH_NOTIFICATION_CONTROLLER_H_
+#define ASH_SYSTEM_CHROMEOS_BLUETOOTH_BLUETOOTH_NOTIFICATION_CONTROLLER_H_
+
+#include <set>
+
+#include "ash/ash_export.h"
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "base/strings/string16.h"
+#include "device/bluetooth/bluetooth_adapter.h"
+#include "device/bluetooth/bluetooth_device.h"
+
+namespace ash {
+namespace internal {
+
+// The BluetoothNotificationController receives incoming pairing requests from
+// the BluetoothAdapter, and notifications of changes to the adapter state and
+// set of paired devices. It presents incoming pairing requests in the form of
+// rich notifications that the user can interact with to approve the request.
+class ASH_EXPORT BluetoothNotificationController
+ : public device::BluetoothAdapter::Observer,
+ public device::BluetoothDevice::PairingDelegate {
+ public:
+ BluetoothNotificationController();
+ virtual ~BluetoothNotificationController();
+
+ // device::BluetoothAdapter::Observer override.
+ virtual void DeviceAdded(device::BluetoothAdapter* adapter,
+ device::BluetoothDevice* device) OVERRIDE;
+ virtual void DeviceChanged(device::BluetoothAdapter* adapter,
+ device::BluetoothDevice* device) OVERRIDE;
+ virtual void DeviceRemoved(device::BluetoothAdapter* adapter,
+ device::BluetoothDevice* device) OVERRIDE;
+
+ // device::BluetoothDevice::PairingDelegate override.
+ virtual void RequestPinCode(device::BluetoothDevice* device) OVERRIDE;
+ virtual void RequestPasskey(device::BluetoothDevice* device) OVERRIDE;
+ virtual void DisplayPinCode(device::BluetoothDevice* device,
+ const std::string& pincode) OVERRIDE;
+ virtual void DisplayPasskey(device::BluetoothDevice* device,
+ uint32 passkey) OVERRIDE;
+ virtual void KeysEntered(device::BluetoothDevice* device,
+ uint32 entered) OVERRIDE;
+ virtual void ConfirmPasskey(device::BluetoothDevice* device,
+ uint32 passkey) OVERRIDE;
+ virtual void AuthorizePairing(device::BluetoothDevice* device) OVERRIDE;
+
+ private:
+ // Internal method called by BluetoothAdapterFactory to provide the adapter
+ // object.
+ void OnGetAdapter(scoped_refptr<device::BluetoothAdapter> adapter);
+
+ // Presents a notification to the user that a device |device| is making a
+ // pairing request. The exact message to display is given in |message| and
+ // should include all relevant instructions, if |with_buttons| is true then
+ // the notification will have Accept and Reject buttons, if false only the
+ // usual cancel/dismiss button will be present on the notification.
+ void NotifyPairing(device::BluetoothDevice* device,
+ const base::string16& message,
+ bool with_buttons);
+
+ // Clears any shown pairing notification now that the device has been paired.
+ void NotifyPairedDevice(device::BluetoothDevice* device);
+
+ // Reference to the underlying BluetoothAdapter object, holding this reference
+ // ensures we stay around as the pairing delegate for that adapter.
+ scoped_refptr<device::BluetoothAdapter> adapter_;
+
+ // Set of currently paired devices, stored by Bluetooth address, used to
+ // filter out property changes for devices that were previously paired.
+ std::set<std::string> paired_devices_;
+
+ // Note: This should remain the last member so it'll be destroyed and
+ // invalidate its weak pointers before any other members are destroyed.
+ base::WeakPtrFactory<BluetoothNotificationController> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(BluetoothNotificationController);
+};
+
+} // namespace internal
+} // namespace ash
+
+#endif // ASH_SYSTEM_CHROMEOS_BLUETOOTH_BLUETOOTH_NOTIFICATION_CONTROLLER_H_
diff --git a/ash/system/system_notifier.cc b/ash/system/system_notifier.cc
index e0bc939..dadb12a 100644
--- a/ash/system/system_notifier.cc
+++ b/ash/system/system_notifier.cc
@@ -35,6 +35,7 @@ const char* kAshSystemNotifiers[] = {
kNotifierScreenShare,
kNotifierSessionLengthTimeout,
kNotifierPower,
+ kNotifierBluetooth,
NULL
};
@@ -52,6 +53,7 @@ bool MatchSystemNotifierId(const message_center::NotifierId& notifier_id,
} // namespace
+const char kNotifierBluetooth[] = "ash.bluetooth";
const char kNotifierDisplay[] = "ash.display";
const char kNotifierDisplayResolutionChange[] = "ash.display.resolution-change";
const char kNotifierDisplayError[] = "ash.display.error";
@@ -61,11 +63,11 @@ const char kNotifierMultiProfileFirstRun[] = "ash.multi-profile.first-run";
const char kNotifierNetwork[] = "ash.network";
const char kNotifierNetworkError[] = "ash.network.error";
const char kNotifierNetworkPortalDetector[] = "ash.network.portal-detector";
+const char kNotifierPower[] = "ash.power";
const char kNotifierScreenshot[] = "ash.screenshot";
const char kNotifierScreenCapture[] = "ash.screen-capture";
const char kNotifierScreenShare[] = "ash.screen-share";
const char kNotifierSessionLengthTimeout[] = "ash.session-length-timeout";
-const char kNotifierPower[] = "ash.power";
bool ShouldAlwaysShowPopups(const message_center::NotifierId& notifier_id) {
return MatchSystemNotifierId(notifier_id, kAlwaysShownNotifierIds);
diff --git a/ash/system/system_notifier.h b/ash/system/system_notifier.h
index 8aacb5a..0d4b6c7 100644
--- a/ash/system/system_notifier.h
+++ b/ash/system/system_notifier.h
@@ -14,6 +14,7 @@ namespace ash {
namespace system_notifier {
// The list of ash system notifier IDs. Alphabetical order.
+ASH_EXPORT extern const char kNotifierBluetooth[];
ASH_EXPORT extern const char kNotifierDisplay[];
ASH_EXPORT extern const char kNotifierDisplayResolutionChange[];
ASH_EXPORT extern const char kNotifierDisplayError[];
@@ -23,11 +24,11 @@ ASH_EXPORT extern const char kNotifierMultiProfileFirstRun[];
ASH_EXPORT extern const char kNotifierNetwork[];
ASH_EXPORT extern const char kNotifierNetworkError[];
ASH_EXPORT extern const char kNotifierNetworkPortalDetector[];
+ASH_EXPORT extern const char kNotifierPower[];
ASH_EXPORT extern const char kNotifierScreenshot[];
ASH_EXPORT extern const char kNotifierScreenCapture[];
ASH_EXPORT extern const char kNotifierScreenShare[];
ASH_EXPORT extern const char kNotifierSessionLengthTimeout[];
-ASH_EXPORT extern const char kNotifierPower[];
// Returns true if notifications from |notifier_id| should always appear as
// popups. "Always appear" means the popups should appear even in login screen,
diff --git a/chromeos/dbus/fake_bluetooth_adapter_client.cc b/chromeos/dbus/fake_bluetooth_adapter_client.cc
index a82e459..636e7ad 100644
--- a/chromeos/dbus/fake_bluetooth_adapter_client.cc
+++ b/chromeos/dbus/fake_bluetooth_adapter_client.cc
@@ -178,6 +178,11 @@ void FakeBluetoothAdapterClient::StopDiscovery(
DBusThreadManager::Get()->GetBluetoothDeviceClient());
device_client->EndDiscoverySimulation(dbus::ObjectPath(kAdapterPath));
+ if (simulation_interval_ms_ > 100) {
+ device_client->BeginIncomingPairingSimulation(
+ dbus::ObjectPath(kAdapterPath));
+ }
+
properties_->discovering.ReplaceValue(false);
}
}
diff --git a/chromeos/dbus/fake_bluetooth_device_client.cc b/chromeos/dbus/fake_bluetooth_device_client.cc
index f70e2cf..43903a31 100644
--- a/chromeos/dbus/fake_bluetooth_device_client.cc
+++ b/chromeos/dbus/fake_bluetooth_device_client.cc
@@ -62,6 +62,11 @@ void SimulatedProfileSocket(int fd) {
close(fd);
}
+void SimpleErrorCallback(const std::string& error_name,
+ const std::string& error_message) {
+ VLOG(1) << "Bluetooth Error: " << error_name << ": " << error_message;
+}
+
} // namespace
namespace chromeos {
@@ -199,6 +204,7 @@ void FakeBluetoothDeviceClient::Properties::Set(
FakeBluetoothDeviceClient::FakeBluetoothDeviceClient()
: simulation_interval_ms_(kSimulationIntervalMs),
discovery_simulation_step_(0),
+ incoming_pairing_simulation_step_(0),
pairing_cancelled_(false) {
Properties* properties = new Properties(base::Bind(
&FakeBluetoothDeviceClient::OnPropertyChanged,
@@ -440,6 +446,25 @@ void FakeBluetoothDeviceClient::EndDiscoverySimulation(
discovery_simulation_step_ = 0;
}
+void FakeBluetoothDeviceClient::BeginIncomingPairingSimulation(
+ const dbus::ObjectPath& adapter_path) {
+ VLOG(1) << "starting incoming pairing simulation";
+
+ incoming_pairing_simulation_step_ = 1;
+
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&FakeBluetoothDeviceClient::IncomingPairingSimulationTimer,
+ base::Unretained(this)),
+ base::TimeDelta::FromMilliseconds(30 * simulation_interval_ms_));
+}
+
+void FakeBluetoothDeviceClient::EndIncomingPairingSimulation(
+ const dbus::ObjectPath& adapter_path) {
+ VLOG(1) << "stopping incoming pairing simulation";
+ incoming_pairing_simulation_step_ = 0;
+}
+
void FakeBluetoothDeviceClient::SetSimulationIntervalMs(int interval_ms) {
simulation_interval_ms_ = interval_ms;
}
@@ -642,6 +667,66 @@ void FakeBluetoothDeviceClient::DiscoverySimulationTimer() {
base::TimeDelta::FromMilliseconds(simulation_interval_ms_));
}
+void FakeBluetoothDeviceClient::IncomingPairingSimulationTimer() {
+ if (!incoming_pairing_simulation_step_)
+ return;
+
+ VLOG(1) << "incoming pairing simulation, step "
+ << incoming_pairing_simulation_step_;
+ switch (incoming_pairing_simulation_step_) {
+ case 1:
+ CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
+ dbus::ObjectPath(kPhonePath));
+ SimulatePairing(dbus::ObjectPath(kPhonePath), true,
+ base::Bind(&base::DoNothing),
+ base::Bind(&SimpleErrorCallback));
+ break;
+ case 2:
+ CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
+ dbus::ObjectPath(kBoseSpeakersPath));
+ SimulatePairing(dbus::ObjectPath(kBoseSpeakersPath), true,
+ base::Bind(&base::DoNothing),
+ base::Bind(&SimpleErrorCallback));
+ break;
+ case 3:
+ CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
+ dbus::ObjectPath(kAppleKeyboardPath));
+ SimulatePairing(dbus::ObjectPath(kAppleKeyboardPath), true,
+ base::Bind(&base::DoNothing),
+ base::Bind(&SimpleErrorCallback));
+ break;
+ case 4:
+ CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
+ dbus::ObjectPath(kMotorolaKeyboardPath));
+ SimulatePairing(dbus::ObjectPath(kMotorolaKeyboardPath), true,
+ base::Bind(&base::DoNothing),
+ base::Bind(&SimpleErrorCallback));
+ break;
+ case 5:
+ CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
+ dbus::ObjectPath(kSonyHeadphonesPath));
+ SimulatePairing(dbus::ObjectPath(kSonyHeadphonesPath), true,
+ base::Bind(&base::DoNothing),
+ base::Bind(&SimpleErrorCallback));
+ break;
+ case 6:
+ CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
+ dbus::ObjectPath(kWeirdDevicePath));
+ SimulatePairing(dbus::ObjectPath(kWeirdDevicePath), true,
+ base::Bind(&base::DoNothing),
+ base::Bind(&SimpleErrorCallback));
+ break;
+ default:
+ return;
+ }
+
+ ++incoming_pairing_simulation_step_;
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&FakeBluetoothDeviceClient::IncomingPairingSimulationTimer,
+ base::Unretained(this)),
+ base::TimeDelta::FromMilliseconds(45 * simulation_interval_ms_));
+}
void FakeBluetoothDeviceClient::SimulatePairing(
const dbus::ObjectPath& object_path,
diff --git a/chromeos/dbus/fake_bluetooth_device_client.h b/chromeos/dbus/fake_bluetooth_device_client.h
index b228a11..e3eed05 100644
--- a/chromeos/dbus/fake_bluetooth_device_client.h
+++ b/chromeos/dbus/fake_bluetooth_device_client.h
@@ -76,6 +76,10 @@ class CHROMEOS_EXPORT FakeBluetoothDeviceClient
void BeginDiscoverySimulation(const dbus::ObjectPath& adapter_path);
void EndDiscoverySimulation(const dbus::ObjectPath& adapter_path);
+ // Simulates incoming pairing of devices for the given adapter.
+ void BeginIncomingPairingSimulation(const dbus::ObjectPath& adapter_path);
+ void EndIncomingPairingSimulation(const dbus::ObjectPath& adapter_path);
+
// Creates a device from the set we return for the given adapter.
void CreateDevice(const dbus::ObjectPath& adapter_path,
const dbus::ObjectPath& device_path);
@@ -161,6 +165,7 @@ class CHROMEOS_EXPORT FakeBluetoothDeviceClient
const std::string& property_name);
void DiscoverySimulationTimer();
+ void IncomingPairingSimulationTimer();
void CompleteSimulatedPairing(
const dbus::ObjectPath& object_path,
@@ -226,6 +231,7 @@ class CHROMEOS_EXPORT FakeBluetoothDeviceClient
int simulation_interval_ms_;
uint32_t discovery_simulation_step_;
+ uint32_t incoming_pairing_simulation_step_;
bool pairing_cancelled_;
};
diff --git a/device/bluetooth/bluetooth_device_chromeos.cc b/device/bluetooth/bluetooth_device_chromeos.cc
index b76c512..d45ea7b 100644
--- a/device/bluetooth/bluetooth_device_chromeos.cc
+++ b/device/bluetooth/bluetooth_device_chromeos.cc
@@ -395,7 +395,6 @@ void BluetoothDeviceChromeOS::ClearOutOfBandPairingData(
BluetoothPairingChromeOS* BluetoothDeviceChromeOS::BeginPairing(
BluetoothDevice::PairingDelegate* pairing_delegate) {
- DCHECK(!pairing_);
pairing_.reset(new BluetoothPairingChromeOS(this, pairing_delegate));
return pairing_.get();
}
diff --git a/device/bluetooth/bluetooth_pairing_chromeos.cc b/device/bluetooth/bluetooth_pairing_chromeos.cc
index b81c342..dc73f6d 100644
--- a/device/bluetooth/bluetooth_pairing_chromeos.cc
+++ b/device/bluetooth/bluetooth_pairing_chromeos.cc
@@ -26,6 +26,10 @@ enum UMAPairingMethod {
UMA_PAIRING_METHOD_COUNT
};
+// Number of keys that will be entered for a passkey, six digits plus the
+// final enter.
+const uint16 kPasskeyMaxKeysEntered = 7;
+
} // namespace
namespace chromeos {
@@ -74,10 +78,10 @@ void BluetoothPairingChromeOS::RequestPinCode(
UMA_PAIRING_METHOD_REQUEST_PINCODE,
UMA_PAIRING_METHOD_COUNT);
- DCHECK(pincode_callback_.is_null());
+ ResetCallbacks();
pincode_callback_ = callback;
- pairing_delegate_->RequestPinCode(device_);
pairing_delegate_used_ = true;
+ pairing_delegate_->RequestPinCode(device_);
}
bool BluetoothPairingChromeOS::ExpectingPinCode() const {
@@ -104,8 +108,9 @@ void BluetoothPairingChromeOS::DisplayPinCode(const std::string& pincode) {
UMA_PAIRING_METHOD_DISPLAY_PINCODE,
UMA_PAIRING_METHOD_COUNT);
- pairing_delegate_->DisplayPinCode(device_, pincode);
+ ResetCallbacks();
pairing_delegate_used_ = true;
+ pairing_delegate_->DisplayPinCode(device_, pincode);
// If this is not an outgoing connection to the device, the pairing context
// needs to be cleaned up again as there's no reliable indication of
@@ -120,10 +125,10 @@ void BluetoothPairingChromeOS::RequestPasskey(
UMA_PAIRING_METHOD_REQUEST_PASSKEY,
UMA_PAIRING_METHOD_COUNT);
- DCHECK(passkey_callback_.is_null());
+ ResetCallbacks();
passkey_callback_ = callback;
- pairing_delegate_->RequestPasskey(device_);
pairing_delegate_used_ = true;
+ pairing_delegate_->RequestPasskey(device_);
}
bool BluetoothPairingChromeOS::ExpectingPasskey() const {
@@ -150,22 +155,23 @@ void BluetoothPairingChromeOS::DisplayPasskey(uint32 passkey) {
UMA_PAIRING_METHOD_DISPLAY_PASSKEY,
UMA_PAIRING_METHOD_COUNT);
-
+ ResetCallbacks();
+ pairing_delegate_used_ = true;
pairing_delegate_->DisplayPasskey(device_, passkey);
+
+}
+
+void BluetoothPairingChromeOS::KeysEntered(uint16 entered) {
pairing_delegate_used_ = true;
+ pairing_delegate_->KeysEntered(device_, entered);
// If this is not an outgoing connection to the device, the pairing context
// needs to be cleaned up again as there's no reliable indication of
// completion of incoming pairing.
- if (!device_->IsConnecting())
+ if (entered >= kPasskeyMaxKeysEntered && !device_->IsConnecting())
device_->EndPairing();
}
-void BluetoothPairingChromeOS::KeysEntered(uint16 entered) {
- pairing_delegate_->KeysEntered(device_, entered);
- pairing_delegate_used_ = true;
-}
-
void BluetoothPairingChromeOS::RequestConfirmation(
uint32 passkey,
const BluetoothAgentServiceProvider::Delegate::ConfirmationCallback&
@@ -174,10 +180,10 @@ void BluetoothPairingChromeOS::RequestConfirmation(
UMA_PAIRING_METHOD_CONFIRM_PASSKEY,
UMA_PAIRING_METHOD_COUNT);
- DCHECK(confirmation_callback_.is_null());
+ ResetCallbacks();
confirmation_callback_ = callback;
- pairing_delegate_->ConfirmPasskey(device_, passkey);
pairing_delegate_used_ = true;
+ pairing_delegate_->ConfirmPasskey(device_, passkey);
}
void BluetoothPairingChromeOS::RequestAuthorization(
@@ -187,10 +193,10 @@ void BluetoothPairingChromeOS::RequestAuthorization(
UMA_PAIRING_METHOD_NONE,
UMA_PAIRING_METHOD_COUNT);
- DCHECK(confirmation_callback_.is_null());
+ ResetCallbacks();
confirmation_callback_ = callback;
- pairing_delegate_->AuthorizePairing(device_);
pairing_delegate_used_ = true;
+ pairing_delegate_->AuthorizePairing(device_);
}
bool BluetoothPairingChromeOS::ExpectingConfirmation() const {
@@ -226,6 +232,12 @@ BluetoothPairingChromeOS::GetPairingDelegate() const {
return pairing_delegate_;
}
+void BluetoothPairingChromeOS::ResetCallbacks() {
+ pincode_callback_.Reset();
+ passkey_callback_.Reset();
+ confirmation_callback_.Reset();
+}
+
bool BluetoothPairingChromeOS::RunPairingCallbacks(
BluetoothAgentServiceProvider::Delegate::Status status) {
pairing_delegate_used_ = true;
diff --git a/device/bluetooth/bluetooth_pairing_chromeos.h b/device/bluetooth/bluetooth_pairing_chromeos.h
index 85c45c6..ae906bc 100644
--- a/device/bluetooth/bluetooth_pairing_chromeos.h
+++ b/device/bluetooth/bluetooth_pairing_chromeos.h
@@ -108,6 +108,10 @@ class BluetoothPairingChromeOS {
device::BluetoothDevice::PairingDelegate* GetPairingDelegate() const;
private:
+ // Internal method to reset the current set of callbacks because a new
+ // request has arrived that supercedes them.
+ void ResetCallbacks();
+
// Internal method to respond to the relevant callback for a RejectPairing
// or CancelPairing call.
bool RunPairingCallbacks(