diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2017-07-17 13:57:45 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2017-07-19 13:44:40 +0000 |
commit | 6ec7b8da05d21a3878bd21c691b41e675d74bb1c (patch) | |
tree | b87f250bc19413750b9bb9cdbf2da20ef5014820 /chromium/device | |
parent | ec02ee4181c49b61fce1c8fb99292dbb8139cc90 (diff) | |
download | qtwebengine-chromium-6ec7b8da05d21a3878bd21c691b41e675d74bb1c.tar.gz |
BASELINE: Update Chromium to 60.0.3112.70
Change-Id: I9911c2280a014d4632f254857876a395d4baed2d
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'chromium/device')
382 files changed, 7124 insertions, 8785 deletions
diff --git a/chromium/device/BUILD.gn b/chromium/device/BUILD.gn index eba54e219c1..458c5ebb771 100644 --- a/chromium/device/BUILD.gn +++ b/chromium/device/BUILD.gn @@ -2,11 +2,12 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("vr/features.gni") +import("vr/features/features.gni") import("//build/config/features.gni") import("//testing/test.gni") if (is_android) { + import("//build/config/android/config.gni") import("//build/config/android/rules.gni") # For generate_jni(). } @@ -19,8 +20,6 @@ is_linux_without_udev = is_linux && !use_udev test("device_unittests") { sources = [ "base/synchronization/one_writer_seqlock_unittest.cc", - "battery/battery_status_manager_win_unittest.cc", - "battery/battery_status_service_unittest.cc", "bluetooth/bluetooth_adapter_mac_unittest.mm", "bluetooth/bluetooth_adapter_unittest.cc", "bluetooth/bluetooth_adapter_win_unittest.cc", @@ -74,22 +73,19 @@ test("device_unittests") { "sensors/sensor_manager_android_unittest.cc", "sensors/sensor_manager_chromeos_unittest.cc", "test/run_all_unittests.cc", - "u2f/u2f_apdu_unittest.cc", - "u2f/u2f_message_unittest.cc", ] deps = [ "//base/test:test_support", "//base/third_party/dynamic_annotations:dynamic_annotations", "//device/base/synchronization", - "//device/battery", - "//device/battery:mojo_bindings", "//device/bluetooth", "//device/bluetooth:mocks", "//device/bluetooth:mojo", "//device/bluetooth/uribeacon", "//device/gamepad", "//device/gamepad:test_helpers", + "//device/gamepad/public/cpp:shared_with_blink", "//device/gamepad/public/interfaces", "//device/gamepad/public/interfaces:gamepad_struct_traits_test", "//device/generic_sensor", @@ -106,17 +102,11 @@ test("device_unittests") { "//net", "//testing/gmock", "//testing/gtest", - "//third_party/WebKit/public:blink", "//third_party/WebKit/public:blink_headers", "//tools/usb_gadget", "//url", ] - if (is_linux && !is_chromeos && use_dbus) { - sources += [ "battery/battery_status_manager_linux_unittest.cc" ] - deps += [ "//dbus:test_support" ] - } - if (!is_linux_without_udev) { sources += [ "generic_sensor/platform_sensor_and_provider_unittest_linux.cc" ] @@ -130,17 +120,25 @@ test("device_unittests") { "hid/hid_connection_unittest.cc", "hid/hid_device_filter_unittest.cc", "hid/hid_report_descriptor_unittest.cc", + "hid/hid_service_unittest.cc", "hid/input_service_linux_unittest.cc", "hid/test_report_descriptors.cc", "hid/test_report_descriptors.h", "serial/serial_io_handler_posix_unittest.cc", + "u2f/u2f_apdu_unittest.cc", "u2f/u2f_hid_device_unittest.cc", + "u2f/u2f_message_unittest.cc", + "u2f/u2f_register_unittest.cc", + "u2f/u2f_request_unittest.cc", + "u2f/u2f_sign_unittest.cc", ] deps += [ "//device/hid", "//device/hid:mocks", "//device/serial", "//device/serial:test_support", + "//device/u2f", + "//device/u2f:mocks", ] } @@ -170,7 +168,6 @@ test("device_unittests") { deps += [ "//device/base", "//device/base:mocks", - "//device/u2f", "//device/usb", "//device/usb:test_support", "//device/usb/mojo", @@ -186,7 +183,6 @@ test("device_unittests") { } if (is_android) { - sources -= [ "battery/battery_status_service_unittest.cc" ] deps += [ ":bluetooth_test_java", ":bluetooth_test_jni_headers", @@ -195,7 +191,6 @@ test("device_unittests") { "//device/sensors:java", "//device/usb:java", ] - deps -= [ "//device/battery" ] } if (is_chromeos) { @@ -298,17 +293,17 @@ if (is_android) { junit_binary("device_junit_tests") { java_files = [ "gamepad/android/junit/src/org/chromium/device/gamepad/GamepadMappingsTest.java", - "generic_sensor/android/junit/src/org/chromium/device/sensors/PlatformSensorAndProviderTest.java", - "nfc/android/junit/src/org/chromium/device/nfc/NFCTest.java", + "geolocation/android/junit/src/org/chromium/device/geolocation/LocationProviderTest.java", ] deps = [ + "$google_play_services_package:google_play_services_base_java", + "$google_play_services_package:google_play_services_basement_java", + "$google_play_services_package:google_play_services_location_java", "//base:base_java", "//base:base_java_test_support", "//device/gamepad:java", - "//device/generic_sensor:java", - "//device/generic_sensor/public/interfaces:interfaces_java", - "//device/nfc:mojo_bindings_java", - "//device/nfc/android:java", + "//device/geolocation:geolocation_java", + "//device/geolocation:geolocation_java_test_support", "//mojo/public/java:bindings_java", "//third_party/android_tools:android_support_annotations_java", ] diff --git a/chromium/device/battery/BUILD.gn b/chromium/device/battery/BUILD.gn deleted file mode 100644 index 2647882a894..00000000000 --- a/chromium/device/battery/BUILD.gn +++ /dev/null @@ -1,80 +0,0 @@ -# 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. - -import("//build/config/features.gni") -import("//mojo/public/tools/bindings/mojom.gni") - -# On android, BatteryManager mojo service is implemented directly in Java. -if (!is_android) { - component("battery") { - output_name = "device_battery" - - sources = [ - "battery_export.h", - "battery_monitor_impl.cc", - "battery_monitor_impl.h", - "battery_status_manager.h", - "battery_status_manager_chromeos.cc", - "battery_status_manager_default.cc", - "battery_status_manager_linux-inl.h", - "battery_status_manager_linux.cc", - "battery_status_manager_linux.h", - "battery_status_manager_mac.cc", - "battery_status_manager_win.cc", - "battery_status_manager_win.h", - "battery_status_service.cc", - "battery_status_service.h", - ] - - defines = [ "DEVICE_BATTERY_IMPLEMENTATION" ] - - deps = [ - ":mojo_bindings", - "//base", - "//base/third_party/dynamic_annotations", - "//mojo/public/cpp/bindings", - ] - - if (is_chromeos) { - configs += [ "//build/config/linux/dbus" ] - deps += [ - "//chromeos:chromeos", - "//chromeos:power_manager_proto", - ] - sources -= [ - "battery_status_manager_default.cc", - "battery_status_manager_linux.cc", - ] - } - - if (is_linux && !is_chromeos) { - if (use_dbus) { - configs += [ "//build/config/linux/dbus" ] - deps += [ "//dbus" ] - sources -= [ "battery_status_manager_default.cc" ] - } else { - sources -= [ "battery_status_manager_linux.cc" ] - } - } - - if (is_mac) { - sources -= [ "battery_status_manager_default.cc" ] - libs = [ - "CoreFoundation.framework", - "IOKit.framework", - ] - } - - if (is_win) { - sources -= [ "battery_status_manager_default.cc" ] - } - } -} - -mojom("mojo_bindings") { - sources = [ - "battery_monitor.mojom", - "battery_status.mojom", - ] -} diff --git a/chromium/device/battery/DEPS b/chromium/device/battery/DEPS deleted file mode 100644 index d6abddad069..00000000000 --- a/chromium/device/battery/DEPS +++ /dev/null @@ -1,3 +0,0 @@ -include_rules = [ - "+dbus", -] diff --git a/chromium/device/battery/OWNERS b/chromium/device/battery/OWNERS deleted file mode 100644 index fddb71dacaf..00000000000 --- a/chromium/device/battery/OWNERS +++ /dev/null @@ -1,4 +0,0 @@ -timvolodine@chromium.org - -per-file *.mojom=set noparent -per-file *.mojom=file://ipc/SECURITY_OWNERS diff --git a/chromium/device/battery/android/BUILD.gn b/chromium/device/battery/android/BUILD.gn deleted file mode 100644 index fa22d0677c0..00000000000 --- a/chromium/device/battery/android/BUILD.gn +++ /dev/null @@ -1,23 +0,0 @@ -# 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. - -import("//build/config/android/config.gni") -import("//build/config/android/rules.gni") - -android_library("battery_monitor_java") { - java_files = [ - "java/src/org/chromium/device/battery/BatteryStatusManager.java", - "java/src/org/chromium/device/battery/BatteryMonitorImpl.java", - "java/src/org/chromium/device/battery/BatteryMonitorFactory.java", - ] - - deps = [ - "//base:base_java", - "//device/battery:mojo_bindings_java", - "//mojo/public/java:bindings_java", - "//mojo/public/java:system_java", - "//services/service_manager/public/java:service_manager_java", - "//third_party/jsr-305:jsr_305_javalib", - ] -} diff --git a/chromium/device/battery/battery_export.h b/chromium/device/battery/battery_export.h deleted file mode 100644 index 639c25a2bb1..00000000000 --- a/chromium/device/battery/battery_export.h +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) 2012 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 DEVICE_BATTERY_DEVICE_BATTERY_EXPORT_H_ -#define DEVICE_BATTERY_DEVICE_BATTERY_EXPORT_H_ - -#if defined(COMPONENT_BUILD) -#if defined(WIN32) - -#if defined(DEVICE_BATTERY_IMPLEMENTATION) -#define DEVICE_BATTERY_EXPORT __declspec(dllexport) -#else -#define DEVICE_BATTERY_EXPORT __declspec(dllimport) -#endif // defined(DEVICE_BATTERY_IMPLEMENTATION) - -#else // defined(WIN32) -#if defined(DEVICE_BATTERY_IMPLEMENTATION) -#define DEVICE_BATTERY_EXPORT __attribute__((visibility("default"))) -#else -#define DEVICE_BATTERY_EXPORT -#endif -#endif - -#else // defined(COMPONENT_BUILD) -#define DEVICE_BATTERY_EXPORT -#endif - -#endif // DEVICE_BATTERY_DEVICE_BATTERY_EXPORT_H_ diff --git a/chromium/device/battery/battery_monitor.mojom b/chromium/device/battery/battery_monitor.mojom deleted file mode 100644 index c5c16009087..00000000000 --- a/chromium/device/battery/battery_monitor.mojom +++ /dev/null @@ -1,15 +0,0 @@ -// 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. - -module device.mojom; - -import "device/battery/battery_status.mojom"; - -interface BatteryMonitor { - // Battery status is reported once it changes or immediately if this is the - // first call to QueryNextStatus on this instance. QueryNextStatus calls may - // be throttled by the service. Overlapping calls to QueryNextStatus are - // prohibited and will be treated as a connection error. - QueryNextStatus() => (BatteryStatus status); -}; diff --git a/chromium/device/battery/battery_monitor_impl.cc b/chromium/device/battery/battery_monitor_impl.cc deleted file mode 100644 index 9309175d663..00000000000 --- a/chromium/device/battery/battery_monitor_impl.cc +++ /dev/null @@ -1,65 +0,0 @@ -// 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 "device/battery/battery_monitor_impl.h" - -#include <utility> - -#include "base/bind.h" -#include "base/logging.h" -#include "base/memory/ptr_util.h" -#include "mojo/public/cpp/bindings/strong_binding.h" - -namespace device { - -// static -void BatteryMonitorImpl::Create(mojom::BatteryMonitorRequest request) { - auto* impl = new BatteryMonitorImpl; - auto binding = - mojo::MakeStrongBinding(base::WrapUnique(impl), std::move(request)); - impl->binding_ = binding; -} - -BatteryMonitorImpl::BatteryMonitorImpl() : status_to_report_(false) { - // NOTE: DidChange may be called before AddCallback returns. This is done to - // report current status. - subscription_ = BatteryStatusService::GetInstance()->AddCallback( - base::Bind(&BatteryMonitorImpl::DidChange, base::Unretained(this))); -} - -BatteryMonitorImpl::~BatteryMonitorImpl() { -} - -void BatteryMonitorImpl::QueryNextStatus( - const QueryNextStatusCallback& callback) { - if (!callback_.is_null()) { - DVLOG(1) << "Overlapped call to QueryNextStatus!"; - binding_->Close(); - return; - } - callback_ = callback; - - if (status_to_report_) - ReportStatus(); -} - -void BatteryMonitorImpl::RegisterSubscription() { -} - -void BatteryMonitorImpl::DidChange(const mojom::BatteryStatus& battery_status) { - status_ = battery_status; - status_to_report_ = true; - - if (!callback_.is_null()) - ReportStatus(); -} - -void BatteryMonitorImpl::ReportStatus() { - callback_.Run(status_.Clone()); - callback_.Reset(); - - status_to_report_ = false; -} - -} // namespace device diff --git a/chromium/device/battery/battery_monitor_impl.h b/chromium/device/battery/battery_monitor_impl.h deleted file mode 100644 index 67be418d685..00000000000 --- a/chromium/device/battery/battery_monitor_impl.h +++ /dev/null @@ -1,46 +0,0 @@ -// 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 DEVICE_BATTERY_BATTERY_MONITOR_IMPL_H_ -#define DEVICE_BATTERY_BATTERY_MONITOR_IMPL_H_ - -#include <memory> - -#include "base/macros.h" -#include "device/battery/battery_export.h" -#include "device/battery/battery_monitor.mojom.h" -#include "device/battery/battery_status_service.h" -#include "mojo/public/cpp/bindings/strong_binding.h" - -namespace device { - -class BatteryMonitorImpl : public mojom::BatteryMonitor { - public: - DEVICE_BATTERY_EXPORT static void Create( - mojom::BatteryMonitorRequest request); - - BatteryMonitorImpl(); - ~BatteryMonitorImpl() override; - - private: - // mojom::BatteryMonitor methods: - void QueryNextStatus(const QueryNextStatusCallback& callback) override; - - void RegisterSubscription(); - void DidChange(const mojom::BatteryStatus& battery_status); - void ReportStatus(); - - mojo::StrongBindingPtr<mojom::BatteryMonitor> binding_; - std::unique_ptr<BatteryStatusService::BatteryUpdateSubscription> - subscription_; - QueryNextStatusCallback callback_; - mojom::BatteryStatus status_; - bool status_to_report_; - - DISALLOW_COPY_AND_ASSIGN(BatteryMonitorImpl); -}; - -} // namespace device - -#endif // DEVICE_BATTERY_BATTERY_MONITOR_IMPL_H_ diff --git a/chromium/device/battery/battery_status.mojom b/chromium/device/battery/battery_status.mojom deleted file mode 100644 index 83c0026cc44..00000000000 --- a/chromium/device/battery/battery_status.mojom +++ /dev/null @@ -1,12 +0,0 @@ -// 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. - -module device.mojom; - -struct BatteryStatus { - bool charging = true; - double charging_time = 0.0; - double discharging_time = double.INFINITY; - double level = 1.0; -}; diff --git a/chromium/device/battery/battery_status_manager.h b/chromium/device/battery/battery_status_manager.h deleted file mode 100644 index b80579bc6a3..00000000000 --- a/chromium/device/battery/battery_status_manager.h +++ /dev/null @@ -1,36 +0,0 @@ -// 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 DEVICE_BATTERY_BATTERY_STATUS_MANAGER_H_ -#define DEVICE_BATTERY_BATTERY_STATUS_MANAGER_H_ - -#include <memory> - -#include "device/battery/battery_status_service.h" - -namespace device { - -// Platform specific manager class for fetching battery status data. -class BatteryStatusManager { - public: - // Creates a BatteryStatusManager object. |callback| should be called when the - // battery status changes. - static std::unique_ptr<BatteryStatusManager> Create( - const BatteryStatusService::BatteryUpdateCallback& callback); - - virtual ~BatteryStatusManager() {} - - // Start listening for battery status changes. New updates are signalled - // by invoking the callback provided at construction time. - // Note that this is called in the IO thread. - virtual bool StartListeningBatteryChange() = 0; - - // Stop listening for battery status changes. - // Note that this is called in the IO thread. - virtual void StopListeningBatteryChange() = 0; -}; - -} // namespace device - -#endif // DEVICE_BATTERY_BATTERY_STATUS_MANAGER_H_ diff --git a/chromium/device/battery/battery_status_manager_chromeos.cc b/chromium/device/battery/battery_status_manager_chromeos.cc deleted file mode 100644 index d5daa28b97a..00000000000 --- a/chromium/device/battery/battery_status_manager_chromeos.cc +++ /dev/null @@ -1,157 +0,0 @@ -// 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 "device/battery/battery_status_manager.h" - -#include <memory> - -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/power_manager/power_supply_properties.pb.h" -#include "chromeos/dbus/power_manager_client.h" - -namespace device { - -namespace { - -class PowerManagerObserver - : public chromeos::PowerManagerClient::Observer, - public base::RefCountedThreadSafe<PowerManagerObserver> { - public: - explicit PowerManagerObserver( - const BatteryStatusService::BatteryUpdateCallback& callback) - : callback_(callback), currently_listening_(false) {} - - // Starts listening for updates. - void Start() { - if (currently_listening_) - return; - chromeos::PowerManagerClient* power_client = - chromeos::DBusThreadManager::Get()->GetPowerManagerClient(); - power_client->AddObserver(this); - power_client->RequestStatusUpdate(); - currently_listening_ = true; - } - - // Stops listening for updates. - void Stop() { - if (!currently_listening_) - return; - chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->RemoveObserver( - this); - currently_listening_ = false; - } - - private: - friend class base::RefCountedThreadSafe<PowerManagerObserver>; - - ~PowerManagerObserver() override {} - - bool IsBatteryPresent( - const power_manager::PowerSupplyProperties& proto) const { - return proto.battery_state() != - power_manager::PowerSupplyProperties_BatteryState_NOT_PRESENT; - } - - bool IsUsbChargerConnected( - const power_manager::PowerSupplyProperties& proto) const { - return proto.external_power() == - power_manager::PowerSupplyProperties_ExternalPower_USB; - } - - bool IsBatteryCharging( - const power_manager::PowerSupplyProperties& proto) const { - return proto.battery_state() != - power_manager::PowerSupplyProperties_BatteryState_DISCHARGING; - } - - bool IsBatteryFull(const power_manager::PowerSupplyProperties& proto) const { - return proto.battery_state() == - power_manager::PowerSupplyProperties_BatteryState_FULL; - } - - double GetBatteryLevel( - const power_manager::PowerSupplyProperties& proto) const { - const double kMaxBatteryLevelProto = 100.f; - return proto.battery_percent() / kMaxBatteryLevelProto; - } - - // chromeos::PowerManagerClient::Observer: - void PowerChanged( - const power_manager::PowerSupplyProperties& proto) override { - mojom::BatteryStatus status; - - // Use the default values if there is no battery in the system. - if (IsBatteryPresent(proto)) { - // The charging status is unreliable if a low power charger is connected - // (i.e. usb). - bool status_unreliable = IsUsbChargerConnected(proto); - // Battery time is unreliable if it is still being computed. - bool time_unreliable = - status_unreliable || proto.is_calculating_battery_time(); - - // Set |charging| only if the status is reliable. Otherwise, keep the - // default (which is |true|). - if (!status_unreliable) - status.charging = IsBatteryCharging(proto); - - // Set |chargingTime| to +infinity if the battery is discharging, or if - // the time is unreliable. Keep the default value (which is 0) if the - // battery is full. - if (time_unreliable || !status.charging) - status.charging_time = std::numeric_limits<double>::infinity(); - else if (!IsBatteryFull(proto)) - status.charging_time = proto.battery_time_to_full_sec(); - - // Keep the default value for |dischargingTime| (which is +infinity) if - // the time is unreliable, or if the battery is charging. - if (!time_unreliable && !status.charging) - status.discharging_time = proto.battery_time_to_empty_sec(); - - status.level = GetBatteryLevel(proto); - } - callback_.Run(status); - } - - BatteryStatusService::BatteryUpdateCallback callback_; - bool currently_listening_; - - DISALLOW_COPY_AND_ASSIGN(PowerManagerObserver); -}; - -class BatteryStatusManagerChromeOS - : public BatteryStatusManager, - public chromeos::PowerManagerClient::Observer { - public: - explicit BatteryStatusManagerChromeOS( - const BatteryStatusService::BatteryUpdateCallback& callback) - : observer_(new PowerManagerObserver(callback)) {} - - ~BatteryStatusManagerChromeOS() override { observer_->Stop(); } - - private: - // BatteryStatusManager: - bool StartListeningBatteryChange() override { - observer_->Start(); - return true; - } - - void StopListeningBatteryChange() override { observer_->Stop(); } - - scoped_refptr<PowerManagerObserver> observer_; - - DISALLOW_COPY_AND_ASSIGN(BatteryStatusManagerChromeOS); -}; - -} // namespace - -// static -std::unique_ptr<BatteryStatusManager> BatteryStatusManager::Create( - const BatteryStatusService::BatteryUpdateCallback& callback) { - return std::unique_ptr<BatteryStatusManager>( - new BatteryStatusManagerChromeOS(callback)); -} - -} // namespace device diff --git a/chromium/device/battery/battery_status_manager_default.cc b/chromium/device/battery/battery_status_manager_default.cc deleted file mode 100644 index c0a513df505..00000000000 --- a/chromium/device/battery/battery_status_manager_default.cc +++ /dev/null @@ -1,43 +0,0 @@ -// 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 "device/battery/battery_status_manager.h" - -#include <memory> - -#include "base/logging.h" -#include "base/macros.h" - -namespace device { - -namespace { - -class BatteryStatusManagerDefault : public BatteryStatusManager { - public: - explicit BatteryStatusManagerDefault( - const BatteryStatusService::BatteryUpdateCallback& callback) {} - ~BatteryStatusManagerDefault() override {} - - private: - // BatteryStatusManager: - bool StartListeningBatteryChange() override { - NOTIMPLEMENTED(); - return false; - } - - void StopListeningBatteryChange() override { NOTIMPLEMENTED(); } - - DISALLOW_COPY_AND_ASSIGN(BatteryStatusManagerDefault); -}; - -} // namespace - -// static -std::unique_ptr<BatteryStatusManager> BatteryStatusManager::Create( - const BatteryStatusService::BatteryUpdateCallback& callback) { - return std::unique_ptr<BatteryStatusManager>( - new BatteryStatusManagerDefault(callback)); -} - -} // namespace device diff --git a/chromium/device/battery/battery_status_manager_linux-inl.h b/chromium/device/battery/battery_status_manager_linux-inl.h deleted file mode 100644 index d045dba3445..00000000000 --- a/chromium/device/battery/battery_status_manager_linux-inl.h +++ /dev/null @@ -1,28 +0,0 @@ -// 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 DEVICE_BATTERY_BATTERY_STATUS_MANAGER_LINUX_INL_H_ -#define DEVICE_BATTERY_BATTERY_STATUS_MANAGER_LINUX_INL_H_ - -namespace device { -const char kUPowerInterfaceName[] = "org.freedesktop.UPower"; -const char kUPowerServiceName[] = "org.freedesktop.UPower"; -const char kUPowerMethodEnumerateDevices[] = "EnumerateDevices"; -const char kUPowerMethodGetDisplayDevice[] = "GetDisplayDevice"; -const char kUPowerPath[] = "/org/freedesktop/UPower"; -const char kUPowerPropertyDaemonVersion[] = "DaemonVersion"; -const char kUPowerSignalDeviceAdded[] = "DeviceAdded"; -const char kUPowerSignalDeviceRemoved[] = "DeviceRemoved"; - -const char kUPowerDeviceInterfaceName[] = "org.freedesktop.UPower.Device"; -const char kUPowerDevicePropertyIsPresent[] = "IsPresent"; -const char kUPowerDevicePropertyPercentage[] = "Percentage"; -const char kUPowerDevicePropertyState[] = "State"; -const char kUPowerDevicePropertyTimeToEmpty[] = "TimeToEmpty"; -const char kUPowerDevicePropertyTimeToFull[] = "TimeToFull"; -const char kUPowerDevicePropertyType[] = "Type"; -const char kUPowerDeviceSignalChanged[] = "Changed"; -} // namespace device - -#endif // DEVICE_BATTERY_BATTERY_STATUS_MANAGER_LINUX_INL_H_ diff --git a/chromium/device/battery/battery_status_manager_linux.cc b/chromium/device/battery/battery_status_manager_linux.cc deleted file mode 100644 index 0fd085949b6..00000000000 --- a/chromium/device/battery/battery_status_manager_linux.cc +++ /dev/null @@ -1,622 +0,0 @@ -// 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 "device/battery/battery_status_manager_linux.h" - -#include <stddef.h> -#include <stdint.h> - -#include <limits> -#include <memory> -#include <string> -#include <utility> -#include <vector> - -#include "base/macros.h" -#include "base/metrics/histogram_macros.h" -#include "base/single_thread_task_runner.h" -#include "base/threading/thread.h" -#include "base/values.h" -#include "base/version.h" -#include "dbus/bus.h" -#include "dbus/message.h" -#include "dbus/object_path.h" -#include "dbus/object_proxy.h" -#include "dbus/property.h" -#include "dbus/values_util.h" -#include "device/battery/battery_status_manager_linux-inl.h" - -namespace device { -namespace { -const char kBatteryNotifierThreadName[] = "BatteryStatusNotifier"; - -class UPowerProperties : public dbus::PropertySet { - public: - UPowerProperties(dbus::ObjectProxy* object_proxy, - const PropertyChangedCallback callback); - ~UPowerProperties() override; - - base::Version daemon_version(); - - private: - dbus::Property<std::string> daemon_version_; - - DISALLOW_COPY_AND_ASSIGN(UPowerProperties); -}; - -UPowerProperties::UPowerProperties(dbus::ObjectProxy* object_proxy, - const PropertyChangedCallback callback) - : dbus::PropertySet(object_proxy, kUPowerInterfaceName, callback) { - RegisterProperty(kUPowerPropertyDaemonVersion, &daemon_version_); -} - -UPowerProperties::~UPowerProperties() {} - -base::Version UPowerProperties::daemon_version() { - return (daemon_version_.is_valid() || daemon_version_.GetAndBlock()) - ? base::Version(daemon_version_.value()) - : base::Version(); -} - -class UPowerObject { - public: - using PropertyChangedCallback = dbus::PropertySet::PropertyChangedCallback; - - UPowerObject(dbus::Bus* dbus, - const PropertyChangedCallback property_changed_callback); - ~UPowerObject(); - - std::vector<dbus::ObjectPath> EnumerateDevices(); - dbus::ObjectPath GetDisplayDevice(); - - dbus::ObjectProxy* proxy() { return proxy_; } - UPowerProperties* properties() { return properties_.get(); } - - private: - dbus::Bus* dbus_; // Owned by the BatteryStatusNotificationThread. - dbus::ObjectProxy* proxy_; // Owned by the dbus. - std::unique_ptr<UPowerProperties> properties_; - - DISALLOW_COPY_AND_ASSIGN(UPowerObject); -}; - -UPowerObject::UPowerObject( - dbus::Bus* dbus, - const PropertyChangedCallback property_changed_callback) - : dbus_(dbus), - proxy_(dbus_->GetObjectProxy(kUPowerServiceName, - dbus::ObjectPath(kUPowerPath))), - properties_(new UPowerProperties(proxy_, property_changed_callback)) {} - -UPowerObject::~UPowerObject() { - properties_.reset(); // before the proxy is deleted. - dbus_->RemoveObjectProxy(kUPowerServiceName, proxy_->object_path(), - base::Bind(&base::DoNothing)); -} - -std::vector<dbus::ObjectPath> UPowerObject::EnumerateDevices() { - std::vector<dbus::ObjectPath> paths; - dbus::MethodCall method_call(kUPowerServiceName, - kUPowerMethodEnumerateDevices); - std::unique_ptr<dbus::Response> response(proxy_->CallMethodAndBlock( - &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); - - if (response) { - dbus::MessageReader reader(response.get()); - reader.PopArrayOfObjectPaths(&paths); - } - return paths; -} - -dbus::ObjectPath UPowerObject::GetDisplayDevice() { - dbus::ObjectPath display_device_path; - if (!proxy_) - return display_device_path; - - dbus::MethodCall method_call(kUPowerServiceName, - kUPowerMethodGetDisplayDevice); - std::unique_ptr<dbus::Response> response(proxy_->CallMethodAndBlock( - &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); - - if (response) { - dbus::MessageReader reader(response.get()); - reader.PopObjectPath(&display_device_path); - } - return display_device_path; -} - -void UpdateNumberBatteriesHistogram(int count) { - UMA_HISTOGRAM_CUSTOM_COUNTS( - "BatteryStatus.NumberBatteriesLinux", count, 1, 5, 6); -} - -class BatteryProperties : public dbus::PropertySet { - public: - BatteryProperties(dbus::ObjectProxy* object_proxy, - const PropertyChangedCallback callback); - ~BatteryProperties() override; - - void ConnectSignals() override; - - void Invalidate(); - - bool is_present(bool default_value = false); - double percentage(double default_value = 100); - uint32_t state(uint32_t default_value = UPOWER_DEVICE_STATE_UNKNOWN); - int64_t time_to_empty(int64_t default_value = 0); - int64_t time_to_full(int64_t default_value = 0); - uint32_t type(uint32_t default_value = UPOWER_DEVICE_TYPE_UNKNOWN); - - private: - bool connected_ = false; - dbus::Property<bool> is_present_; - dbus::Property<double> percentage_; - dbus::Property<uint32_t> state_; - dbus::Property<int64_t> time_to_empty_; - dbus::Property<int64_t> time_to_full_; - dbus::Property<uint32_t> type_; - - DISALLOW_COPY_AND_ASSIGN(BatteryProperties); -}; - -BatteryProperties::BatteryProperties(dbus::ObjectProxy* object_proxy, - const PropertyChangedCallback callback) - : dbus::PropertySet(object_proxy, kUPowerDeviceInterfaceName, callback) { - RegisterProperty(kUPowerDevicePropertyIsPresent, &is_present_); - RegisterProperty(kUPowerDevicePropertyPercentage, &percentage_); - RegisterProperty(kUPowerDevicePropertyState, &state_); - RegisterProperty(kUPowerDevicePropertyTimeToEmpty, &time_to_empty_); - RegisterProperty(kUPowerDevicePropertyTimeToFull, &time_to_full_); - RegisterProperty(kUPowerDevicePropertyType, &type_); -} - -BatteryProperties::~BatteryProperties() {} - -void BatteryProperties::ConnectSignals() { - if (!connected_) { - connected_ = true; - dbus::PropertySet::ConnectSignals(); - } -} - -void BatteryProperties::Invalidate() { - is_present_.set_valid(false); - percentage_.set_valid(false); - state_.set_valid(false); - time_to_empty_.set_valid(false); - time_to_full_.set_valid(false); - type_.set_valid(false); -} - -bool BatteryProperties::is_present(bool default_value) { - return (is_present_.is_valid() || is_present_.GetAndBlock()) - ? is_present_.value() - : default_value; -} - -double BatteryProperties::percentage(double default_value) { - return (percentage_.is_valid() || percentage_.GetAndBlock()) - ? percentage_.value() - : default_value; -} - -uint32_t BatteryProperties::state(uint32_t default_value) { - return (state_.is_valid() || state_.GetAndBlock()) ? state_.value() - : default_value; -} - -int64_t BatteryProperties::time_to_empty(int64_t default_value) { - return (time_to_empty_.is_valid() || time_to_empty_.GetAndBlock()) - ? time_to_empty_.value() - : default_value; -} - -int64_t BatteryProperties::time_to_full(int64_t default_value) { - return (time_to_full_.is_valid() || time_to_full_.GetAndBlock()) - ? time_to_full_.value() - : default_value; -} - -uint32_t BatteryProperties::type(uint32_t default_value) { - return (type_.is_valid() || type_.GetAndBlock()) ? type_.value() - : default_value; -} - -class BatteryObject { - public: - using PropertyChangedCallback = dbus::PropertySet::PropertyChangedCallback; - - BatteryObject(dbus::Bus* dbus, - const dbus::ObjectPath& device_path, - const PropertyChangedCallback& property_changed_callback); - ~BatteryObject(); - - bool IsValid(); - - dbus::ObjectProxy* proxy() { return proxy_; } - BatteryProperties* properties() { return properties_.get(); } - - private: - dbus::Bus* dbus_; // Owned by the BatteryStatusNotificationThread, - dbus::ObjectProxy* proxy_; // Owned by the dbus. - std::unique_ptr<BatteryProperties> properties_; - - DISALLOW_COPY_AND_ASSIGN(BatteryObject); -}; - -BatteryObject::BatteryObject( - dbus::Bus* dbus, - const dbus::ObjectPath& device_path, - const PropertyChangedCallback& property_changed_callback) - : dbus_(dbus), - proxy_(dbus_->GetObjectProxy(kUPowerServiceName, device_path)), - properties_(new BatteryProperties(proxy_, property_changed_callback)) {} - -BatteryObject::~BatteryObject() { - properties_.reset(); // before the proxy is deleted. - dbus_->RemoveObjectProxy(kUPowerServiceName, proxy_->object_path(), - base::Bind(&base::DoNothing)); -} - -bool BatteryObject::IsValid() { - return properties_->is_present() && - properties_->type() == UPOWER_DEVICE_TYPE_BATTERY; -} - -mojom::BatteryStatus ComputeWebBatteryStatus(BatteryProperties* properties) { - mojom::BatteryStatus status; - uint32_t state = properties->state(); - status.charging = state != UPOWER_DEVICE_STATE_DISCHARGING && - state != UPOWER_DEVICE_STATE_EMPTY; - // Convert percentage to a value between 0 and 1 with 2 digits of precision. - // This is to bring it in line with other platforms like Mac and Android where - // we report level with 1% granularity. It also serves the purpose of reducing - // the possibility of fingerprinting and triggers less level change events on - // the blink side. - // TODO(timvolodine): consider moving this rounding to the blink side. - status.level = round(properties->percentage()) / 100.f; - - switch (state) { - case UPOWER_DEVICE_STATE_CHARGING: { - int64_t time_to_full = properties->time_to_full(); - status.charging_time = (time_to_full > 0) - ? time_to_full - : std::numeric_limits<double>::infinity(); - break; - } - case UPOWER_DEVICE_STATE_DISCHARGING: { - int64_t time_to_empty = properties->time_to_empty(); - // Set dischargingTime if it's available. Otherwise leave the default - // value which is +infinity. - if (time_to_empty > 0) - status.discharging_time = time_to_empty; - status.charging_time = std::numeric_limits<double>::infinity(); - break; - } - case UPOWER_DEVICE_STATE_FULL: { - break; - } - default: { status.charging_time = std::numeric_limits<double>::infinity(); } - } - return status; -} - -} // namespace - -// Class that represents a dedicated thread which communicates with DBus to -// obtain battery information and receives battery change notifications. -class BatteryStatusManagerLinux::BatteryStatusNotificationThread - : public base::Thread { - public: - BatteryStatusNotificationThread( - const BatteryStatusService::BatteryUpdateCallback& callback) - : base::Thread(kBatteryNotifierThreadName), callback_(callback) {} - - ~BatteryStatusNotificationThread() override { - // Make sure to shutdown the dbus connection if it is still open in the very - // end. It needs to happen on the BatteryStatusNotificationThread. - message_loop()->task_runner()->PostTask( - FROM_HERE, - base::Bind(&BatteryStatusNotificationThread::ShutdownDBusConnection, - base::Unretained(this))); - - // Drain the message queue of the BatteryStatusNotificationThread and stop. - Stop(); - } - - void StartListening() { - DCHECK(OnWatcherThread()); - - if (upower_) - return; - - if (!system_bus_) - InitDBus(); - - upower_ = base::MakeUnique<UPowerObject>( - system_bus_.get(), UPowerObject::PropertyChangedCallback()); - upower_->proxy()->ConnectToSignal( - kUPowerServiceName, kUPowerSignalDeviceAdded, - base::Bind(&BatteryStatusNotificationThread::DeviceAdded, - base::Unretained(this)), - base::Bind(&BatteryStatusNotificationThread::OnSignalConnected, - base::Unretained(this))); - upower_->proxy()->ConnectToSignal( - kUPowerServiceName, kUPowerSignalDeviceRemoved, - base::Bind(&BatteryStatusNotificationThread::DeviceRemoved, - base::Unretained(this)), - base::Bind(&BatteryStatusNotificationThread::OnSignalConnected, - base::Unretained(this))); - - FindBatteryDevice(); - } - - void StopListening() { - DCHECK(OnWatcherThread()); - ShutdownDBusConnection(); - } - - void SetDBusForTesting(dbus::Bus* bus) { system_bus_ = bus; } - - private: - bool OnWatcherThread() { - return task_runner()->BelongsToCurrentThread(); - } - - void InitDBus() { - DCHECK(OnWatcherThread()); - - dbus::Bus::Options options; - options.bus_type = dbus::Bus::SYSTEM; - options.connection_type = dbus::Bus::PRIVATE; - system_bus_ = new dbus::Bus(options); - } - - bool IsDaemonVersionBelow_0_99() { - base::Version daemon_version = upower_->properties()->daemon_version(); - return daemon_version.IsValid() && - daemon_version.CompareTo(base::Version("0.99")) < 0; - } - - void FindBatteryDevice() { - // Move the currently watched battery_ device to a stack-local variable such - // that we can enumerate all devices (once more): - // first testing the display device, then testing all devices from - // EnumerateDevices. We will monitor the first battery device we find. - // - That may be the same device we did monitor on entering this method; - // then we'll use the same BatteryObject instance, that was moved to - // current - see UseCurrentOrCreateBattery(). - // - Or it may be a new device; then the previously monitored BatteryObject - // instance (if any) is released on leaving this function. - // - Or we may not find a battery device; then on leaving this function - // battery_ will be nullptr and the previously monitored BatteryObject - // instance (if any) is no longer a battery and will be released. - std::unique_ptr<BatteryObject> current = std::move(battery_); - auto UseCurrentOrCreateBattery = - [¤t, this](const dbus::ObjectPath& device_path) { - if (current && current->proxy()->object_path() == device_path) - return std::move(current); - return CreateBattery(device_path); - }; - - dbus::ObjectPath display_device_path; - if (!IsDaemonVersionBelow_0_99()) - display_device_path = upower_->GetDisplayDevice(); - if (display_device_path.IsValid()) { - auto battery = UseCurrentOrCreateBattery(display_device_path); - if (battery->IsValid()) - battery_ = std::move(battery); - } - - if (!battery_) { - int num_batteries = 0; - for (const auto& device_path : upower_->EnumerateDevices()) { - auto battery = UseCurrentOrCreateBattery(device_path); - if (!battery->IsValid()) - continue; - - if (battery_) { - // TODO(timvolodine): add support for multiple batteries. Currently we - // only collect information from the first battery we encounter - // (crbug.com/400780). - LOG(WARNING) << "multiple batteries found, " - << "using status data of the first battery only."; - } else { - battery_ = std::move(battery); - } - num_batteries++; - } - - UpdateNumberBatteriesHistogram(num_batteries); - } - - if (!battery_) { - callback_.Run(mojom::BatteryStatus()); - return; - } - - battery_->properties()->ConnectSignals(); - NotifyBatteryStatus(); - - if (IsDaemonVersionBelow_0_99()) { - // UPower Version 0.99 replaced the Changed signal with the - // PropertyChanged signal. For older versions we need to listen - // to the Changed signal. - battery_->proxy()->ConnectToSignal( - kUPowerDeviceInterfaceName, kUPowerDeviceSignalChanged, - base::Bind(&BatteryStatusNotificationThread::BatteryChanged, - base::Unretained(this)), - base::Bind(&BatteryStatusNotificationThread::OnSignalConnected, - base::Unretained(this))); - } - } - - void ShutdownDBusConnection() { - DCHECK(OnWatcherThread()); - - if (!system_bus_.get()) - return; - - battery_.reset(); // before the system_bus_ is shut down. - upower_.reset(); - - // Shutdown DBus connection later because there may be pending tasks on - // this thread. - message_loop()->task_runner()->PostTask( - FROM_HERE, base::Bind(&dbus::Bus::ShutdownAndBlock, system_bus_)); - system_bus_ = NULL; - } - - void OnSignalConnected(const std::string& interface_name, - const std::string& signal_name, - bool success) {} - - std::unique_ptr<BatteryObject> CreateBattery( - const dbus::ObjectPath& device_path) { - return base::MakeUnique<BatteryObject>( - system_bus_.get(), device_path, - base::Bind(&BatteryStatusNotificationThread::BatteryPropertyChanged, - base::Unretained(this))); - } - - void DeviceAdded(dbus::Signal* signal /* unused */) { - // Re-iterate all devices to see if we need to monitor the added battery - // instead of the currently monitored battery. - FindBatteryDevice(); - } - - void DeviceRemoved(dbus::Signal* signal) { - if (!battery_) - return; - - // UPower specifies that the DeviceRemoved signal has an object-path as - // argument, however IRL that signal was observed with a string argument, - // so cover both cases (argument as string, as object-path and neither of - // these) and call FindBatteryDevice() if either we couldn't get the - // argument or the removed device-path is the battery_. - dbus::MessageReader reader(signal); - dbus::ObjectPath removed_device_path; - switch (reader.GetDataType()) { - case dbus::Message::DataType::STRING: { - std::string removed_device_path_string; - if (reader.PopString(&removed_device_path_string)) - removed_device_path = dbus::ObjectPath(removed_device_path_string); - break; - } - - case dbus::Message::DataType::OBJECT_PATH: - reader.PopObjectPath(&removed_device_path); - break; - - default: - break; - } - - if (!removed_device_path.IsValid() || - battery_->proxy()->object_path() == removed_device_path) - FindBatteryDevice(); - } - - void BatteryPropertyChanged(const std::string& property_name) { - NotifyBatteryStatus(); - } - - void BatteryChanged(dbus::Signal* signal /* unsused */) { - DCHECK(battery_); - battery_->properties()->Invalidate(); - NotifyBatteryStatus(); - } - - void NotifyBatteryStatus() { - DCHECK(OnWatcherThread()); - - if (!system_bus_.get() || !battery_ || notifying_battery_status_) - return; - - // If the system uses a UPower daemon older than version 0.99 - // (see IsDaemonVersionBelow_0_99), then we are notified about changed - // battery_ properties through the 'Changed' signal of the battery_ - // device (see BatteryChanged()). That is implemented to invalidate all - // battery_ properties (so they are re-fetched from the dbus). Getting - // the new property-value triggers a callback to BatteryPropertyChanged(). - // notifying_battery_status_ is set to avoid recursion and computing the - // status too often. - notifying_battery_status_ = true; - callback_.Run(ComputeWebBatteryStatus(battery_->properties())); - notifying_battery_status_ = false; - } - - BatteryStatusService::BatteryUpdateCallback callback_; - scoped_refptr<dbus::Bus> system_bus_; - std::unique_ptr<UPowerObject> upower_; - std::unique_ptr<BatteryObject> battery_; - bool notifying_battery_status_ = false; - - DISALLOW_COPY_AND_ASSIGN(BatteryStatusNotificationThread); -}; - -BatteryStatusManagerLinux::BatteryStatusManagerLinux( - const BatteryStatusService::BatteryUpdateCallback& callback) - : callback_(callback) {} - -BatteryStatusManagerLinux::~BatteryStatusManagerLinux() {} - -bool BatteryStatusManagerLinux::StartListeningBatteryChange() { - if (!StartNotifierThreadIfNecessary()) - return false; - - notifier_thread_->task_runner()->PostTask( - FROM_HERE, base::Bind(&BatteryStatusNotificationThread::StartListening, - base::Unretained(notifier_thread_.get()))); - return true; -} - -void BatteryStatusManagerLinux::StopListeningBatteryChange() { - if (!notifier_thread_) - return; - - notifier_thread_->task_runner()->PostTask( - FROM_HERE, base::Bind(&BatteryStatusNotificationThread::StopListening, - base::Unretained(notifier_thread_.get()))); -} - -bool BatteryStatusManagerLinux::StartNotifierThreadIfNecessary() { - if (notifier_thread_) - return true; - - base::Thread::Options thread_options(base::MessageLoop::TYPE_IO, 0); - auto notifier_thread = - base::MakeUnique<BatteryStatusNotificationThread>(callback_); - if (!notifier_thread->StartWithOptions(thread_options)) { - LOG(ERROR) << "Could not start the " << kBatteryNotifierThreadName - << " thread"; - return false; - } - notifier_thread_ = std::move(notifier_thread); - return true; -} - -base::Thread* BatteryStatusManagerLinux::GetNotifierThreadForTesting() { - return notifier_thread_.get(); -} - -// static -std::unique_ptr<BatteryStatusManagerLinux> -BatteryStatusManagerLinux::CreateForTesting( - const BatteryStatusService::BatteryUpdateCallback& callback, - dbus::Bus* bus) { - auto manager = base::MakeUnique<BatteryStatusManagerLinux>(callback); - if (!manager->StartNotifierThreadIfNecessary()) - return nullptr; - manager->notifier_thread_->SetDBusForTesting(bus); - return manager; -} - -// static -std::unique_ptr<BatteryStatusManager> BatteryStatusManager::Create( - const BatteryStatusService::BatteryUpdateCallback& callback) { - return base::MakeUnique<BatteryStatusManagerLinux>(callback); -} - -} // namespace device diff --git a/chromium/device/battery/battery_status_manager_linux.h b/chromium/device/battery/battery_status_manager_linux.h deleted file mode 100644 index 019fd3efec6..00000000000 --- a/chromium/device/battery/battery_status_manager_linux.h +++ /dev/null @@ -1,75 +0,0 @@ -// 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 DEVICE_BATTERY_BATTERY_STATUS_MANAGER_LINUX_H_ -#define DEVICE_BATTERY_BATTERY_STATUS_MANAGER_LINUX_H_ - -#include "device/battery/battery_export.h" -#include "device/battery/battery_status.mojom.h" -#include "device/battery/battery_status_manager.h" - -namespace dbus { -class Bus; -} // namespace dbus - -namespace device { -// UPowerDeviceState reflects the possible UPower.Device.State values, -// see upower.freedesktop.org/docs/Device.html#Device:State. -enum UPowerDeviceState { - UPOWER_DEVICE_STATE_UNKNOWN = 0, - UPOWER_DEVICE_STATE_CHARGING = 1, - UPOWER_DEVICE_STATE_DISCHARGING = 2, - UPOWER_DEVICE_STATE_EMPTY = 3, - UPOWER_DEVICE_STATE_FULL = 4, - UPOWER_DEVICE_STATE_PENDING_CHARGE = 5, - UPOWER_DEVICE_STATE_PENDING_DISCHARGE = 6, -}; - -// UPowerDeviceType reflects the possible UPower.Device.Type values, -// see upower.freedesktop.org/docs/Device.html#Device:Type. -enum UPowerDeviceType { - UPOWER_DEVICE_TYPE_UNKNOWN = 0, - UPOWER_DEVICE_TYPE_LINE_POWER = 1, - UPOWER_DEVICE_TYPE_BATTERY = 2, - UPOWER_DEVICE_TYPE_UPS = 3, - UPOWER_DEVICE_TYPE_MONITOR = 4, - UPOWER_DEVICE_TYPE_MOUSE = 5, - UPOWER_DEVICE_TYPE_KEYBOARD = 6, - UPOWER_DEVICE_TYPE_PDA = 7, - UPOWER_DEVICE_TYPE_PHONE = 8, -}; - -// Creates a notification thread and delegates Start/Stop calls to it. -class DEVICE_BATTERY_EXPORT BatteryStatusManagerLinux - : public BatteryStatusManager { - public: - explicit BatteryStatusManagerLinux( - const BatteryStatusService::BatteryUpdateCallback& callback); - ~BatteryStatusManagerLinux() override; - - private: - friend class BatteryStatusManagerLinuxTest; - class BatteryStatusNotificationThread; - - // BatteryStatusManager: - bool StartListeningBatteryChange() override; - void StopListeningBatteryChange() override; - - // Starts the notifier thread if not already started and returns true on - // success. - bool StartNotifierThreadIfNecessary(); - base::Thread* GetNotifierThreadForTesting(); - - static std::unique_ptr<BatteryStatusManagerLinux> CreateForTesting( - const BatteryStatusService::BatteryUpdateCallback& callback, - dbus::Bus* bus); - - BatteryStatusService::BatteryUpdateCallback callback_; - std::unique_ptr<BatteryStatusNotificationThread> notifier_thread_; - - DISALLOW_COPY_AND_ASSIGN(BatteryStatusManagerLinux); -}; - -} // namespace device - -#endif // DEVICE_BATTERY_BATTERY_STATUS_MANAGER_LINUX_H_ diff --git a/chromium/device/battery/battery_status_manager_linux_unittest.cc b/chromium/device/battery/battery_status_manager_linux_unittest.cc deleted file mode 100644 index 1d2f6da2fbe..00000000000 --- a/chromium/device/battery/battery_status_manager_linux_unittest.cc +++ /dev/null @@ -1,1223 +0,0 @@ -// 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 "device/battery/battery_status_manager_linux.h" - -#include <limits> -#include <list> -#include <string> - -#include "base/bind.h" -#include "base/single_thread_task_runner.h" -#include "base/synchronization/waitable_event.h" -#include "base/threading/thread.h" -#include "dbus/mock_bus.h" -#include "dbus/mock_object_proxy.h" -#include "dbus/object_path.h" -#include "dbus/property.h" -#include "device/battery/battery_status_manager_linux-inl.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -using testing::_; -using testing::Invoke; -using testing::NiceMock; -using testing::Return; -using testing::Unused; - -namespace device { - -namespace { -const char kUPowerDeviceACLinePath[] = - "/org/freedesktop/UPower/devices/line_power_AC"; -const char kUPowerDeviceBattery0Path[] = - "/org/freedesktop/UPower/devices/battery_BAT0"; -const char kUPowerDeviceBattery1Path[] = - "/org/freedesktop/UPower/devices/battery_BAT1"; -const char kUPowerDisplayDevicePath[] = - "/org/freedesktop/UPower/devices/DisplayDevice"; - -class MockUPowerObject { - public: - MockUPowerObject() {} - void ConnectToSignal( - const std::string& interface_name, - const std::string& signal_name, - dbus::ObjectProxy::SignalCallback signal_callback, - dbus::ObjectProxy::OnConnectedCallback on_connected_callback); - dbus::Response* CreateCallMethodResponse(dbus::MethodCall* method_call, - Unused); - void SignalDeviceAdded(const std::string& added_device_path); - void SignalDeviceRemoved(const std::string& removed_device_path); - - scoped_refptr<dbus::MockObjectProxy> proxy; - dbus::ObjectProxy::SignalCallback signal_callback_device_added; - dbus::ObjectProxy::SignalCallback signal_callback_device_changed; - dbus::ObjectProxy::SignalCallback signal_callback_device_removed; - std::string daemon_version; - std::list<std::string> devices; - std::string display_device; - - private: - DISALLOW_COPY_AND_ASSIGN(MockUPowerObject); -}; - -void MockUPowerObject::ConnectToSignal( - const std::string& interface_name, - const std::string& signal_name, - dbus::ObjectProxy::SignalCallback signal_callback, - dbus::ObjectProxy::OnConnectedCallback on_connected_callback) { - bool on_connected_success = true; - if (interface_name == kUPowerInterfaceName) { - if (signal_name == kUPowerSignalDeviceAdded) - signal_callback_device_added = signal_callback; - else if (signal_name == kUPowerSignalDeviceRemoved) - signal_callback_device_removed = signal_callback; - else - on_connected_success = false; - } else { - on_connected_success = false; - } - - if (!on_connected_success) { - LOG(WARNING) << "MockUPowerObject::" << __FUNCTION__ - << " Unexpected interface=" << interface_name - << ", signal=" << signal_name; - } - on_connected_callback.Run(interface_name, signal_name, on_connected_success); -} - -dbus::Response* MockUPowerObject::CreateCallMethodResponse( - dbus::MethodCall* method_call, - Unused) { - if (method_call->GetInterface() == kUPowerInterfaceName) { - if (method_call->GetMember() == kUPowerMethodEnumerateDevices) { - std::unique_ptr<dbus::Response> response = dbus::Response::CreateEmpty(); - dbus::MessageWriter writer(response.get()); - dbus::MessageWriter array_writer(nullptr); - writer.OpenArray("o", &array_writer); - for (const auto& device : devices) - array_writer.AppendObjectPath(dbus::ObjectPath(device)); - writer.CloseContainer(&array_writer); - return response.release(); - } else if (method_call->GetMember() == kUPowerMethodGetDisplayDevice) { - std::unique_ptr<dbus::Response> response = dbus::Response::CreateEmpty(); - if (!display_device.empty()) { - dbus::MessageWriter writer(response.get()); - writer.AppendObjectPath(dbus::ObjectPath(display_device)); - } - return response.release(); - } - } else if (method_call->GetInterface() == dbus::kPropertiesInterface) { - std::unique_ptr<dbus::Response> response = dbus::Response::CreateEmpty(); - dbus::MessageWriter writer(response.get()); - if (method_call->GetMember() == dbus::kPropertiesGet) { - dbus::MessageReader reader(method_call); - std::string interface_name; - std::string property_name; - if (reader.PopString(&interface_name) && - reader.PopString(&property_name) && - property_name == kUPowerPropertyDaemonVersion) { - writer.AppendVariantOfString(daemon_version); - return response.release(); - } - } else if (method_call->GetMember() == dbus::kPropertiesGetAll) { - dbus::MessageWriter array_writer(nullptr); - dbus::MessageWriter dict_entry_writer(nullptr); - writer.OpenArray("{sv}", &array_writer); - array_writer.OpenDictEntry(&dict_entry_writer); - dict_entry_writer.AppendString(kUPowerPropertyDaemonVersion); - dict_entry_writer.AppendVariantOfString(daemon_version); - array_writer.CloseContainer(&dict_entry_writer); - writer.CloseContainer(&array_writer); - return response.release(); - } - } - - LOG(ERROR) << "Unexpected method call: " << method_call->ToString(); - return nullptr; -} - -void MockUPowerObject::SignalDeviceAdded(const std::string& added_device_path) { - dbus::Signal signal(kUPowerInterfaceName, kUPowerSignalDeviceAdded); - signal.SetPath(proxy->object_path()); - dbus::MessageWriter writer(&signal); - writer.AppendObjectPath(dbus::ObjectPath(added_device_path)); - signal_callback_device_added.Run(&signal); -} - -void MockUPowerObject::SignalDeviceRemoved( - const std::string& removed_device_path) { - dbus::Signal signal(kUPowerInterfaceName, kUPowerSignalDeviceRemoved); - signal.SetPath(proxy->object_path()); - dbus::MessageWriter writer(&signal); - writer.AppendObjectPath(dbus::ObjectPath(removed_device_path)); - signal_callback_device_removed.Run(&signal); -} - -struct MockBatteryProperties { - bool is_present = true; - double percentage = 100; - uint32_t state = UPowerDeviceState::UPOWER_DEVICE_STATE_UNKNOWN; - int64_t time_to_empty = 0; - int64_t time_to_full = 0; - uint32_t type = UPowerDeviceType::UPOWER_DEVICE_TYPE_BATTERY; -}; - -class MockBatteryObject { - public: - MockBatteryObject(dbus::Bus* bus, - const std::string& object_path, - MockBatteryProperties* properties); - void ConnectToSignal( - const std::string& interface_name, - const std::string& signal_name, - dbus::ObjectProxy::SignalCallback signal_callback, - dbus::ObjectProxy::OnConnectedCallback on_connected_callback); - dbus::Response* CreateCallMethodResponse(dbus::MethodCall* method_call, - Unused); - MockBatteryObject& ExpectConnectToSignalChanged(); - MockBatteryObject& ExpectConnectToSignalPropertyChanged(); - void SignalChanged(); - void SignalPropertyChanged(const std::string& property_name); - - scoped_refptr<dbus::MockObjectProxy> proxy; - MockBatteryProperties* properties; - dbus::ObjectProxy::SignalCallback signal_callback_changed; - dbus::ObjectProxy::SignalCallback signal_callback_properties_changed; - - private: - void AppendPropertyToWriter(dbus::MessageWriter* writer, - const std::string& property_name); - void AppendAllPropertiesToWriter(dbus::MessageWriter* writer); - - DISALLOW_COPY_AND_ASSIGN(MockBatteryObject); -}; - -MockBatteryObject::MockBatteryObject(dbus::Bus* bus, - const std::string& object_path, - MockBatteryProperties* properties) - : proxy(new NiceMock<dbus::MockObjectProxy>(bus, - kUPowerServiceName, - dbus::ObjectPath(object_path))), - properties(properties) {} - -void MockBatteryObject::ConnectToSignal( - const std::string& interface_name, - const std::string& signal_name, - dbus::ObjectProxy::SignalCallback signal_callback, - dbus::ObjectProxy::OnConnectedCallback on_connected_callback) { - bool on_connected_success = true; - if (interface_name == kUPowerDeviceInterfaceName && - signal_name == kUPowerDeviceSignalChanged) - signal_callback_changed = signal_callback; - else if (interface_name == dbus::kPropertiesInterface && - signal_name == dbus::kPropertiesChanged) - signal_callback_properties_changed = signal_callback; - else - on_connected_success = false; - - if (!on_connected_success) { - LOG(WARNING) << "MockBatteryObject::" << __FUNCTION__ - << " Unexpected interface=" << interface_name - << ", signal=" << signal_name; - } - on_connected_callback.Run(interface_name, signal_name, on_connected_success); -} - -dbus::Response* MockBatteryObject::CreateCallMethodResponse( - dbus::MethodCall* method_call, - Unused) { - if (method_call->GetInterface() == dbus::kPropertiesInterface) { - if (method_call->GetMember() == dbus::kPropertiesGet) { - if (!properties) - return nullptr; - - dbus::MessageReader reader(method_call); - std::string interface_name; - std::string property_name; - if (reader.PopString(&interface_name) && - reader.PopString(&property_name)) { - std::unique_ptr<dbus::Response> response = - dbus::Response::CreateEmpty(); - dbus::MessageWriter writer(response.get()); - AppendPropertyToWriter(&writer, property_name); - return response.release(); - } - } else if (method_call->GetMember() == dbus::kPropertiesGetAll) { - if (!properties) - return nullptr; - - std::unique_ptr<dbus::Response> response = dbus::Response::CreateEmpty(); - dbus::MessageWriter writer(response.get()); - AppendAllPropertiesToWriter(&writer); - return response.release(); - } - } - LOG(ERROR) << "Unexpected method call: " << method_call->ToString(); - return nullptr; -} - -MockBatteryObject& MockBatteryObject::ExpectConnectToSignalChanged() { - EXPECT_CALL(*proxy.get(), ConnectToSignal(kUPowerDeviceInterfaceName, - kUPowerDeviceSignalChanged, _, _)) - .WillOnce(Invoke(this, &MockBatteryObject::ConnectToSignal)); - return *this; -} - -MockBatteryObject& MockBatteryObject::ExpectConnectToSignalPropertyChanged() { - EXPECT_CALL(*proxy.get(), ConnectToSignal(dbus::kPropertiesInterface, - dbus::kPropertiesChanged, _, _)) - .WillOnce(Invoke(this, &MockBatteryObject::ConnectToSignal)); - return *this; -} - -void MockBatteryObject::SignalChanged() { - dbus::Signal signal(kUPowerInterfaceName, kUPowerDeviceSignalChanged); - signal.SetPath(proxy->object_path()); - dbus::MessageWriter writer(&signal); - writer.AppendString(kUPowerDeviceInterfaceName); - signal_callback_changed.Run(&signal); -} - -void MockBatteryObject::SignalPropertyChanged( - const std::string& property_name) { - dbus::Signal signal(dbus::kPropertiesInterface, dbus::kPropertiesChanged); - signal.SetPath(proxy->object_path()); - dbus::MessageWriter writer(&signal); - writer.AppendString(kUPowerDeviceInterfaceName); - - // Dictionary {sv} of property-name => new value: - dbus::MessageWriter array_writer(nullptr); - writer.OpenArray("{sv}", &array_writer); - writer.CloseContainer(&array_writer); - - // Array of invalidated properties: - writer.OpenArray("s", &array_writer); - array_writer.AppendString(property_name); - writer.CloseContainer(&array_writer); - - signal_callback_properties_changed.Run(&signal); -} - -void MockBatteryObject::AppendPropertyToWriter( - dbus::MessageWriter* writer, - const std::string& property_name) { - if (property_name == kUPowerDevicePropertyIsPresent) - writer->AppendVariantOfBool(properties->is_present); - else if (property_name == kUPowerDevicePropertyPercentage) - writer->AppendVariantOfDouble(properties->percentage); - else if (property_name == kUPowerDevicePropertyState) - writer->AppendVariantOfUint32(properties->state); - else if (property_name == kUPowerDevicePropertyTimeToEmpty) - writer->AppendVariantOfInt64(properties->time_to_empty); - else if (property_name == kUPowerDevicePropertyTimeToFull) - writer->AppendVariantOfInt64(properties->time_to_full); - else if (property_name == kUPowerDevicePropertyType) - writer->AppendVariantOfUint32(properties->type); - else - LOG(WARNING) << __FUNCTION__ << " unknown property: " << property_name; -} - -void MockBatteryObject::AppendAllPropertiesToWriter( - dbus::MessageWriter* writer) { - dbus::MessageWriter array_writer(nullptr); - dbus::MessageWriter dict_entry_writer(nullptr); - writer->OpenArray("{sv}", &array_writer); - for (auto* property_name : - {kUPowerDevicePropertyIsPresent, kUPowerDevicePropertyState, - kUPowerDevicePropertyTimeToEmpty, kUPowerDevicePropertyTimeToFull, - kUPowerDevicePropertyType}) { - array_writer.OpenDictEntry(&dict_entry_writer); - dict_entry_writer.AppendString(property_name); - AppendPropertyToWriter(&dict_entry_writer, property_name); - array_writer.CloseContainer(&dict_entry_writer); - } - writer->CloseContainer(&array_writer); -} - -} // namespace - -class BatteryStatusManagerLinuxTest : public testing::Test { - public: - BatteryStatusManagerLinuxTest() {} - void SetUp() override; - - MockBatteryObject& SetUpDisplayDeviceProxy(MockBatteryProperties* properties); - void AddDevicePath(const std::string& object_path); - void PushFrontDevicePath(const std::string& object_path); - MockBatteryObject& AddDeviceProxy(const std::string& object_path, - MockBatteryProperties* properties); - MockBatteryObject& PushFrontDeviceProxy(const std::string& object_path, - MockBatteryProperties* properties); - - void ExpectGetObjectProxy(const std::string& object_path, - MockBatteryObject* mock_object); - void ExpectGetObjectProxy(const std::string& object_path, - dbus::ObjectProxy* object_proxy); - - void DeviceSignalChanged(MockBatteryObject* device); - void DeviceSignalPropertyChanged(MockBatteryObject* device, - const std::string& property_name); - - void UPowerSignalDeviceAdded(const std::string& device_path); - void UPowerSignalDeviceRemoved(const std::string& device_path); - - void StartBatteryStatusManagerLinux(); - - int count_battery_updates() const { return count_battery_updates_; } - const mojom::BatteryStatus& last_battery_status() const { - return last_status_; - } - - protected: - scoped_refptr<dbus::MockBus> mock_bus_; - MockUPowerObject mock_upower_; - std::unique_ptr<MockBatteryObject> mock_display_device_; - std::list<std::unique_ptr<MockBatteryObject>> mock_battery_devices_; - - private: - std::unique_ptr<MockBatteryObject> CreateMockBatteryObject( - const std::string& object_path, - MockBatteryProperties* properties); - void BatteryUpdateCallback(const mojom::BatteryStatus& status); - void SyncWithNotifierThread(); - - std::unique_ptr<BatteryStatusManagerLinux> manager_; - int count_battery_updates_ = 0; - mojom::BatteryStatus last_status_; - - DISALLOW_COPY_AND_ASSIGN(BatteryStatusManagerLinuxTest); -}; - -void BatteryStatusManagerLinuxTest::SetUp() { - dbus::Bus::Options options; - options.bus_type = dbus::Bus::SYSTEM; - options.connection_type = dbus::Bus::PRIVATE; - mock_bus_ = new NiceMock<dbus::MockBus>(options); - - mock_upower_.proxy = new NiceMock<dbus::MockObjectProxy>( - mock_bus_.get(), kUPowerServiceName, dbus::ObjectPath(kUPowerPath)); - ExpectGetObjectProxy(kUPowerPath, mock_upower_.proxy.get()); - EXPECT_CALL(*mock_upower_.proxy.get(), MockCallMethodAndBlock(_, _)) - .WillRepeatedly( - Invoke(&mock_upower_, &MockUPowerObject::CreateCallMethodResponse)); - EXPECT_CALL( - *mock_upower_.proxy.get(), - ConnectToSignal(kUPowerInterfaceName, kUPowerSignalDeviceAdded, _, _)) - .WillOnce(Invoke(&mock_upower_, &MockUPowerObject::ConnectToSignal)); - EXPECT_CALL( - *mock_upower_.proxy.get(), - ConnectToSignal(kUPowerInterfaceName, kUPowerSignalDeviceRemoved, _, _)) - .WillOnce(Invoke(&mock_upower_, &MockUPowerObject::ConnectToSignal)); -} - -MockBatteryObject& BatteryStatusManagerLinuxTest::SetUpDisplayDeviceProxy( - MockBatteryProperties* properties) { - mock_upower_.display_device = kUPowerDisplayDevicePath; - mock_display_device_ = - CreateMockBatteryObject(mock_upower_.display_device, properties); - return *mock_display_device_.get(); -} - -void BatteryStatusManagerLinuxTest::AddDevicePath( - const std::string& object_path) { - mock_upower_.devices.push_back(object_path); -} - -void BatteryStatusManagerLinuxTest::PushFrontDevicePath( - const std::string& object_path) { - mock_upower_.devices.push_front(object_path); -} - -MockBatteryObject& BatteryStatusManagerLinuxTest::AddDeviceProxy( - const std::string& object_path, - MockBatteryProperties* properties) { - AddDevicePath(object_path); - mock_battery_devices_.push_back( - CreateMockBatteryObject(object_path, properties)); - return *mock_battery_devices_.back().get(); -} - -MockBatteryObject& BatteryStatusManagerLinuxTest::PushFrontDeviceProxy( - const std::string& object_path, - MockBatteryProperties* properties) { - PushFrontDevicePath(object_path); - mock_battery_devices_.push_front( - CreateMockBatteryObject(object_path, properties)); - return *mock_battery_devices_.front().get(); -} - -void BatteryStatusManagerLinuxTest::ExpectGetObjectProxy( - const std::string& object_path, - MockBatteryObject* mock_object) { - ExpectGetObjectProxy(object_path, mock_object->proxy.get()); -} - -void BatteryStatusManagerLinuxTest::ExpectGetObjectProxy( - const std::string& object_path, - dbus::ObjectProxy* object_proxy) { - EXPECT_CALL(*mock_bus_.get(), - GetObjectProxy(kUPowerServiceName, dbus::ObjectPath(object_path))) - .WillOnce(Return(object_proxy)); -} - -void BatteryStatusManagerLinuxTest::DeviceSignalChanged( - MockBatteryObject* device) { - manager_->GetNotifierThreadForTesting()->task_runner()->PostTask( - FROM_HERE, - base::Bind(&MockBatteryObject::SignalChanged, base::Unretained(device))); - SyncWithNotifierThread(); -} - -void BatteryStatusManagerLinuxTest::DeviceSignalPropertyChanged( - MockBatteryObject* device, - const std::string& property_name) { - manager_->GetNotifierThreadForTesting()->task_runner()->PostTask( - FROM_HERE, base::Bind(&MockBatteryObject::SignalPropertyChanged, - base::Unretained(device), property_name)); - SyncWithNotifierThread(); -} - -void BatteryStatusManagerLinuxTest::UPowerSignalDeviceAdded( - const std::string& device_path) { - ASSERT_FALSE(mock_upower_.signal_callback_device_added.is_null()); - manager_->GetNotifierThreadForTesting()->task_runner()->PostTask( - FROM_HERE, base::Bind(&MockUPowerObject::SignalDeviceAdded, - base::Unretained(&mock_upower_), device_path)); - SyncWithNotifierThread(); -} - -void BatteryStatusManagerLinuxTest::UPowerSignalDeviceRemoved( - const std::string& device_path) { - ASSERT_FALSE(mock_upower_.signal_callback_device_removed.is_null()); - manager_->GetNotifierThreadForTesting()->task_runner()->PostTask( - FROM_HERE, base::Bind(&MockUPowerObject::SignalDeviceRemoved, - base::Unretained(&mock_upower_), device_path)); - SyncWithNotifierThread(); -} - -void BatteryStatusManagerLinuxTest::StartBatteryStatusManagerLinux() { - manager_ = BatteryStatusManagerLinux::CreateForTesting( - base::Bind(&BatteryStatusManagerLinuxTest::BatteryUpdateCallback, - base::Unretained(this)), - mock_bus_.get()); - manager_->StartListeningBatteryChange(); - SyncWithNotifierThread(); -} - -std::unique_ptr<MockBatteryObject> -BatteryStatusManagerLinuxTest::CreateMockBatteryObject( - const std::string& object_path, - MockBatteryProperties* properties) { - std::unique_ptr<MockBatteryObject> mock_object( - new MockBatteryObject(mock_bus_.get(), object_path, properties)); - ExpectGetObjectProxy(object_path, mock_object.get()); - EXPECT_CALL(*mock_object->proxy.get(), MockCallMethodAndBlock(_, _)) - .WillRepeatedly(Invoke(mock_object.get(), - &MockBatteryObject::CreateCallMethodResponse)); - return mock_object; -} - -void BatteryStatusManagerLinuxTest::BatteryUpdateCallback( - const mojom::BatteryStatus& status) { - ++count_battery_updates_; - last_status_ = status; -} - -void BatteryStatusManagerLinuxTest::SyncWithNotifierThread() { - ASSERT_TRUE(manager_ != nullptr); - base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED); - manager_->GetNotifierThreadForTesting()->task_runner()->PostTask( - FROM_HERE, - base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event))); - event.Wait(); -} - -TEST_F(BatteryStatusManagerLinuxTest, NoBattery) { - mojom::BatteryStatus default_status; - StartBatteryStatusManagerLinux(); - mojom::BatteryStatus status = last_battery_status(); - EXPECT_LE(1, count_battery_updates()); - - EXPECT_EQ(default_status.charging, status.charging); - EXPECT_EQ(default_status.charging_time, status.charging_time); - EXPECT_EQ(default_status.discharging_time, status.discharging_time); - EXPECT_EQ(default_status.level, status.level); -} - -TEST_F(BatteryStatusManagerLinuxTest, ChargingHalfFull) { - MockBatteryProperties battery_bat0_properties; - battery_bat0_properties.state = - UPowerDeviceState::UPOWER_DEVICE_STATE_CHARGING; - battery_bat0_properties.time_to_full = 0; - battery_bat0_properties.percentage = 50; - AddDeviceProxy(kUPowerDeviceBattery0Path, &battery_bat0_properties) - .ExpectConnectToSignalPropertyChanged(); - - StartBatteryStatusManagerLinux(); - mojom::BatteryStatus status = last_battery_status(); - EXPECT_LE(1, count_battery_updates()); - - EXPECT_TRUE(status.charging); - EXPECT_EQ(std::numeric_limits<double>::infinity(), status.charging_time); - EXPECT_EQ(std::numeric_limits<double>::infinity(), status.discharging_time); - EXPECT_EQ(0.5, status.level); -} - -TEST_F(BatteryStatusManagerLinuxTest, ChargingTimeToFull) { - MockBatteryProperties battery_bat0_properties; - battery_bat0_properties.state = - UPowerDeviceState::UPOWER_DEVICE_STATE_CHARGING; - battery_bat0_properties.time_to_full = 100; - battery_bat0_properties.percentage = 1; - AddDeviceProxy(kUPowerDeviceBattery0Path, &battery_bat0_properties) - .ExpectConnectToSignalPropertyChanged(); - - StartBatteryStatusManagerLinux(); - mojom::BatteryStatus status = last_battery_status(); - EXPECT_LE(1, count_battery_updates()); - - EXPECT_TRUE(status.charging); - EXPECT_EQ(100, status.charging_time); - EXPECT_EQ(std::numeric_limits<double>::infinity(), status.discharging_time); - EXPECT_EQ(.01, status.level); -} - -TEST_F(BatteryStatusManagerLinuxTest, FullyCharged) { - MockBatteryProperties battery_bat0_properties; - battery_bat0_properties.state = UPowerDeviceState::UPOWER_DEVICE_STATE_FULL; - battery_bat0_properties.time_to_full = 100; - battery_bat0_properties.time_to_empty = 200; - battery_bat0_properties.percentage = 100; - AddDeviceProxy(kUPowerDeviceBattery0Path, &battery_bat0_properties) - .ExpectConnectToSignalPropertyChanged(); - - StartBatteryStatusManagerLinux(); - mojom::BatteryStatus status = last_battery_status(); - EXPECT_LE(1, count_battery_updates()); - - EXPECT_TRUE(status.charging); - EXPECT_EQ(0, status.charging_time); - EXPECT_EQ(std::numeric_limits<double>::infinity(), status.discharging_time); - EXPECT_EQ(1, status.level); -} - -TEST_F(BatteryStatusManagerLinuxTest, Discharging) { - MockBatteryProperties battery_bat0_properties; - battery_bat0_properties.state = - UPowerDeviceState::UPOWER_DEVICE_STATE_DISCHARGING; - battery_bat0_properties.time_to_full = 0; - battery_bat0_properties.time_to_empty = 200; - battery_bat0_properties.percentage = 90; - AddDeviceProxy(kUPowerDeviceBattery0Path, &battery_bat0_properties) - .ExpectConnectToSignalPropertyChanged(); - - StartBatteryStatusManagerLinux(); - mojom::BatteryStatus status = last_battery_status(); - EXPECT_LE(1, count_battery_updates()); - - EXPECT_FALSE(status.charging); - EXPECT_EQ(std::numeric_limits<double>::infinity(), status.charging_time); - EXPECT_EQ(200, status.discharging_time); - EXPECT_EQ(.9, status.level); -} - -TEST_F(BatteryStatusManagerLinuxTest, DischargingTimeToEmptyUnknown) { - MockBatteryProperties battery_bat0_properties; - battery_bat0_properties.state = - UPowerDeviceState::UPOWER_DEVICE_STATE_DISCHARGING; - battery_bat0_properties.time_to_full = 0; - battery_bat0_properties.time_to_empty = 0; - battery_bat0_properties.percentage = 90; - AddDeviceProxy(kUPowerDeviceBattery0Path, &battery_bat0_properties) - .ExpectConnectToSignalPropertyChanged(); - - StartBatteryStatusManagerLinux(); - mojom::BatteryStatus status = last_battery_status(); - EXPECT_LE(1, count_battery_updates()); - - EXPECT_FALSE(status.charging); - EXPECT_EQ(std::numeric_limits<double>::infinity(), status.charging_time); - EXPECT_EQ(std::numeric_limits<double>::infinity(), status.discharging_time); - EXPECT_EQ(.9, status.level); -} - -TEST_F(BatteryStatusManagerLinuxTest, DeviceStateUnknown) { - MockBatteryProperties battery_bat0_properties; - battery_bat0_properties.state = - UPowerDeviceState::UPOWER_DEVICE_STATE_UNKNOWN; - battery_bat0_properties.time_to_full = 0; - battery_bat0_properties.time_to_empty = 0; - battery_bat0_properties.percentage = 50; - AddDeviceProxy(kUPowerDeviceBattery0Path, &battery_bat0_properties) - .ExpectConnectToSignalPropertyChanged(); - - StartBatteryStatusManagerLinux(); - mojom::BatteryStatus status = last_battery_status(); - EXPECT_LE(1, count_battery_updates()); - - EXPECT_TRUE(status.charging); - EXPECT_EQ(std::numeric_limits<double>::infinity(), status.charging_time); - EXPECT_EQ(std::numeric_limits<double>::infinity(), status.discharging_time); - EXPECT_EQ(.5, status.level); -} - -TEST_F(BatteryStatusManagerLinuxTest, DeviceStateEmpty) { - MockBatteryProperties battery_bat0_properties; - battery_bat0_properties.state = UPowerDeviceState::UPOWER_DEVICE_STATE_EMPTY; - battery_bat0_properties.time_to_full = 0; - battery_bat0_properties.time_to_empty = 0; - battery_bat0_properties.percentage = 0; - AddDeviceProxy(kUPowerDeviceBattery0Path, &battery_bat0_properties) - .ExpectConnectToSignalPropertyChanged(); - - StartBatteryStatusManagerLinux(); - mojom::BatteryStatus status = last_battery_status(); - EXPECT_LE(1, count_battery_updates()); - - EXPECT_FALSE(status.charging); - EXPECT_EQ(std::numeric_limits<double>::infinity(), status.charging_time); - EXPECT_EQ(std::numeric_limits<double>::infinity(), status.discharging_time); - EXPECT_EQ(0, status.level); -} - -TEST_F(BatteryStatusManagerLinuxTest, LevelRoundedToThreeSignificantDigits) { - MockBatteryProperties battery_bat0_properties; - battery_bat0_properties.state = - UPowerDeviceState::UPOWER_DEVICE_STATE_DISCHARGING; - battery_bat0_properties.percentage = 14.56; - AddDeviceProxy(kUPowerDeviceBattery0Path, &battery_bat0_properties) - .ExpectConnectToSignalPropertyChanged(); - - StartBatteryStatusManagerLinux(); - mojom::BatteryStatus status = last_battery_status(); - EXPECT_LE(1, count_battery_updates()); - - EXPECT_FALSE(status.charging); - EXPECT_EQ(std::numeric_limits<double>::infinity(), status.charging_time); - EXPECT_EQ(std::numeric_limits<double>::infinity(), status.discharging_time); - EXPECT_EQ(0.15, status.level); -} - -TEST_F(BatteryStatusManagerLinuxTest, UsingFirstBatteryDevice) { - MockBatteryProperties battery_bat0_properties; - battery_bat0_properties.state = - UPowerDeviceState::UPOWER_DEVICE_STATE_DISCHARGING; - battery_bat0_properties.time_to_full = 0; - battery_bat0_properties.time_to_empty = 200; - battery_bat0_properties.percentage = 70; - AddDeviceProxy(kUPowerDeviceBattery0Path, &battery_bat0_properties) - .ExpectConnectToSignalPropertyChanged(); - - MockBatteryProperties battery_bat1_properties; - battery_bat1_properties.state = - UPowerDeviceState::UPOWER_DEVICE_STATE_CHARGING; - battery_bat1_properties.time_to_full = 100; - battery_bat1_properties.time_to_empty = 0; - battery_bat1_properties.percentage = 80; - AddDeviceProxy(kUPowerDeviceBattery1Path, &battery_bat1_properties); - - StartBatteryStatusManagerLinux(); - mojom::BatteryStatus status = last_battery_status(); - EXPECT_LE(1, count_battery_updates()); - - EXPECT_FALSE(status.charging); - EXPECT_EQ(std::numeric_limits<double>::infinity(), status.charging_time); - EXPECT_EQ(200, status.discharging_time); - EXPECT_EQ(0.7, status.level); -} - -TEST_F(BatteryStatusManagerLinuxTest, SkipNonBatteryDevice) { - MockBatteryProperties line_power_AC_properties; - line_power_AC_properties.type = - UPowerDeviceType::UPOWER_DEVICE_TYPE_LINE_POWER; - AddDeviceProxy(kUPowerDeviceACLinePath, &line_power_AC_properties); - - MockBatteryProperties battery_bat0_properties; - battery_bat0_properties.state = - UPowerDeviceState::UPOWER_DEVICE_STATE_DISCHARGING; - battery_bat0_properties.time_to_full = 0; - battery_bat0_properties.time_to_empty = 200; - battery_bat0_properties.percentage = 70; - AddDeviceProxy(kUPowerDeviceBattery0Path, &battery_bat0_properties) - .ExpectConnectToSignalPropertyChanged(); - - StartBatteryStatusManagerLinux(); - mojom::BatteryStatus status = last_battery_status(); - EXPECT_LE(1, count_battery_updates()); - - EXPECT_FALSE(status.charging); - EXPECT_EQ(std::numeric_limits<double>::infinity(), status.charging_time); - EXPECT_EQ(200, status.discharging_time); - EXPECT_EQ(0.7, status.level); -} - -TEST_F(BatteryStatusManagerLinuxTest, UpdateDevicePropertyState) { - MockBatteryProperties battery_bat0_properties; - battery_bat0_properties.state = - UPowerDeviceState::UPOWER_DEVICE_STATE_CHARGING; - battery_bat0_properties.time_to_full = 100; - battery_bat0_properties.time_to_empty = 200; - battery_bat0_properties.percentage = 80; - MockBatteryObject& battery_bat0 = - AddDeviceProxy(kUPowerDeviceBattery0Path, &battery_bat0_properties) - .ExpectConnectToSignalPropertyChanged(); - - StartBatteryStatusManagerLinux(); - mojom::BatteryStatus status = last_battery_status(); - EXPECT_LE(1, count_battery_updates()); - - EXPECT_TRUE(status.charging); - EXPECT_EQ(100, status.charging_time); - EXPECT_EQ(std::numeric_limits<double>::infinity(), status.discharging_time); - EXPECT_EQ(.8, status.level); - - int last_count = count_battery_updates(); - battery_bat0_properties.state = - UPowerDeviceState::UPOWER_DEVICE_STATE_DISCHARGING; - DeviceSignalPropertyChanged(&battery_bat0, kUPowerDevicePropertyState); - status = last_battery_status(); - - EXPECT_LT(last_count, count_battery_updates()); - EXPECT_FALSE(status.charging); - EXPECT_EQ(std::numeric_limits<double>::infinity(), status.charging_time); - EXPECT_EQ(200, status.discharging_time); - EXPECT_EQ(.8, status.level); -} - -TEST_F(BatteryStatusManagerLinuxTest, UpdateDevicePropertyPercentage) { - MockBatteryProperties battery_bat0_properties; - battery_bat0_properties.state = - UPowerDeviceState::UPOWER_DEVICE_STATE_DISCHARGING; - battery_bat0_properties.time_to_full = 100; - battery_bat0_properties.time_to_empty = 200; - battery_bat0_properties.percentage = 80; - MockBatteryObject& battery_bat0 = - AddDeviceProxy(kUPowerDeviceBattery0Path, &battery_bat0_properties) - .ExpectConnectToSignalPropertyChanged(); - - StartBatteryStatusManagerLinux(); - mojom::BatteryStatus status = last_battery_status(); - EXPECT_LE(1, count_battery_updates()); - - EXPECT_FALSE(status.charging); - EXPECT_EQ(std::numeric_limits<double>::infinity(), status.charging_time); - EXPECT_EQ(200, status.discharging_time); - EXPECT_EQ(.8, status.level); - - int last_count = count_battery_updates(); - battery_bat0_properties.percentage = 70; - DeviceSignalPropertyChanged(&battery_bat0, kUPowerDevicePropertyPercentage); - status = last_battery_status(); - - EXPECT_LT(last_count, count_battery_updates()); - EXPECT_FALSE(status.charging); - EXPECT_EQ(std::numeric_limits<double>::infinity(), status.charging_time); - EXPECT_EQ(200, status.discharging_time); - EXPECT_EQ(.7, status.level); -} - -TEST_F(BatteryStatusManagerLinuxTest, UpdateDevicePropertyTimeToEmpty) { - MockBatteryProperties battery_bat0_properties; - battery_bat0_properties.state = - UPowerDeviceState::UPOWER_DEVICE_STATE_DISCHARGING; - battery_bat0_properties.time_to_full = 100; - battery_bat0_properties.time_to_empty = 200; - battery_bat0_properties.percentage = 80; - MockBatteryObject& battery_bat0 = - AddDeviceProxy(kUPowerDeviceBattery0Path, &battery_bat0_properties) - .ExpectConnectToSignalPropertyChanged(); - - StartBatteryStatusManagerLinux(); - mojom::BatteryStatus status = last_battery_status(); - EXPECT_LE(1, count_battery_updates()); - - EXPECT_FALSE(status.charging); - EXPECT_EQ(std::numeric_limits<double>::infinity(), status.charging_time); - EXPECT_EQ(200, status.discharging_time); - EXPECT_EQ(.8, status.level); - - int last_count = count_battery_updates(); - battery_bat0_properties.time_to_empty = 150; - DeviceSignalPropertyChanged(&battery_bat0, kUPowerDevicePropertyTimeToEmpty); - status = last_battery_status(); - - EXPECT_LT(last_count, count_battery_updates()); - EXPECT_FALSE(status.charging); - EXPECT_EQ(std::numeric_limits<double>::infinity(), status.charging_time); - EXPECT_EQ(150, status.discharging_time); - EXPECT_EQ(.8, status.level); -} - -TEST_F(BatteryStatusManagerLinuxTest, UpdateDevicePropertyTimeToFull) { - MockBatteryProperties battery_bat0_properties; - battery_bat0_properties.state = - UPowerDeviceState::UPOWER_DEVICE_STATE_CHARGING; - battery_bat0_properties.time_to_full = 100; - battery_bat0_properties.time_to_empty = 200; - battery_bat0_properties.percentage = 80; - MockBatteryObject& battery_bat0 = - AddDeviceProxy(kUPowerDeviceBattery0Path, &battery_bat0_properties) - .ExpectConnectToSignalPropertyChanged(); - - StartBatteryStatusManagerLinux(); - mojom::BatteryStatus status = last_battery_status(); - EXPECT_LE(1, count_battery_updates()); - - EXPECT_TRUE(status.charging); - EXPECT_EQ(100, status.charging_time); - EXPECT_EQ(std::numeric_limits<double>::infinity(), status.discharging_time); - EXPECT_EQ(.8, status.level); - - int last_count = count_battery_updates(); - battery_bat0_properties.time_to_full = 50; - DeviceSignalPropertyChanged(&battery_bat0, kUPowerDevicePropertyTimeToFull); - status = last_battery_status(); - - EXPECT_LT(last_count, count_battery_updates()); - EXPECT_TRUE(status.charging); - EXPECT_EQ(50, status.charging_time); - EXPECT_EQ(std::numeric_limits<double>::infinity(), status.discharging_time); - EXPECT_EQ(.8, status.level); -} - -TEST_F(BatteryStatusManagerLinuxTest, OldDaemonDeviceSignalChanged) { - mock_upower_.daemon_version = "0.9.23"; - - MockBatteryProperties battery_bat0_properties; - battery_bat0_properties.state = - UPowerDeviceState::UPOWER_DEVICE_STATE_DISCHARGING; - battery_bat0_properties.time_to_full = 100; - battery_bat0_properties.time_to_empty = 200; - battery_bat0_properties.percentage = 80; - MockBatteryObject& battery_bat0 = - AddDeviceProxy(kUPowerDeviceBattery0Path, &battery_bat0_properties) - .ExpectConnectToSignalChanged() - .ExpectConnectToSignalPropertyChanged(); - - StartBatteryStatusManagerLinux(); - mojom::BatteryStatus status = last_battery_status(); - EXPECT_LE(1, count_battery_updates()); - - EXPECT_FALSE(status.charging); - EXPECT_EQ(std::numeric_limits<double>::infinity(), status.charging_time); - EXPECT_EQ(200, status.discharging_time); - EXPECT_EQ(.8, status.level); - - int last_count = count_battery_updates(); - battery_bat0_properties.percentage = 70; - DeviceSignalChanged(&battery_bat0); - status = last_battery_status(); - - EXPECT_LT(last_count, count_battery_updates()); - EXPECT_FALSE(status.charging); - EXPECT_EQ(std::numeric_limits<double>::infinity(), status.charging_time); - EXPECT_EQ(200, status.discharging_time); - EXPECT_EQ(.7, status.level); -} - -TEST_F(BatteryStatusManagerLinuxTest, DisplayDeviceNoBattery) { - MockBatteryProperties display_device_properties; - display_device_properties.type = UPowerDeviceType::UPOWER_DEVICE_TYPE_UNKNOWN; - SetUpDisplayDeviceProxy(&display_device_properties); - - MockBatteryProperties battery_bat0_properties; - battery_bat0_properties.state = - UPowerDeviceState::UPOWER_DEVICE_STATE_DISCHARGING; - battery_bat0_properties.time_to_full = 0; - battery_bat0_properties.time_to_empty = 200; - battery_bat0_properties.percentage = 90; - AddDeviceProxy(kUPowerDeviceBattery0Path, &battery_bat0_properties) - .ExpectConnectToSignalPropertyChanged(); - - StartBatteryStatusManagerLinux(); - mojom::BatteryStatus status = last_battery_status(); - EXPECT_LE(1, count_battery_updates()); - - EXPECT_FALSE(status.charging); - EXPECT_EQ(std::numeric_limits<double>::infinity(), status.charging_time); - EXPECT_EQ(200, status.discharging_time); - EXPECT_EQ(0.9, status.level); -} - -TEST_F(BatteryStatusManagerLinuxTest, DisplayDeviceBattery) { - MockBatteryProperties display_device_properties; - display_device_properties.state = - UPowerDeviceState::UPOWER_DEVICE_STATE_DISCHARGING; - display_device_properties.time_to_full = 0; - display_device_properties.time_to_empty = 200; - display_device_properties.percentage = 90; - SetUpDisplayDeviceProxy(&display_device_properties) - .ExpectConnectToSignalPropertyChanged(); - - StartBatteryStatusManagerLinux(); - mojom::BatteryStatus status = last_battery_status(); - EXPECT_LE(1, count_battery_updates()); - - EXPECT_FALSE(status.charging); - EXPECT_EQ(std::numeric_limits<double>::infinity(), status.charging_time); - EXPECT_EQ(200, status.discharging_time); - EXPECT_EQ(.9, status.level); -} - -TEST_F(BatteryStatusManagerLinuxTest, DisplayDeviceBatterySkipsEnumerate) { - MockBatteryProperties display_device_properties; - display_device_properties.state = - UPowerDeviceState::UPOWER_DEVICE_STATE_DISCHARGING; - display_device_properties.time_to_full = 0; - display_device_properties.time_to_empty = 200; - display_device_properties.percentage = 90; - SetUpDisplayDeviceProxy(&display_device_properties) - .ExpectConnectToSignalPropertyChanged(); - - AddDevicePath(kUPowerDeviceACLinePath); - AddDevicePath(kUPowerDeviceBattery0Path); - AddDevicePath(kUPowerDeviceBattery1Path); - - StartBatteryStatusManagerLinux(); - mojom::BatteryStatus status = last_battery_status(); - EXPECT_LE(1, count_battery_updates()); - - EXPECT_FALSE(status.charging); - EXPECT_EQ(std::numeric_limits<double>::infinity(), status.charging_time); - EXPECT_EQ(200, status.discharging_time); - EXPECT_EQ(.9, status.level); -} - -// Adding a display-device will make the BatteryStatusManagerLinux switch to -// the display-device. -TEST_F(BatteryStatusManagerLinuxTest, SignalDeviceAddedDisplayDevice) { - MockBatteryProperties battery_bat0_properties; - battery_bat0_properties.state = - UPowerDeviceState::UPOWER_DEVICE_STATE_DISCHARGING; - battery_bat0_properties.time_to_full = 0; - battery_bat0_properties.time_to_empty = 200; - battery_bat0_properties.percentage = 70; - AddDeviceProxy(kUPowerDeviceBattery0Path, &battery_bat0_properties) - .ExpectConnectToSignalPropertyChanged(); - - StartBatteryStatusManagerLinux(); - mojom::BatteryStatus status = last_battery_status(); - EXPECT_LE(1, count_battery_updates()); - - EXPECT_FALSE(status.charging); - EXPECT_EQ(std::numeric_limits<double>::infinity(), status.charging_time); - EXPECT_EQ(200, status.discharging_time); - EXPECT_EQ(0.7, status.level); - - int last_count = count_battery_updates(); - MockBatteryProperties display_device_properties; - display_device_properties.state = - UPowerDeviceState::UPOWER_DEVICE_STATE_CHARGING; - display_device_properties.time_to_full = 100; - display_device_properties.time_to_empty = 150; - display_device_properties.percentage = 80; - SetUpDisplayDeviceProxy(&display_device_properties) - .ExpectConnectToSignalPropertyChanged(); - - UPowerSignalDeviceAdded(mock_upower_.display_device); - status = last_battery_status(); - EXPECT_LT(last_count, count_battery_updates()); - - EXPECT_TRUE(status.charging); - EXPECT_EQ(100, status.charging_time); - EXPECT_EQ(std::numeric_limits<double>::infinity(), status.discharging_time); - EXPECT_EQ(0.8, status.level); -} - -// Prepending a battery should switch to that battery. -TEST_F(BatteryStatusManagerLinuxTest, SignalDeviceAddedBatteryAtFront) { - MockBatteryProperties battery_bat1_properties; - battery_bat1_properties.state = - UPowerDeviceState::UPOWER_DEVICE_STATE_DISCHARGING; - battery_bat1_properties.time_to_full = 0; - battery_bat1_properties.time_to_empty = 200; - battery_bat1_properties.percentage = 70; - AddDeviceProxy(kUPowerDeviceBattery1Path, &battery_bat1_properties) - .ExpectConnectToSignalPropertyChanged(); - - StartBatteryStatusManagerLinux(); - mojom::BatteryStatus status = last_battery_status(); - EXPECT_LE(1, count_battery_updates()); - - EXPECT_FALSE(status.charging); - EXPECT_EQ(std::numeric_limits<double>::infinity(), status.charging_time); - EXPECT_EQ(200, status.discharging_time); - EXPECT_EQ(0.7, status.level); - - int last_count = count_battery_updates(); - MockBatteryProperties battery_bat0_properties; - battery_bat0_properties.state = - UPowerDeviceState::UPOWER_DEVICE_STATE_DISCHARGING; - battery_bat0_properties.time_to_full = 0; - battery_bat0_properties.time_to_empty = 150; - battery_bat0_properties.percentage = 50; - PushFrontDeviceProxy(kUPowerDeviceBattery0Path, &battery_bat0_properties) - .ExpectConnectToSignalPropertyChanged(); - UPowerSignalDeviceAdded(kUPowerDeviceBattery0Path); - status = last_battery_status(); - EXPECT_LT(last_count, count_battery_updates()); - - EXPECT_FALSE(status.charging); - EXPECT_EQ(std::numeric_limits<double>::infinity(), status.charging_time); - EXPECT_EQ(150, status.discharging_time); - EXPECT_EQ(0.5, status.level); -} - -// Appending a battery should keep the current battery. -TEST_F(BatteryStatusManagerLinuxTest, SignalDeviceAddedBatteryAtBack) { - MockBatteryProperties battery_bat0_properties; - battery_bat0_properties.state = - UPowerDeviceState::UPOWER_DEVICE_STATE_DISCHARGING; - battery_bat0_properties.time_to_full = 0; - battery_bat0_properties.time_to_empty = 150; - battery_bat0_properties.percentage = 50; - AddDeviceProxy(kUPowerDeviceBattery0Path, &battery_bat0_properties) - .ExpectConnectToSignalPropertyChanged(); - - StartBatteryStatusManagerLinux(); - mojom::BatteryStatus status = last_battery_status(); - EXPECT_LE(1, count_battery_updates()); - - EXPECT_FALSE(status.charging); - EXPECT_EQ(std::numeric_limits<double>::infinity(), status.charging_time); - EXPECT_EQ(150, status.discharging_time); - EXPECT_EQ(0.5, status.level); - - int last_count = count_battery_updates(); - MockBatteryProperties battery_bat1_properties; - battery_bat1_properties.state = - UPowerDeviceState::UPOWER_DEVICE_STATE_DISCHARGING; - battery_bat1_properties.time_to_full = 0; - battery_bat1_properties.time_to_empty = 200; - battery_bat1_properties.percentage = 70; - AddDeviceProxy(kUPowerDeviceBattery1Path, &battery_bat1_properties); - UPowerSignalDeviceAdded(kUPowerDeviceBattery1Path); - status = last_battery_status(); - EXPECT_LT(last_count, count_battery_updates()); - - EXPECT_FALSE(status.charging); - EXPECT_EQ(std::numeric_limits<double>::infinity(), status.charging_time); - EXPECT_EQ(150, status.discharging_time); - EXPECT_EQ(0.5, status.level); -} - -// Adding a device that is no battery should not change anything. -TEST_F(BatteryStatusManagerLinuxTest, SignalDeviceAddedNoBattery) { - MockBatteryProperties battery_bat0_properties; - battery_bat0_properties.state = - UPowerDeviceState::UPOWER_DEVICE_STATE_DISCHARGING; - battery_bat0_properties.time_to_full = 0; - battery_bat0_properties.time_to_empty = 200; - battery_bat0_properties.percentage = 70; - AddDeviceProxy(kUPowerDeviceBattery0Path, &battery_bat0_properties) - .ExpectConnectToSignalPropertyChanged(); - - StartBatteryStatusManagerLinux(); - mojom::BatteryStatus status = last_battery_status(); - EXPECT_LE(1, count_battery_updates()); - - EXPECT_FALSE(status.charging); - EXPECT_EQ(std::numeric_limits<double>::infinity(), status.charging_time); - EXPECT_EQ(200, status.discharging_time); - EXPECT_EQ(0.7, status.level); - - int last_count = count_battery_updates(); - MockBatteryProperties line_power_AC_properties; - line_power_AC_properties.type = - UPowerDeviceType::UPOWER_DEVICE_TYPE_LINE_POWER; - PushFrontDeviceProxy(kUPowerDeviceACLinePath, &line_power_AC_properties); - UPowerSignalDeviceAdded(kUPowerDeviceACLinePath); - status = last_battery_status(); - EXPECT_LT(last_count, count_battery_updates()); - - EXPECT_FALSE(status.charging); - EXPECT_EQ(std::numeric_limits<double>::infinity(), status.charging_time); - EXPECT_EQ(200, status.discharging_time); - EXPECT_EQ(0.7, status.level); -} - -TEST_F(BatteryStatusManagerLinuxTest, SignalDeviceRemovedBattery) { - MockBatteryProperties battery_bat0_properties; - battery_bat0_properties.state = - UPowerDeviceState::UPOWER_DEVICE_STATE_DISCHARGING; - battery_bat0_properties.time_to_full = 0; - battery_bat0_properties.time_to_empty = 200; - battery_bat0_properties.percentage = 70; - AddDeviceProxy(kUPowerDeviceBattery0Path, &battery_bat0_properties) - .ExpectConnectToSignalPropertyChanged(); - - MockBatteryProperties battery_bat1_properties; - battery_bat1_properties.state = - UPowerDeviceState::UPOWER_DEVICE_STATE_CHARGING; - battery_bat1_properties.time_to_full = 100; - battery_bat1_properties.time_to_empty = 0; - battery_bat1_properties.percentage = 80; - MockBatteryObject& battery_bat1 = - AddDeviceProxy(kUPowerDeviceBattery1Path, &battery_bat1_properties); - - StartBatteryStatusManagerLinux(); - mojom::BatteryStatus status = last_battery_status(); - EXPECT_LE(1, count_battery_updates()); - - EXPECT_FALSE(status.charging); - EXPECT_EQ(std::numeric_limits<double>::infinity(), status.charging_time); - EXPECT_EQ(200, status.discharging_time); - EXPECT_EQ(0.7, status.level); - - int last_count = count_battery_updates(); - ExpectGetObjectProxy(kUPowerDeviceBattery1Path, &battery_bat1); - battery_bat1.ExpectConnectToSignalPropertyChanged(); - - EXPECT_EQ(kUPowerDeviceBattery0Path, mock_upower_.devices.front()); - mock_upower_.devices.pop_front(); - UPowerSignalDeviceRemoved(kUPowerDeviceBattery0Path); - status = last_battery_status(); - EXPECT_LT(last_count, count_battery_updates()); - - EXPECT_TRUE(status.charging); - EXPECT_EQ(100, status.charging_time); - EXPECT_EQ(std::numeric_limits<double>::infinity(), status.discharging_time); - EXPECT_EQ(0.8, status.level); -} - -TEST_F(BatteryStatusManagerLinuxTest, SignalDeviceRemovedOther) { - MockBatteryProperties battery_bat0_properties; - battery_bat0_properties.state = - UPowerDeviceState::UPOWER_DEVICE_STATE_DISCHARGING; - battery_bat0_properties.time_to_full = 0; - battery_bat0_properties.time_to_empty = 200; - battery_bat0_properties.percentage = 70; - AddDeviceProxy(kUPowerDeviceBattery0Path, &battery_bat0_properties) - .ExpectConnectToSignalPropertyChanged(); - - MockBatteryProperties line_power_AC_properties; - line_power_AC_properties.type = - UPowerDeviceType::UPOWER_DEVICE_TYPE_LINE_POWER; - AddDeviceProxy(kUPowerDeviceACLinePath, &line_power_AC_properties); - - StartBatteryStatusManagerLinux(); - mojom::BatteryStatus status = last_battery_status(); - EXPECT_LE(1, count_battery_updates()); - - EXPECT_FALSE(status.charging); - EXPECT_EQ(std::numeric_limits<double>::infinity(), status.charging_time); - EXPECT_EQ(200, status.discharging_time); - EXPECT_EQ(0.7, status.level); - - int last_count = count_battery_updates(); - mock_upower_.devices.pop_back(); - UPowerSignalDeviceRemoved(kUPowerDeviceACLinePath); - status = last_battery_status(); - EXPECT_EQ(last_count, count_battery_updates()); - - EXPECT_FALSE(status.charging); - EXPECT_EQ(std::numeric_limits<double>::infinity(), status.charging_time); - EXPECT_EQ(200, status.discharging_time); - EXPECT_EQ(0.7, status.level); -} - -} // namespace device diff --git a/chromium/device/battery/battery_status_manager_mac.cc b/chromium/device/battery/battery_status_manager_mac.cc deleted file mode 100644 index 00d088057e9..00000000000 --- a/chromium/device/battery/battery_status_manager_mac.cc +++ /dev/null @@ -1,246 +0,0 @@ -// 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 "device/battery/battery_status_manager.h" - -#include <CoreFoundation/CoreFoundation.h> -#include <IOKit/ps/IOPSKeys.h> -#include <IOKit/ps/IOPowerSources.h> - -#include <memory> -#include <vector> - -#include "base/mac/foundation_util.h" -#include "base/mac/scoped_cftyperef.h" -#include "base/macros.h" -#include "base/metrics/histogram_macros.h" -#include "base/time/time.h" - -namespace device { - -namespace { - -typedef BatteryStatusService::BatteryUpdateCallback BatteryCallback; - -// Returns the value corresponding to |key| in the dictionary |description|. -// Returns |default_value| if the dictionary does not contain |key|, the -// corresponding value is NULL or it could not be converted to SInt64. -SInt64 GetValueAsSInt64(CFDictionaryRef description, - CFStringRef key, - SInt64 default_value) { - CFNumberRef number = - base::mac::GetValueFromDictionary<CFNumberRef>(description, key); - SInt64 value; - - if (number && CFNumberGetValue(number, kCFNumberSInt64Type, &value)) - return value; - - return default_value; -} - -bool GetValueAsBoolean(CFDictionaryRef description, - CFStringRef key, - bool default_value) { - CFBooleanRef boolean = - base::mac::GetValueFromDictionary<CFBooleanRef>(description, key); - - return boolean ? CFBooleanGetValue(boolean) : default_value; -} - -bool CFStringsAreEqual(CFStringRef string1, CFStringRef string2) { - if (!string1 || !string2) - return false; - return CFStringCompare(string1, string2, 0) == kCFCompareEqualTo; -} - -void UpdateNumberBatteriesHistogram(int count) { - UMA_HISTOGRAM_CUSTOM_COUNTS( - "BatteryStatus.NumberBatteriesMac", count, 1, 5, 6); -} - -void FetchBatteryStatus(CFDictionaryRef description, - mojom::BatteryStatus* status) { - CFStringRef current_state = - base::mac::GetValueFromDictionary<CFStringRef>(description, - CFSTR(kIOPSPowerSourceStateKey)); - - bool on_battery_power = - CFStringsAreEqual(current_state, CFSTR(kIOPSBatteryPowerValue)); - bool is_charging = - GetValueAsBoolean(description, CFSTR(kIOPSIsChargingKey), true); - bool is_charged = - GetValueAsBoolean(description, CFSTR(kIOPSIsChargedKey), false); - - status->charging = !on_battery_power || is_charging; - - SInt64 current_capacity = - GetValueAsSInt64(description, CFSTR(kIOPSCurrentCapacityKey), -1); - SInt64 max_capacity = - GetValueAsSInt64(description, CFSTR(kIOPSMaxCapacityKey), -1); - - // Set level if it is available and valid. Otherwise leave the default value, - // which is 1. - if (current_capacity != -1 && max_capacity != -1 && - current_capacity <= max_capacity && max_capacity != 0) { - status->level = current_capacity / static_cast<double>(max_capacity); - } - - if (is_charging) { - SInt64 charging_time = - GetValueAsSInt64(description, CFSTR(kIOPSTimeToFullChargeKey), -1); - - // Battery is charging: set the charging time if it's available, otherwise - // set to +infinity. - status->charging_time = charging_time != -1 - ? base::TimeDelta::FromMinutes(charging_time).InSeconds() - : std::numeric_limits<double>::infinity(); - } else { - // Battery is not charging. - // Set chargingTime to +infinity if the battery is not charged. Otherwise - // leave the default value, which is 0. - if (!is_charged) - status->charging_time = std::numeric_limits<double>::infinity(); - - // Set dischargingTime if it's available and valid, i.e. when on battery - // power. Otherwise leave the default value, which is +infinity. - if (on_battery_power) { - SInt64 discharging_time = - GetValueAsSInt64(description, CFSTR(kIOPSTimeToEmptyKey), -1); - if (discharging_time != -1) { - status->discharging_time = - base::TimeDelta::FromMinutes(discharging_time).InSeconds(); - } - } - } -} - -std::vector<mojom::BatteryStatus> GetInternalBatteriesStates() { - std::vector<mojom::BatteryStatus> internal_sources; - - base::ScopedCFTypeRef<CFTypeRef> info(IOPSCopyPowerSourcesInfo()); - base::ScopedCFTypeRef<CFArrayRef> power_sources_list( - IOPSCopyPowerSourcesList(info)); - CFIndex count = CFArrayGetCount(power_sources_list); - - for (CFIndex i = 0; i < count; ++i) { - CFDictionaryRef description = IOPSGetPowerSourceDescription(info, - CFArrayGetValueAtIndex(power_sources_list, i)); - - if (!description) - continue; - - CFStringRef transport_type = - base::mac::GetValueFromDictionary<CFStringRef>(description, - CFSTR(kIOPSTransportTypeKey)); - - bool internal_source = - CFStringsAreEqual(transport_type, CFSTR(kIOPSInternalType)); - bool source_present = - GetValueAsBoolean(description, CFSTR(kIOPSIsPresentKey), false); - - if (internal_source && source_present) { - mojom::BatteryStatus status; - FetchBatteryStatus(description, &status); - internal_sources.push_back(status); - } - } - - return internal_sources; -} - -void OnBatteryStatusChanged(const BatteryCallback& callback) { - std::vector<mojom::BatteryStatus> batteries(GetInternalBatteriesStates()); - - if (batteries.empty()) { - callback.Run(mojom::BatteryStatus()); - return; - } - - // TODO(timvolodine): implement the case when there are multiple internal - // sources, e.g. when multiple batteries are present. Currently this will - // fail a DCHECK. - DCHECK(batteries.size() == 1); - callback.Run(batteries.front()); -} - -class BatteryStatusObserver { - public: - explicit BatteryStatusObserver(const BatteryCallback& callback) - : callback_(callback) {} - - ~BatteryStatusObserver() { DCHECK(!notifier_run_loop_source_); } - - void Start() { - if (notifier_run_loop_source_) - return; - - notifier_run_loop_source_.reset( - IOPSNotificationCreateRunLoopSource(CallOnBatteryStatusChanged, - static_cast<void*>(&callback_))); - if (!notifier_run_loop_source_) { - LOG(ERROR) << "Failed to create battery status notification run loop"; - // Make sure to execute to callback with the default values. - callback_.Run(mojom::BatteryStatus()); - return; - } - - CallOnBatteryStatusChanged(static_cast<void*>(&callback_)); - CFRunLoopAddSource(CFRunLoopGetCurrent(), notifier_run_loop_source_, - kCFRunLoopDefaultMode); - UpdateNumberBatteriesHistogram(GetInternalBatteriesStates().size()); - } - - void Stop() { - if (!notifier_run_loop_source_) - return; - - CFRunLoopRemoveSource(CFRunLoopGetCurrent(), notifier_run_loop_source_, - kCFRunLoopDefaultMode); - notifier_run_loop_source_.reset(); - } - - private: - static void CallOnBatteryStatusChanged(void* callback) { - OnBatteryStatusChanged(*static_cast<BatteryCallback*>(callback)); - } - - BatteryCallback callback_; - base::ScopedCFTypeRef<CFRunLoopSourceRef> notifier_run_loop_source_; - - DISALLOW_COPY_AND_ASSIGN(BatteryStatusObserver); -}; - -class BatteryStatusManagerMac : public BatteryStatusManager { - public: - explicit BatteryStatusManagerMac(const BatteryCallback& callback) - : notifier_(new BatteryStatusObserver(callback)) {} - - ~BatteryStatusManagerMac() override { notifier_->Stop(); } - - // BatteryStatusManager: - bool StartListeningBatteryChange() override { - notifier_->Start(); - return true; - } - - void StopListeningBatteryChange() override { - notifier_->Stop(); - } - - private: - std::unique_ptr<BatteryStatusObserver> notifier_; - - DISALLOW_COPY_AND_ASSIGN(BatteryStatusManagerMac); -}; - -} // end namespace - -// static -std::unique_ptr<BatteryStatusManager> BatteryStatusManager::Create( - const BatteryStatusService::BatteryUpdateCallback& callback) { - return std::unique_ptr<BatteryStatusManager>( - new BatteryStatusManagerMac(callback)); -} - -} // namespace device diff --git a/chromium/device/battery/battery_status_manager_win.cc b/chromium/device/battery/battery_status_manager_win.cc deleted file mode 100644 index 9bc8ad5c6e2..00000000000 --- a/chromium/device/battery/battery_status_manager_win.cc +++ /dev/null @@ -1,217 +0,0 @@ -// 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 "device/battery/battery_status_manager_win.h" - -#include <memory> - -#include "base/bind.h" -#include "base/macros.h" -#include "base/metrics/histogram_macros.h" -#include "base/strings/string16.h" -#include "base/win/message_window.h" -#include "base/win/windows_version.h" -#include "device/battery/battery_status_manager.h" - -namespace device { - -namespace { - -typedef BatteryStatusService::BatteryUpdateCallback BatteryCallback; - -const wchar_t kWindowClassName[] = L"BatteryStatusMessageWindow"; - -// This enum is used for histogram. Don't change the order of the existing -// values. -enum NumberBatteriesType { - UNKNOWN_BATTERIES = 0, - NO_BATTERY = 1, - ONE_OR_MORE_BATTERIES = 2, - BATTERY_TYPES_COUNT = 3, -}; - -void UpdateNumberBatteriesHistogram(NumberBatteriesType count) { - UMA_HISTOGRAM_ENUMERATION("BatteryStatus.NumberBatteriesWin", - count, - BATTERY_TYPES_COUNT); -} - -void UpdateNumberBatteriesHistogram() { - SYSTEM_POWER_STATUS win_status; - if (!GetSystemPowerStatus(&win_status)) { - UpdateNumberBatteriesHistogram(UNKNOWN_BATTERIES); - return; - } - - if (win_status.BatteryFlag == 255) - UpdateNumberBatteriesHistogram(UNKNOWN_BATTERIES); - else if (win_status.BatteryFlag == 128) - UpdateNumberBatteriesHistogram(NO_BATTERY); - else - UpdateNumberBatteriesHistogram(ONE_OR_MORE_BATTERIES); -} - -// Message-only window for handling battery changes on Windows. -class BatteryStatusObserver { - public: - explicit BatteryStatusObserver(const BatteryCallback& callback) - : power_handle_(NULL), - battery_change_handle_(NULL), - callback_(callback) { - } - - ~BatteryStatusObserver() { DCHECK(!window_); } - - void Start() { - if (CreateMessageWindow()) { - BatteryChanged(); - // RegisterPowerSettingNotification function work from Windows Vista - // onwards. However even without them we will receive notifications, - // e.g. when a power source is connected. - // TODO(timvolodine) : consider polling for battery changes on windows - // versions prior to Vista, see crbug.com/402466. - power_handle_ = - RegisterNotification(&GUID_ACDC_POWER_SOURCE); - battery_change_handle_ = - RegisterNotification(&GUID_BATTERY_PERCENTAGE_REMAINING); - } else { - // Could not create a message window, execute callback with the default - // values. - callback_.Run(mojom::BatteryStatus()); - } - - UpdateNumberBatteriesHistogram(); - } - - void Stop() { - if (power_handle_) { - UnregisterNotification(power_handle_); - power_handle_ = NULL; - } - if (battery_change_handle_) { - UnregisterNotification(battery_change_handle_); - battery_change_handle_ = NULL; - } - window_.reset(); - } - - private: - void BatteryChanged() { - SYSTEM_POWER_STATUS win_status; - if (GetSystemPowerStatus(&win_status)) - callback_.Run(ComputeWebBatteryStatus(win_status)); - else - callback_.Run(mojom::BatteryStatus()); - } - - bool HandleMessage(UINT message, - WPARAM wparam, - LPARAM lparam, - LRESULT* result) { - switch(message) { - case WM_POWERBROADCAST: - if (wparam == PBT_APMPOWERSTATUSCHANGE || - wparam == PBT_POWERSETTINGCHANGE) { - BatteryChanged(); - } - *result = NULL; - return true; - default: - return false; - } - } - - HPOWERNOTIFY RegisterNotification(LPCGUID power_setting) { - if (base::win::GetVersion() < base::win::VERSION_VISTA) - return NULL; - - return RegisterPowerSettingNotification(window_->hwnd(), power_setting, - DEVICE_NOTIFY_WINDOW_HANDLE); - } - - BOOL UnregisterNotification(HPOWERNOTIFY handle) { - if (base::win::GetVersion() < base::win::VERSION_VISTA) - return FALSE; - - return UnregisterPowerSettingNotification(handle); - } - - bool CreateMessageWindow() { - // TODO(timvolodine): consider reusing the message window of PowerMonitor. - window_.reset(new base::win::MessageWindow()); - if (!window_->CreateNamed(base::Bind(&BatteryStatusObserver::HandleMessage, - base::Unretained(this)), - base::string16(kWindowClassName))) { - LOG(ERROR) << "Failed to create message window: " << kWindowClassName; - window_.reset(); - return false; - } - return true; - } - - HPOWERNOTIFY power_handle_; - HPOWERNOTIFY battery_change_handle_; - BatteryCallback callback_; - std::unique_ptr<base::win::MessageWindow> window_; - - DISALLOW_COPY_AND_ASSIGN(BatteryStatusObserver); -}; - -class BatteryStatusManagerWin : public BatteryStatusManager { - public: - explicit BatteryStatusManagerWin(const BatteryCallback& callback) - : battery_observer_(new BatteryStatusObserver(callback)) {} - ~BatteryStatusManagerWin() override { battery_observer_->Stop(); } - - public: - // BatteryStatusManager: - bool StartListeningBatteryChange() override { - battery_observer_->Start(); - return true; - } - - void StopListeningBatteryChange() override { battery_observer_->Stop(); } - - private: - std::unique_ptr<BatteryStatusObserver> battery_observer_; - - DISALLOW_COPY_AND_ASSIGN(BatteryStatusManagerWin); -}; - -} // namespace - -mojom::BatteryStatus ComputeWebBatteryStatus( - const SYSTEM_POWER_STATUS& win_status) { - mojom::BatteryStatus status; - status.charging = win_status.ACLineStatus != WIN_AC_LINE_STATUS_OFFLINE; - - // Set level if available. Otherwise keep the default value which is 1. - if (win_status.BatteryLifePercent != 255) { - // Convert percentage to a value between 0 and 1 with 2 significant digits. - status.level = static_cast<double>(win_status.BatteryLifePercent) / 100.; - } - - if (!status.charging) { - // Set discharging_time if available otherwise keep the default value, - // which is +Infinity. - if (win_status.BatteryLifeTime != (DWORD)-1) - status.discharging_time = win_status.BatteryLifeTime; - status.charging_time = std::numeric_limits<double>::infinity(); - } else { - // Set charging_time to +Infinity if not fully charged, otherwise leave the - // default value, which is 0. - if (status.level < 1) - status.charging_time = std::numeric_limits<double>::infinity(); - } - return status; -} - -// static -std::unique_ptr<BatteryStatusManager> BatteryStatusManager::Create( - const BatteryStatusService::BatteryUpdateCallback& callback) { - return std::unique_ptr<BatteryStatusManager>( - new BatteryStatusManagerWin(callback)); -} - -} // namespace device diff --git a/chromium/device/battery/battery_status_manager_win.h b/chromium/device/battery/battery_status_manager_win.h deleted file mode 100644 index cb53f1cc6cf..00000000000 --- a/chromium/device/battery/battery_status_manager_win.h +++ /dev/null @@ -1,26 +0,0 @@ -// 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 DEVICE_BATTERY_BATTERY_STATUS_MANAGER_WIN_H_ -#define DEVICE_BATTERY_BATTERY_STATUS_MANAGER_WIN_H_ - -#include <windows.h> -#include "device/battery/battery_export.h" -#include "device/battery/battery_status.mojom.h" - -namespace device { - -enum WinACLineStatus { - WIN_AC_LINE_STATUS_OFFLINE = 0, - WIN_AC_LINE_STATUS_ONLINE = 1, - WIN_AC_LINE_STATUS_UNKNOWN = 255, -}; - -// Returns WebBatteryStatus corresponding to the given SYSTEM_POWER_STATUS. -DEVICE_BATTERY_EXPORT mojom::BatteryStatus ComputeWebBatteryStatus( - const SYSTEM_POWER_STATUS& win_status); - -} // namespace device - -#endif // DEVICE_BATTERY_BATTERY_STATUS_MANAGER_WIN_H_ diff --git a/chromium/device/battery/battery_status_manager_win_unittest.cc b/chromium/device/battery/battery_status_manager_win_unittest.cc deleted file mode 100644 index 17d1c02a245..00000000000 --- a/chromium/device/battery/battery_status_manager_win_unittest.cc +++ /dev/null @@ -1,80 +0,0 @@ -// 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 "device/battery/battery_status_manager_win.h" - -#include "testing/gtest/include/gtest/gtest.h" - -namespace device { - -namespace { - -TEST(BatteryStatusManagerWinTest, ACLineStatusOffline) { - SYSTEM_POWER_STATUS win_status; - win_status.ACLineStatus = WIN_AC_LINE_STATUS_OFFLINE; - win_status.BatteryLifePercent = 100; - win_status.BatteryLifeTime = 200; - - mojom::BatteryStatus status = ComputeWebBatteryStatus(win_status); - EXPECT_FALSE(status.charging); - EXPECT_EQ(std::numeric_limits<double>::infinity(), status.charging_time); - EXPECT_EQ(200, status.discharging_time); - EXPECT_EQ(1, status.level); -} - -TEST(BatteryStatusManagerWinTest, ACLineStatusOfflineDischargingTimeUnknown) { - SYSTEM_POWER_STATUS win_status; - win_status.ACLineStatus = WIN_AC_LINE_STATUS_OFFLINE; - win_status.BatteryLifePercent = 100; - win_status.BatteryLifeTime = (DWORD)-1; - - mojom::BatteryStatus status = ComputeWebBatteryStatus(win_status); - EXPECT_FALSE(status.charging); - EXPECT_EQ(std::numeric_limits<double>::infinity(), status.charging_time); - EXPECT_EQ(std::numeric_limits<double>::infinity(), status.discharging_time); - EXPECT_EQ(1, status.level); -} - -TEST(BatteryStatusManagerWinTest, ACLineStatusOnline) { - SYSTEM_POWER_STATUS win_status; - win_status.ACLineStatus = WIN_AC_LINE_STATUS_ONLINE; - win_status.BatteryLifePercent = 50; - win_status.BatteryLifeTime = 200; - - mojom::BatteryStatus status = ComputeWebBatteryStatus(win_status); - EXPECT_TRUE(status.charging); - EXPECT_EQ(std::numeric_limits<double>::infinity(), status.charging_time); - EXPECT_EQ(std::numeric_limits<double>::infinity(), status.discharging_time); - EXPECT_EQ(.5, status.level); -} - -TEST(BatteryStatusManagerWinTest, ACLineStatusOnlineFullBattery) { - SYSTEM_POWER_STATUS win_status; - win_status.ACLineStatus = WIN_AC_LINE_STATUS_ONLINE; - win_status.BatteryLifePercent = 100; - win_status.BatteryLifeTime = 200; - - mojom::BatteryStatus status = ComputeWebBatteryStatus(win_status); - EXPECT_TRUE(status.charging); - EXPECT_EQ(0, status.charging_time); - EXPECT_EQ(std::numeric_limits<double>::infinity(), status.discharging_time); - EXPECT_EQ(1, status.level); -} - -TEST(BatteryStatusManagerWinTest, ACLineStatusUnknown) { - SYSTEM_POWER_STATUS win_status; - win_status.ACLineStatus = WIN_AC_LINE_STATUS_UNKNOWN; - win_status.BatteryLifePercent = 50; - win_status.BatteryLifeTime = 200; - - mojom::BatteryStatus status = ComputeWebBatteryStatus(win_status); - EXPECT_TRUE(status.charging); - EXPECT_EQ(std::numeric_limits<double>::infinity(), status.charging_time); - EXPECT_EQ(std::numeric_limits<double>::infinity(), status.discharging_time); - EXPECT_EQ(.5, status.level); -} - -} // namespace - -} // namespace device diff --git a/chromium/device/battery/battery_status_service.cc b/chromium/device/battery/battery_status_service.cc deleted file mode 100644 index d46817b4af0..00000000000 --- a/chromium/device/battery/battery_status_service.cc +++ /dev/null @@ -1,110 +0,0 @@ -// 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 "device/battery/battery_status_service.h" - -#include <utility> - -#include "base/bind.h" -#include "base/location.h" -#include "base/single_thread_task_runner.h" -#include "base/threading/thread_task_runner_handle.h" -#include "device/battery/battery_monitor_impl.h" -#include "device/battery/battery_status_manager.h" - -namespace device { - -BatteryStatusService::BatteryStatusService() - : main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()), - update_callback_(base::Bind(&BatteryStatusService::NotifyConsumers, - base::Unretained(this))), - status_updated_(false), - is_shutdown_(false) { - callback_list_.set_removal_callback( - base::Bind(&BatteryStatusService::ConsumersChanged, - base::Unretained(this))); -} - -BatteryStatusService::~BatteryStatusService() { -} - -BatteryStatusService* BatteryStatusService::GetInstance() { - return base::Singleton< - BatteryStatusService, - base::LeakySingletonTraits<BatteryStatusService>>::get(); -} - -std::unique_ptr<BatteryStatusService::BatteryUpdateSubscription> -BatteryStatusService::AddCallback(const BatteryUpdateCallback& callback) { - DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); - DCHECK(!is_shutdown_); - - if (!battery_fetcher_) - battery_fetcher_ = BatteryStatusManager::Create(update_callback_); - - if (callback_list_.empty()) { - bool success = battery_fetcher_->StartListeningBatteryChange(); - // On failure pass the default values back. - if (!success) - callback.Run(mojom::BatteryStatus()); - } - - if (status_updated_) { - // Send recent status to the new callback if already available. - callback.Run(status_); - } - - return callback_list_.Add(callback); -} - -void BatteryStatusService::ConsumersChanged() { - if (is_shutdown_) - return; - - if (callback_list_.empty()) { - battery_fetcher_->StopListeningBatteryChange(); - status_updated_ = false; - } -} - -void BatteryStatusService::NotifyConsumers(const mojom::BatteryStatus& status) { - DCHECK(!is_shutdown_); - - main_thread_task_runner_->PostTask(FROM_HERE, base::Bind( - &BatteryStatusService::NotifyConsumersOnMainThread, - base::Unretained(this), - status)); -} - -void BatteryStatusService::NotifyConsumersOnMainThread( - const mojom::BatteryStatus& status) { - DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); - if (callback_list_.empty()) - return; - - status_ = status; - status_updated_ = true; - callback_list_.Notify(status_); -} - -void BatteryStatusService::Shutdown() { - if (!callback_list_.empty()) - battery_fetcher_->StopListeningBatteryChange(); - battery_fetcher_.reset(); - is_shutdown_ = true; -} - -const BatteryStatusService::BatteryUpdateCallback& -BatteryStatusService::GetUpdateCallbackForTesting() const { - return update_callback_; -} - -void BatteryStatusService::SetBatteryManagerForTesting( - std::unique_ptr<BatteryStatusManager> test_battery_manager) { - battery_fetcher_ = std::move(test_battery_manager); - status_ = mojom::BatteryStatus(); - status_updated_ = false; -} - -} // namespace device diff --git a/chromium/device/battery/battery_status_service.h b/chromium/device/battery/battery_status_service.h deleted file mode 100644 index bcdfd4becd4..00000000000 --- a/chromium/device/battery/battery_status_service.h +++ /dev/null @@ -1,76 +0,0 @@ -// 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 DEVICE_BATTERY_BATTERY_STATUS_SERVICE_H_ -#define DEVICE_BATTERY_BATTERY_STATUS_SERVICE_H_ - -#include <memory> - -#include "base/callback_list.h" -#include "base/macros.h" -#include "base/memory/singleton.h" -#include "device/battery/battery_export.h" -#include "device/battery/battery_status.mojom.h" - -namespace base { -class SingleThreadTaskRunner; -} - -namespace device { -class BatteryStatusManager; - -class DEVICE_BATTERY_EXPORT BatteryStatusService { - public: - typedef base::Callback<void(const mojom::BatteryStatus&)> - BatteryUpdateCallback; - typedef base::CallbackList<void(const mojom::BatteryStatus&)> - BatteryUpdateCallbackList; - typedef BatteryUpdateCallbackList::Subscription BatteryUpdateSubscription; - - // Returns the BatteryStatusService singleton. - static BatteryStatusService* GetInstance(); - - // Adds a callback to receive battery status updates. Must be called on the - // main thread. The callback itself will be called on the main thread as well. - // NOTE: The callback may be run before AddCallback returns! - std::unique_ptr<BatteryUpdateSubscription> AddCallback( - const BatteryUpdateCallback& callback); - - // Gracefully clean-up. - void Shutdown(); - - // Injects a custom battery status manager for testing purposes. - void SetBatteryManagerForTesting( - std::unique_ptr<BatteryStatusManager> test_battery_manager); - - // Returns callback to invoke when battery is changed. Used for testing. - const BatteryUpdateCallback& GetUpdateCallbackForTesting() const; - - private: - friend struct base::DefaultSingletonTraits<BatteryStatusService>; - friend class BatteryStatusServiceTest; - - BatteryStatusService(); - virtual ~BatteryStatusService(); - - // Updates current battery status and sends new status to interested - // render processes. Can be called on any thread via a callback. - void NotifyConsumers(const mojom::BatteryStatus& status); - void NotifyConsumersOnMainThread(const mojom::BatteryStatus& status); - void ConsumersChanged(); - - scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_; - std::unique_ptr<BatteryStatusManager> battery_fetcher_; - BatteryUpdateCallbackList callback_list_; - BatteryUpdateCallback update_callback_; - mojom::BatteryStatus status_; - bool status_updated_; - bool is_shutdown_; - - DISALLOW_COPY_AND_ASSIGN(BatteryStatusService); -}; - -} // namespace device - -#endif // DEVICE_BATTERY_BATTERY_STATUS_SERVICE_H_ diff --git a/chromium/device/battery/battery_status_service_unittest.cc b/chromium/device/battery/battery_status_service_unittest.cc deleted file mode 100644 index a9a964267d5..00000000000 --- a/chromium/device/battery/battery_status_service_unittest.cc +++ /dev/null @@ -1,192 +0,0 @@ -// 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 "device/battery/battery_status_service.h" - -#include <memory> -#include <utility> - -#include "base/bind.h" -#include "base/macros.h" -#include "base/message_loop/message_loop.h" -#include "base/run_loop.h" -#include "device/battery/battery_status_manager.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace device { - -namespace { - -class FakeBatteryManager : public BatteryStatusManager { - public: - explicit FakeBatteryManager( - const BatteryStatusService::BatteryUpdateCallback& callback) - : callback_(callback), start_invoked_count_(0), stop_invoked_count_(0) {} - ~FakeBatteryManager() override {} - - // Methods from Battery Status Manager - bool StartListeningBatteryChange() override { - start_invoked_count_++; - return true; - } - - void StopListeningBatteryChange() override { stop_invoked_count_++; } - - void InvokeUpdateCallback(const mojom::BatteryStatus& status) { - callback_.Run(status); - } - - int start_invoked_count() const { return start_invoked_count_; } - int stop_invoked_count() const { return stop_invoked_count_; } - - private: - BatteryStatusService::BatteryUpdateCallback callback_; - int start_invoked_count_; - int stop_invoked_count_; - - DISALLOW_COPY_AND_ASSIGN(FakeBatteryManager); -}; - -} // namespace - -class BatteryStatusServiceTest : public testing::Test { - public: - BatteryStatusServiceTest() - : battery_manager_(nullptr), - callback1_invoked_count_(0), - callback2_invoked_count_(0) {} - ~BatteryStatusServiceTest() override {} - - protected: - typedef BatteryStatusService::BatteryUpdateSubscription BatterySubscription; - - void SetUp() override { - callback1_ = base::Bind(&BatteryStatusServiceTest::Callback1, - base::Unretained(this)); - callback2_ = base::Bind(&BatteryStatusServiceTest::Callback2, - base::Unretained(this)); - - // We keep a raw pointer to the FakeBatteryManager, which we expect to - // remain valid for the lifetime of the BatteryStatusService. - std::unique_ptr<FakeBatteryManager> battery_manager( - new FakeBatteryManager(battery_service_.GetUpdateCallbackForTesting())); - battery_manager_ = battery_manager.get(); - - battery_service_.SetBatteryManagerForTesting(std::move(battery_manager)); - } - - void TearDown() override { - base::RunLoop().RunUntilIdle(); - } - - FakeBatteryManager* battery_manager() { - return battery_manager_; - } - - std::unique_ptr<BatterySubscription> AddCallback( - const BatteryStatusService::BatteryUpdateCallback& callback) { - return battery_service_.AddCallback(callback); - } - - int callback1_invoked_count() const { - return callback1_invoked_count_; - } - - int callback2_invoked_count() const { - return callback2_invoked_count_; - } - - const mojom::BatteryStatus& battery_status() const { return battery_status_; } - - const BatteryStatusService::BatteryUpdateCallback& callback1() const { - return callback1_; - } - - const BatteryStatusService::BatteryUpdateCallback& callback2() const { - return callback2_; - } - - private: - void Callback1(const mojom::BatteryStatus& status) { - callback1_invoked_count_++; - battery_status_ = status; - } - - void Callback2(const mojom::BatteryStatus& status) { - callback2_invoked_count_++; - battery_status_ = status; - } - - base::MessageLoop message_loop_; - BatteryStatusService battery_service_; - FakeBatteryManager* battery_manager_; - BatteryStatusService::BatteryUpdateCallback callback1_; - BatteryStatusService::BatteryUpdateCallback callback2_; - int callback1_invoked_count_; - int callback2_invoked_count_; - mojom::BatteryStatus battery_status_; - - DISALLOW_COPY_AND_ASSIGN(BatteryStatusServiceTest); -}; - -TEST_F(BatteryStatusServiceTest, AddFirstCallback) { - std::unique_ptr<BatterySubscription> subscription1 = AddCallback(callback1()); - EXPECT_EQ(1, battery_manager()->start_invoked_count()); - EXPECT_EQ(0, battery_manager()->stop_invoked_count()); - subscription1.reset(); - EXPECT_EQ(1, battery_manager()->start_invoked_count()); - EXPECT_EQ(1, battery_manager()->stop_invoked_count()); -} - -TEST_F(BatteryStatusServiceTest, AddCallbackAfterUpdate) { - std::unique_ptr<BatterySubscription> subscription1 = AddCallback(callback1()); - mojom::BatteryStatus status; - battery_manager()->InvokeUpdateCallback(status); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(1, callback1_invoked_count()); - EXPECT_EQ(0, callback2_invoked_count()); - - std::unique_ptr<BatterySubscription> subscription2 = AddCallback(callback2()); - EXPECT_EQ(1, callback1_invoked_count()); - EXPECT_EQ(1, callback2_invoked_count()); -} - -TEST_F(BatteryStatusServiceTest, TwoCallbacksUpdate) { - std::unique_ptr<BatterySubscription> subscription1 = AddCallback(callback1()); - std::unique_ptr<BatterySubscription> subscription2 = AddCallback(callback2()); - - mojom::BatteryStatus status; - status.charging = true; - status.charging_time = 100; - status.discharging_time = 200; - status.level = 0.5; - battery_manager()->InvokeUpdateCallback(status); - base::RunLoop().RunUntilIdle(); - - EXPECT_EQ(1, callback1_invoked_count()); - EXPECT_EQ(1, callback2_invoked_count()); - EXPECT_EQ(status.charging, battery_status().charging); - EXPECT_EQ(status.charging_time, battery_status().charging_time); - EXPECT_EQ(status.discharging_time, battery_status().discharging_time); - EXPECT_EQ(status.level, battery_status().level); -} - -TEST_F(BatteryStatusServiceTest, RemoveOneCallback) { - std::unique_ptr<BatterySubscription> subscription1 = AddCallback(callback1()); - std::unique_ptr<BatterySubscription> subscription2 = AddCallback(callback2()); - - mojom::BatteryStatus status; - battery_manager()->InvokeUpdateCallback(status); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(1, callback1_invoked_count()); - EXPECT_EQ(1, callback2_invoked_count()); - - subscription1.reset(); - battery_manager()->InvokeUpdateCallback(status); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(1, callback1_invoked_count()); - EXPECT_EQ(2, callback2_invoked_count()); -} - -} // namespace device diff --git a/chromium/device/bluetooth/BUILD.gn b/chromium/device/bluetooth/BUILD.gn index ea00f55614e..f4e2b6c6c34 100644 --- a/chromium/device/bluetooth/BUILD.gn +++ b/chromium/device/bluetooth/BUILD.gn @@ -41,6 +41,23 @@ source_set("mojo") { ] } +source_set("fake_bluetooth") { + sources = [ + "test/fake_bluetooth.cc", + "test/fake_bluetooth.h", + "test/fake_central.cc", + "test/fake_central.h", + "test/fake_peripheral.cc", + "test/fake_peripheral.h", + ] + + deps = [ + ":bluetooth", + "//device/bluetooth/public/interfaces:fake_bluetooth_interfaces", + "//mojo/public/cpp/bindings", + ] +} + component("bluetooth") { sources = [ "android/bluetooth_jni_registrar.cc", diff --git a/chromium/device/bluetooth/OWNERS b/chromium/device/bluetooth/OWNERS index 77d6b7d2e0e..778c9dfdb75 100644 --- a/chromium/device/bluetooth/OWNERS +++ b/chromium/device/bluetooth/OWNERS @@ -1,6 +1,9 @@ ortuno@chromium.org scheib@chromium.org +# For changes related to Chrome OS. +rkc@chromium.org + per-file *.gyp*=* per-file BUILD.gn=* diff --git a/chromium/device/bluetooth/README.md b/chromium/device/bluetooth/README.md index f3c0ed8939f..a2f3b1acec0 100644 --- a/chromium/device/bluetooth/README.md +++ b/chromium/device/bluetooth/README.md @@ -44,56 +44,6 @@ Known future work is tracked in the [Refactoring meta issue](https://crbug.com/580406). -## Testing - -Implementation of the Bluetooth component is tested via unittests. Client code -uses Mock Bluetooth objects: - - -### Cross Platform Unit Tests - -New feature development uses cross platform unit tests. This reduces test code -redundancy and produces consistency across all implementations. - -Unit tests operate at the public `device/bluetooth` API layer and the -`BluetoothTest` fixture controls fake operating system behavior as close to the -platfom as possible. The resulting test coverage spans the cross platform API, -common implementation, and platform specific implementation as close to -operating system APIs as possible. - -`test/bluetooth_test.h` defines the cross platform test fixture -`BluetoothTestBase`. Platform implementations provide subclasses, such as -`test/bluetooth_test_android.h` and typedef to the name `BluetoothTest`. - -[More testing information](https://docs.google.com/document/d/1mBipxn1sJu6jMqP0RQZpkYXC1o601bzLCpCxwTA2yGA/edit?usp=sharing) - -### Legacy Platform Specific Unit Tests - -Early code (Classic on most platforms, and Low Energy on BlueZ) was tested with -platform specific unit tests, e.g. `bluetooth_bluez_unittest.cc` & -`bluetooth_adapter_win_unittest.cc`. The BlueZ style has platform specific -methods to create fake devices and the public API is used to interact with them. - -Maintenance of these earlier implementation featuress should update tests in -place. Long term these tests should be [refactored into cross platform -tests](https://crbug.com/580403). - - -### Mock Bluetooth Objects - -`test/mock_bluetooth_*` files provide GoogleMock based fake objects for use in -client code. - - -### Chrome OS Blueooth Controller Tests - -Bluetooth controller system tests generating radio signals are run and managed -by the Chrome OS team. See: -https://chromium.googlesource.com/chromiumos/third_party/autotest/+/master/server/site_tests/ -https://chromium.googlesource.com/chromiumos/third_party/autotest/+/master/server/cros/bluetooth/ -https://chromium.googlesource.com/chromiumos/third_party/autotest/+/master/client/cros/bluetooth/ - - ## Android The android implementation requires crossing from C++ to Java using @@ -131,6 +81,10 @@ See also: [Class Diagram of Web Bluetooth through Bluetooth Android][Class] [Class]: https://sites.google.com/a/chromium.org/dev/developers/design-documents/bluetooth-design-docs/web-bluetooth-through-bluetooth-android-class-diagram +## Testing +See [test/README.md](test/README.md) + + ## Design Documents * [Bluetooth Notifications](https://docs.google.com/document/d/1guBtAnQUP8ZoZre4VQGrjR5uX0ZYxfK-lwKNeqY0-z4/edit?usp=sharing) 2016-08-26 diff --git a/chromium/device/bluetooth/adapter.cc b/chromium/device/bluetooth/adapter.cc index 85a36183dbe..fb1f99988a1 100644 --- a/chromium/device/bluetooth/adapter.cc +++ b/chromium/device/bluetooth/adapter.cc @@ -26,23 +26,24 @@ Adapter::~Adapter() { } void Adapter::ConnectToDevice(const std::string& address, - const ConnectToDeviceCallback& callback) { + ConnectToDeviceCallback callback) { device::BluetoothDevice* device = adapter_->GetDevice(address); if (!device) { - callback.Run(mojom::ConnectResult::DEVICE_NO_LONGER_IN_RANGE, - nullptr /* device */); + std::move(callback).Run(mojom::ConnectResult::DEVICE_NO_LONGER_IN_RANGE, + nullptr /* device */); return; } + auto copyable_callback = base::AdaptCallbackForRepeating(std::move(callback)); device->CreateGattConnection( base::Bind(&Adapter::OnGattConnected, weak_ptr_factory_.GetWeakPtr(), - callback), + copyable_callback), base::Bind(&Adapter::OnConnectError, weak_ptr_factory_.GetWeakPtr(), - callback)); + copyable_callback)); } -void Adapter::GetDevices(const GetDevicesCallback& callback) { +void Adapter::GetDevices(GetDevicesCallback callback) { std::vector<mojom::DeviceInfoPtr> devices; for (const device::BluetoothDevice* device : adapter_->GetDevices()) { @@ -51,10 +52,10 @@ void Adapter::GetDevices(const GetDevicesCallback& callback) { devices.push_back(std::move(device_info)); } - callback.Run(std::move(devices)); + std::move(callback).Run(std::move(devices)); } -void Adapter::GetInfo(const GetInfoCallback& callback) { +void Adapter::GetInfo(GetInfoCallback callback) { mojom::AdapterInfoPtr adapter_info = mojom::AdapterInfo::New(); adapter_info->address = adapter_->GetAddress(); adapter_info->name = adapter_->GetName(); @@ -63,20 +64,20 @@ void Adapter::GetInfo(const GetInfoCallback& callback) { adapter_info->powered = adapter_->IsPowered(); adapter_info->discoverable = adapter_->IsDiscoverable(); adapter_info->discovering = adapter_->IsDiscovering(); - callback.Run(std::move(adapter_info)); + std::move(callback).Run(std::move(adapter_info)); } void Adapter::SetClient(mojom::AdapterClientPtr client) { client_ = std::move(client); } -void Adapter::StartDiscoverySession( - const StartDiscoverySessionCallback& callback) { +void Adapter::StartDiscoverySession(StartDiscoverySessionCallback callback) { + auto copyable_callback = base::AdaptCallbackForRepeating(std::move(callback)); adapter_->StartDiscoverySession( base::Bind(&Adapter::OnStartDiscoverySession, - weak_ptr_factory_.GetWeakPtr(), callback), + weak_ptr_factory_.GetWeakPtr(), copyable_callback), base::Bind(&Adapter::OnDiscoverySessionError, - weak_ptr_factory_.GetWeakPtr(), callback)); + weak_ptr_factory_.GetWeakPtr(), copyable_callback)); } void Adapter::AdapterPresentChanged(device::BluetoothAdapter* adapter, @@ -128,34 +129,33 @@ void Adapter::DeviceRemoved(device::BluetoothAdapter* adapter, } void Adapter::OnGattConnected( - const ConnectToDeviceCallback& callback, + ConnectToDeviceCallback callback, std::unique_ptr<device::BluetoothGattConnection> connection) { mojom::DevicePtr device_ptr; Device::Create(adapter_, std::move(connection), mojo::MakeRequest(&device_ptr)); - callback.Run(mojom::ConnectResult::SUCCESS, std::move(device_ptr)); + std::move(callback).Run(mojom::ConnectResult::SUCCESS, std::move(device_ptr)); } void Adapter::OnConnectError( - const ConnectToDeviceCallback& callback, + ConnectToDeviceCallback callback, device::BluetoothDevice::ConnectErrorCode error_code) { - callback.Run(mojo::ConvertTo<mojom::ConnectResult>(error_code), - nullptr /* Device */); + std::move(callback).Run(mojo::ConvertTo<mojom::ConnectResult>(error_code), + nullptr /* Device */); } void Adapter::OnStartDiscoverySession( - const StartDiscoverySessionCallback& callback, + StartDiscoverySessionCallback callback, std::unique_ptr<device::BluetoothDiscoverySession> session) { mojom::DiscoverySessionPtr session_ptr; mojo::MakeStrongBinding( base::MakeUnique<DiscoverySession>(std::move(session)), mojo::MakeRequest(&session_ptr)); - callback.Run(std::move(session_ptr)); + std::move(callback).Run(std::move(session_ptr)); } -void Adapter::OnDiscoverySessionError( - const StartDiscoverySessionCallback& callback) { - callback.Run(nullptr /* session */); +void Adapter::OnDiscoverySessionError(StartDiscoverySessionCallback callback) { + std::move(callback).Run(nullptr /* session */); } } // namespace bluetooth diff --git a/chromium/device/bluetooth/adapter.h b/chromium/device/bluetooth/adapter.h index 6fc2de9a44f..8a081bf3dc0 100644 --- a/chromium/device/bluetooth/adapter.h +++ b/chromium/device/bluetooth/adapter.h @@ -29,12 +29,11 @@ class Adapter : public mojom::Adapter, // mojom::Adapter overrides: void ConnectToDevice(const std::string& address, - const ConnectToDeviceCallback& callback) override; - void GetDevices(const GetDevicesCallback& callback) override; - void GetInfo(const GetInfoCallback& callback) override; + ConnectToDeviceCallback callback) override; + void GetDevices(GetDevicesCallback callback) override; + void GetInfo(GetInfoCallback callback) override; void SetClient(mojom::AdapterClientPtr client) override; - void StartDiscoverySession( - const StartDiscoverySessionCallback& callback) override; + void StartDiscoverySession(StartDiscoverySessionCallback callback) override; // device::BluetoothAdapter::Observer overrides: void AdapterPresentChanged(device::BluetoothAdapter* adapter, @@ -54,17 +53,17 @@ class Adapter : public mojom::Adapter, private: void OnGattConnected( - const ConnectToDeviceCallback& callback, + ConnectToDeviceCallback callback, std::unique_ptr<device::BluetoothGattConnection> connection); - void OnConnectError(const ConnectToDeviceCallback& callback, + void OnConnectError(ConnectToDeviceCallback callback, device::BluetoothDevice::ConnectErrorCode error_code); void OnStartDiscoverySession( - const StartDiscoverySessionCallback& callback, + StartDiscoverySessionCallback callback, std::unique_ptr<device::BluetoothDiscoverySession> session); - void OnDiscoverySessionError(const StartDiscoverySessionCallback& callback); + void OnDiscoverySessionError(StartDiscoverySessionCallback callback); // The current Bluetooth adapter. scoped_refptr<device::BluetoothAdapter> adapter_; diff --git a/chromium/device/bluetooth/adapter_factory.cc b/chromium/device/bluetooth/adapter_factory.cc index 9eabd2d3bb8..423385fd846 100644 --- a/chromium/device/bluetooth/adapter_factory.cc +++ b/chromium/device/bluetooth/adapter_factory.cc @@ -16,28 +16,29 @@ AdapterFactory::AdapterFactory() : weak_ptr_factory_(this) {} AdapterFactory::~AdapterFactory() {} // static -void AdapterFactory::Create(mojom::AdapterFactoryRequest request) { +void AdapterFactory::Create(const service_manager::BindSourceInfo& source_info, + mojom::AdapterFactoryRequest request) { mojo::MakeStrongBinding(base::MakeUnique<AdapterFactory>(), std::move(request)); } -void AdapterFactory::GetAdapter(const GetAdapterCallback& callback) { - if (device::BluetoothAdapterFactory::IsBluetoothAdapterAvailable()) { +void AdapterFactory::GetAdapter(GetAdapterCallback callback) { + if (device::BluetoothAdapterFactory::IsBluetoothSupported()) { device::BluetoothAdapterFactory::GetAdapter( base::Bind(&AdapterFactory::OnGetAdapter, - weak_ptr_factory_.GetWeakPtr(), callback)); + weak_ptr_factory_.GetWeakPtr(), base::Passed(&callback))); } else { - callback.Run(nullptr /* AdapterPtr */); + std::move(callback).Run(nullptr /* AdapterPtr */); } } void AdapterFactory::OnGetAdapter( - const GetAdapterCallback& callback, + GetAdapterCallback callback, scoped_refptr<device::BluetoothAdapter> adapter) { mojom::AdapterPtr adapter_ptr; mojo::MakeStrongBinding(base::MakeUnique<Adapter>(adapter), mojo::MakeRequest(&adapter_ptr)); - callback.Run(std::move(adapter_ptr)); + std::move(callback).Run(std::move(adapter_ptr)); } } // namespace bluetooth diff --git a/chromium/device/bluetooth/adapter_factory.h b/chromium/device/bluetooth/adapter_factory.h index a7f1d2dfd8b..4f0e605751b 100644 --- a/chromium/device/bluetooth/adapter_factory.h +++ b/chromium/device/bluetooth/adapter_factory.h @@ -9,6 +9,10 @@ #include "device/bluetooth/bluetooth_adapter.h" #include "device/bluetooth/public/interfaces/adapter.mojom.h" +namespace service_manager { +struct BindSourceInfo; +} + namespace bluetooth { // Implementation of Mojo AdapterFactory located in @@ -22,13 +26,14 @@ class AdapterFactory : public mojom::AdapterFactory { ~AdapterFactory() override; // Creates an AdapterFactory with a strong Mojo binding to |request|. - static void Create(mojom::AdapterFactoryRequest request); + static void Create(const service_manager::BindSourceInfo& source_info, + mojom::AdapterFactoryRequest request); // mojom::AdapterFactory overrides: - void GetAdapter(const GetAdapterCallback& callback) override; + void GetAdapter(GetAdapterCallback callback) override; private: - void OnGetAdapter(const GetAdapterCallback& callback, + void OnGetAdapter(GetAdapterCallback callback, scoped_refptr<device::BluetoothAdapter> adapter); base::WeakPtrFactory<AdapterFactory> weak_ptr_factory_; diff --git a/chromium/device/bluetooth/android/wrappers.cc b/chromium/device/bluetooth/android/wrappers.cc index 4ad3bc2e9a7..5a93f74532a 100644 --- a/chromium/device/bluetooth/android/wrappers.cc +++ b/chromium/device/bluetooth/android/wrappers.cc @@ -4,7 +4,6 @@ #include "device/bluetooth/android/wrappers.h" -#include "base/android/context_utils.h" #include "base/android/jni_android.h" #include "jni/Wrappers_jni.h" @@ -15,7 +14,7 @@ namespace device { ScopedJavaLocalRef<jobject> BluetoothAdapterWrapper_CreateWithDefaultAdapter() { return Java_BluetoothAdapterWrapper_createWithDefaultAdapter( - AttachCurrentThread(), base::android::GetApplicationContext()); + AttachCurrentThread()); } } // namespace device diff --git a/chromium/device/bluetooth/bluetooth_adapter_factory.cc b/chromium/device/bluetooth/bluetooth_adapter_factory.cc index ed64ecd2ee6..cee5e1dce10 100644 --- a/chromium/device/bluetooth/bluetooth_adapter_factory.cc +++ b/chromium/device/bluetooth/bluetooth_adapter_factory.cc @@ -8,6 +8,7 @@ #include "base/bind.h" #include "base/lazy_instance.h" +#include "base/memory/ptr_util.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "build/build_config.h" @@ -16,11 +17,20 @@ #if defined(OS_MACOSX) #include "base/mac/mac_util.h" #endif +#if defined(OS_WIN) +#include "base/win/windows_version.h" +#endif +#if defined(ANDROID) +#include "base/android/build_info.h" +#endif namespace device { namespace { +static base::LazyInstance<BluetoothAdapterFactory>::Leaky g_singleton = + LAZY_INSTANCE_INITIALIZER; + // Shared default adapter instance. We don't want to keep this class around // if nobody is using it, so use a WeakPtr and create the object when needed. // Since Google C++ Style (and clang's static analyzer) forbids us having @@ -53,8 +63,15 @@ void RunAdapterCallbacks() { } // namespace +BluetoothAdapterFactory::~BluetoothAdapterFactory() {} + // static -bool BluetoothAdapterFactory::IsBluetoothAdapterAvailable() { +BluetoothAdapterFactory& BluetoothAdapterFactory::Get() { + return g_singleton.Get(); +} + +// static +bool BluetoothAdapterFactory::IsBluetoothSupported() { // SetAdapterForTesting() may be used to provide a test or mock adapter // instance even on platforms that would otherwise not support it. if (default_adapter.Get()) @@ -67,28 +84,31 @@ bool BluetoothAdapterFactory::IsBluetoothAdapterAvailable() { #endif } -// static -bool BluetoothAdapterFactory::IsLowEnergyAvailable() { - DCHECK(IsBluetoothAdapterAvailable()); +bool BluetoothAdapterFactory::IsLowEnergySupported() { + if (values_for_testing_) { + return values_for_testing_->GetLESupported(); + } - // SetAdapterForTesting() may be used to provide a test or mock adapter - // instance even on platforms that would otherwise not support it. - if (default_adapter.Get()) - return true; -#if defined(OS_ANDROID) || defined(OS_CHROMEOS) || defined(OS_WIN) || \ - defined(OS_LINUX) - return true; +#if defined(OS_ANDROID) + return base::android::BuildInfo::GetInstance()->sdk_int() >= + base::android::SDK_VERSION_MARSHMALLOW; +#elif defined(OS_WIN) + // Windows 8 supports Low Energy GATT operations but it does not support + // scanning, initiating connections and GATT Server. To keep the API + // consistent we consider Windows 8 as lacking Low Energy support. + return base::win::GetVersion() >= base::win::VERSION_WIN10; #elif defined(OS_MACOSX) return base::mac::IsAtLeastOS10_10(); +#elif defined(OS_LINUX) || defined(OS_CHROMEOS) + return true; #else return false; -#endif // defined(OS_ANDROID) || defined(OS_CHROMEOS) || defined(OS_WIN) || - // defined(OS_LINUX) +#endif } // static void BluetoothAdapterFactory::GetAdapter(const AdapterCallback& callback) { - DCHECK(IsBluetoothAdapterAvailable()); + DCHECK(IsBluetoothSupported()); #if defined(OS_WIN) || defined(OS_LINUX) || defined(OS_CHROMEOS) if (!default_adapter.Get()) { @@ -131,4 +151,23 @@ bool BluetoothAdapterFactory::HasSharedInstanceForTesting() { return default_adapter.Get() != nullptr; } +BluetoothAdapterFactory::GlobalValuesForTesting::GlobalValuesForTesting() + : weak_ptr_factory_(this) {} + +BluetoothAdapterFactory::GlobalValuesForTesting::~GlobalValuesForTesting() {} + +base::WeakPtr<BluetoothAdapterFactory::GlobalValuesForTesting> +BluetoothAdapterFactory::GlobalValuesForTesting::GetWeakPtr() { + return weak_ptr_factory_.GetWeakPtr(); +} + +std::unique_ptr<BluetoothAdapterFactory::GlobalValuesForTesting> +BluetoothAdapterFactory::InitGlobalValuesForTesting() { + auto v = base::MakeUnique<BluetoothAdapterFactory::GlobalValuesForTesting>(); + values_for_testing_ = v->GetWeakPtr(); + return v; +} + +BluetoothAdapterFactory::BluetoothAdapterFactory() {} + } // namespace device diff --git a/chromium/device/bluetooth/bluetooth_adapter_factory.h b/chromium/device/bluetooth/bluetooth_adapter_factory.h index ab800db0b63..16f845703af 100644 --- a/chromium/device/bluetooth/bluetooth_adapter_factory.h +++ b/chromium/device/bluetooth/bluetooth_adapter_factory.h @@ -6,7 +6,9 @@ #define DEVICE_BLUETOOTH_BLUETOOTH_ADAPTER_FACTORY_H_ #include "base/callback.h" +#include "base/lazy_instance.h" #include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" #include "build/build_config.h" #include "device/bluetooth/bluetooth_adapter.h" #include "device/bluetooth/bluetooth_export.h" @@ -15,18 +17,34 @@ namespace device { // A factory class for building a Bluetooth adapter on platforms where Bluetooth // is available. +// +// Testing: Clients that want to specify their own return values for +// BluetoothAdapterFactory's functions need to call InitValuesForTesting(). +// If this function has been called, the Factory will return the specified +// test values instead of the default values. +// +// Only IsLowEnergySupported uses ValuesForTesting. +// TODO(crbug.com/569709): Use ValuesForTesting for all functions. class DEVICE_BLUETOOTH_EXPORT BluetoothAdapterFactory { public: typedef base::Callback<void(scoped_refptr<BluetoothAdapter> adapter)> AdapterCallback; - // Returns true if the Bluetooth adapter is available for the current - // platform. - static bool IsBluetoothAdapterAvailable(); + ~BluetoothAdapterFactory(); - // Returns true if Bluetooth Low Energy is available for the current - // platform. - static bool IsLowEnergyAvailable(); + static BluetoothAdapterFactory& Get(); + + // Returns true if the platform supports Bluetooth. It does not imply that + // there is a Bluetooth radio. Use BluetoothAdapter::IsPresent to know + // if there is a Bluetooth radio present. + static bool IsBluetoothSupported(); + + // Returns true if the platform supports Bluetooth Low Energy. This is + // independent of whether or not there is a Bluetooth radio present e.g. + // Windows 7 does not support BLE so IsLowEnergySupported would return + // false. Windows 10, on the other hand, supports BLE so this function + // returns true even if there is no Bluetooth radio on the system. + bool IsLowEnergySupported(); // Returns the shared instance of the default adapter, creating and // initializing it if necessary. |callback| is called with the adapter @@ -48,6 +66,48 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothAdapterFactory { // Returns true iff the implementation has a (non-NULL) shared instance of the // adapter. Exposed for testing. static bool HasSharedInstanceForTesting(); + + // ValuestForTesting holds the return values for BluetoothAdapterFactory's + // functions that have been set for testing. + class DEVICE_BLUETOOTH_EXPORT GlobalValuesForTesting { + public: + GlobalValuesForTesting(); + ~GlobalValuesForTesting(); + + void SetLESupported(bool supported) { le_supported_ = supported; } + + bool GetLESupported() { return le_supported_; } + + base::WeakPtr<GlobalValuesForTesting> GetWeakPtr(); + + private: + bool le_supported_ = false; + + base::WeakPtrFactory<GlobalValuesForTesting> weak_ptr_factory_; + DISALLOW_COPY_AND_ASSIGN(GlobalValuesForTesting); + }; + + // Returns an object that clients can use to control the return values + // of the Factory's functions. BluetoothAdapterFactory will keep a WeakPtr + // to this object so clients can just destroy the returned + // GlobalValuesForTesting to reset BluetoothAdapterFactory's returned + // values once they are done. + // + // Sometimes clients cannot guarantee that whey will reset all the values + // before another clients starts interacting with BluetoothAdapterFactory. + // By passing ownership of GlobalValuesForTesting to the clients, we + // ensure that only the last client that called + // InitGlobalValuesForTesting() will modify BluetoothAdapterFactory's + // returned values. + std::unique_ptr<GlobalValuesForTesting> InitGlobalValuesForTesting(); + + private: + // Friend LazyInstance to permit access to private constructor. + friend base::LazyInstanceTraitsBase<BluetoothAdapterFactory>; + + BluetoothAdapterFactory(); + + base::WeakPtr<GlobalValuesForTesting> values_for_testing_; }; } // namespace device diff --git a/chromium/device/bluetooth/bluetooth_adapter_factory_wrapper.cc b/chromium/device/bluetooth/bluetooth_adapter_factory_wrapper.cc index 722fb247e48..52a785db327 100644 --- a/chromium/device/bluetooth/bluetooth_adapter_factory_wrapper.cc +++ b/chromium/device/bluetooth/bluetooth_adapter_factory_wrapper.cc @@ -35,12 +35,12 @@ BluetoothAdapterFactoryWrapper& BluetoothAdapterFactoryWrapper::Get() { return g_singleton.Get(); } -bool BluetoothAdapterFactoryWrapper::IsLowEnergyAvailable() { +bool BluetoothAdapterFactoryWrapper::IsLowEnergySupported() { DCHECK(thread_checker_.CalledOnValidThread()); if (adapter_ != nullptr) { return true; } - return BluetoothAdapterFactory::IsLowEnergyAvailable(); + return BluetoothAdapterFactory::Get().IsLowEnergySupported(); } void BluetoothAdapterFactoryWrapper::AcquireAdapter( @@ -56,7 +56,7 @@ void BluetoothAdapterFactoryWrapper::AcquireAdapter( return; } - DCHECK(BluetoothAdapterFactory::IsLowEnergyAvailable()); + DCHECK(BluetoothAdapterFactory::Get().IsLowEnergySupported()); BluetoothAdapterFactory::GetAdapter( base::Bind(&BluetoothAdapterFactoryWrapper::OnGetAdapter, weak_ptr_factory_.GetWeakPtr(), callback)); diff --git a/chromium/device/bluetooth/bluetooth_adapter_factory_wrapper.h b/chromium/device/bluetooth/bluetooth_adapter_factory_wrapper.h index e7fd70e1b9f..3731e3caca6 100644 --- a/chromium/device/bluetooth/bluetooth_adapter_factory_wrapper.h +++ b/chromium/device/bluetooth/bluetooth_adapter_factory_wrapper.h @@ -31,7 +31,7 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothAdapterFactoryWrapper { // Returns true if the platform supports Bluetooth Low Energy or if // SetBluetoothAdapterForTesting has been called. - bool IsLowEnergyAvailable(); + bool IsLowEnergySupported(); // Adds |observer| to the set of adapter observers. If another observer has // acquired the adapter in the past it adds |observer| as an observer to that diff --git a/chromium/device/bluetooth/bluetooth_adapter_mac.mm b/chromium/device/bluetooth/bluetooth_adapter_mac.mm index cda597deee6..e7ffdbfae1c 100644 --- a/chromium/device/bluetooth/bluetooth_adapter_mac.mm +++ b/chromium/device/bluetooth/bluetooth_adapter_mac.mm @@ -587,10 +587,27 @@ void BluetoothAdapterMac::LowEnergyDeviceUpdated( } } -// TODO(krstnmnlsn): Implement. crbug.com/511025 +// TODO(crbug.com/511025): Handle state < CBCentralManagerStatePoweredOff. void BluetoothAdapterMac::LowEnergyCentralManagerUpdatedState() { VLOG(1) << "Central manager state updated: " << [low_energy_central_manager_ state]; + // A state with a value lower than CBCentralManagerStatePoweredOn implies that + // scanning has stopped and that any connected peripherals have been + // disconnected. Call DidDisconnectPeripheral manually to update the devices' + // states since macOS doesn't call it. + // See + // https://developer.apple.com/reference/corebluetooth/cbcentralmanagerdelegate/1518888-centralmanagerdidupdatestate?language=objc + if ([low_energy_central_manager_ state] < CBCentralManagerStatePoweredOn) { + VLOG(1) + << "Central no longer powered on. Notifying of device disconnection."; + for (BluetoothDevice* device : GetDevices()) { + BluetoothLowEnergyDeviceMac* device_mac = + static_cast<BluetoothLowEnergyDeviceMac*>(device); + if (device_mac->IsGattConnected()) { + device_mac->DidDisconnectPeripheral(nullptr); + } + } + } } void BluetoothAdapterMac::AddPairedDevices() { @@ -670,8 +687,7 @@ void BluetoothAdapterMac::DidConnectPeripheral(CBPeripheral* peripheral) { [low_energy_central_manager_ cancelPeripheralConnection:peripheral]; return; } - device_mac->DidConnectGatt(); - device_mac->DiscoverPrimaryServices(); + device_mac->DidConnectPeripheral(); } void BluetoothAdapterMac::DidFailToConnectPeripheral(CBPeripheral* peripheral, diff --git a/chromium/device/bluetooth/bluetooth_adapter_unittest.cc b/chromium/device/bluetooth/bluetooth_adapter_unittest.cc index 5a412aa14cc..264cc4c2e21 100644 --- a/chromium/device/bluetooth/bluetooth_adapter_unittest.cc +++ b/chromium/device/bluetooth/bluetooth_adapter_unittest.cc @@ -741,6 +741,36 @@ TEST_F(BluetoothTest, TogglePowerBeforeScan) { } #endif // defined(OS_ANDROID) +#if defined(OS_MACOSX) +// TODO(crbug.com/725270): Enable on relevant platforms. +TEST_F(BluetoothTest, TurnOffAdapterWithConnectedDevice) { + if (!PlatformSupportsLowEnergy()) { + LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test."; + return; + } + + InitWithFakeAdapter(); + TestBluetoothAdapterObserver observer(adapter_); + + StartLowEnergyDiscoverySession(); + BluetoothDevice* device = SimulateLowEnergyDevice(3); + + device->CreateGattConnection(GetGattConnectionCallback(Call::EXPECTED), + GetConnectErrorCallback(Call::NOT_EXPECTED)); + SimulateGattConnection(device); + base::RunLoop().RunUntilIdle(); + + ASSERT_TRUE(device->IsGattConnected()); + + ResetEventCounts(); + SimulateAdapterPoweredOff(); + + EXPECT_EQ(2, observer.device_changed_count()); + EXPECT_FALSE(device->IsConnected()); + EXPECT_FALSE(device->IsGattConnected()); +} +#endif // defined(OS_MACOSX) + #if defined(OS_CHROMEOS) || defined(OS_LINUX) TEST_F(BluetoothTest, RegisterLocalGattServices) { InitWithFakeAdapter(); @@ -895,7 +925,9 @@ TEST_F(BluetoothTest, DiscoverConnectedLowEnergyDeviceWithNoFilter) { EXPECT_EQ(2, observer.device_added_count()); EXPECT_EQ(2u, adapter_->GetDevices().size()); } +#endif // defined(OS_MACOSX) +#if defined(OS_MACOSX) // Simulate two devices being connected before calling // RetrieveGattConnectedDevicesWithDiscoveryFilter() with one service filter. TEST_F(BluetoothTest, DiscoverConnectedLowEnergyDeviceWithFilter) { @@ -927,7 +959,9 @@ TEST_F(BluetoothTest, DiscoverConnectedLowEnergyDeviceWithFilter) { EXPECT_EQ(1, observer.device_added_count()); EXPECT_EQ(1u, adapter_->GetDevices().size()); } +#endif // defined(OS_MACOSX) +#if defined(OS_MACOSX) // Simulate two devices being connected before calling // RetrieveGattConnectedDevicesWithDiscoveryFilter() with one service filter // that doesn't match. @@ -954,7 +988,9 @@ TEST_F(BluetoothTest, DiscoverConnectedLowEnergyDeviceWithWrongFilter) { EXPECT_EQ(0, observer.device_added_count()); EXPECT_EQ(0u, adapter_->GetDevices().size()); } +#endif // defined(OS_MACOSX) +#if defined(OS_MACOSX) // Simulate two devices being connected before calling // RetrieveGattConnectedDevicesWithDiscoveryFilter() with two service filters // that both match. @@ -999,7 +1035,9 @@ TEST_F(BluetoothTest, DiscoverConnectedLowEnergyDeviceWithTwoFilters) { EXPECT_EQ(2, observer.device_added_count()); EXPECT_EQ(2u, adapter_->GetDevices().size()); } +#endif // defined(OS_MACOSX) +#if defined(OS_MACOSX) // Simulate two devices being connected before calling // RetrieveGattConnectedDevicesWithDiscoveryFilter() with one service filter // that one match device, and then diff --git a/chromium/device/bluetooth/bluetooth_adapter_win.cc b/chromium/device/bluetooth/bluetooth_adapter_win.cc index 78424bd7a3e..c04b614c3cc 100644 --- a/chromium/device/bluetooth/bluetooth_adapter_win.cc +++ b/chromium/device/bluetooth/bluetooth_adapter_win.cc @@ -50,10 +50,8 @@ BluetoothAdapterWin::BluetoothAdapterWin(const InitCallback& init_callback) weak_ptr_factory_(this) {} BluetoothAdapterWin::~BluetoothAdapterWin() { - if (task_manager_.get()) { + if (task_manager_.get()) task_manager_->RemoveObserver(this); - task_manager_->Shutdown(); - } } std::string BluetoothAdapterWin::GetAddress() const { diff --git a/chromium/device/bluetooth/bluetooth_classic_device_mac.h b/chromium/device/bluetooth/bluetooth_classic_device_mac.h index 8a9069ef15b..9b93896a11a 100644 --- a/chromium/device/bluetooth/bluetooth_classic_device_mac.h +++ b/chromium/device/bluetooth/bluetooth_classic_device_mac.h @@ -49,6 +49,9 @@ class BluetoothClassicDeviceMac : public BluetoothDeviceMac { bool ExpectingPasskey() const override; bool ExpectingConfirmation() const override; void GetConnectionInfo(const ConnectionInfoCallback& callback) override; + void SetConnectionLatency(ConnectionLatency connection_latency, + const base::Closure& callback, + const ErrorCallback& error_callback) override; void Connect(PairingDelegate* pairing_delegate, const base::Closure& callback, const ConnectErrorCallback& error_callback) override; diff --git a/chromium/device/bluetooth/bluetooth_classic_device_mac.mm b/chromium/device/bluetooth/bluetooth_classic_device_mac.mm index da2866715b5..433fbcadea2 100644 --- a/chromium/device/bluetooth/bluetooth_classic_device_mac.mm +++ b/chromium/device/bluetooth/bluetooth_classic_device_mac.mm @@ -195,6 +195,13 @@ void BluetoothClassicDeviceMac::GetConnectionInfo( callback.Run(connection_info); } +void BluetoothClassicDeviceMac::SetConnectionLatency( + ConnectionLatency connection_latency, + const base::Closure& callback, + const ErrorCallback& error_callback) { + NOTIMPLEMENTED(); +} + void BluetoothClassicDeviceMac::Connect( PairingDelegate* pairing_delegate, const base::Closure& callback, diff --git a/chromium/device/bluetooth/bluetooth_device.h b/chromium/device/bluetooth/bluetooth_device.h index a2c4568b236..ac9dc0ea7f7 100644 --- a/chromium/device/bluetooth/bluetooth_device.h +++ b/chromium/device/bluetooth/bluetooth_device.h @@ -72,6 +72,13 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothDevice { ~ConnectionInfo(); }; + // Possible connection latency values to pass to SetConnectionLatency(). + enum ConnectionLatency { + CONNECTION_LATENCY_LOW, + CONNECTION_LATENCY_MEDIUM, + CONNECTION_LATENCY_HIGH, + }; + // Possible errors passed back to an error callback function in case of a // failed call to Connect(). enum ConnectErrorCode { @@ -264,7 +271,8 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothDevice { virtual bool IsGattConnected() const = 0; // Indicates whether the paired device accepts connections initiated from the - // adapter. This value is undefined for unpaired devices. + // adapter. This value is undefined for unpaired devices. Only available for + // Chrome OS. virtual bool IsConnectable() const = 0; // Indicates whether there is a call to Connect() ongoing. For this attribute, @@ -389,6 +397,12 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothDevice { // the callback will be populated with |kUnknownPower|. virtual void GetConnectionInfo(const ConnectionInfoCallback& callback) = 0; + // Sets the connection latency for the device. This API is only valid for LE + // devices. + virtual void SetConnectionLatency(ConnectionLatency connection_latency, + const base::Closure& callback, + const ErrorCallback& error_callback) = 0; + // Initiates a connection to the device, pairing first if necessary. // // Method calls will be made on the supplied object |pairing_delegate| diff --git a/chromium/device/bluetooth/bluetooth_device_android.cc b/chromium/device/bluetooth/bluetooth_device_android.cc index 3363e722954..9c930a98219 100644 --- a/chromium/device/bluetooth/bluetooth_device_android.cc +++ b/chromium/device/bluetooth/bluetooth_device_android.cc @@ -4,7 +4,6 @@ #include "device/bluetooth/bluetooth_device_android.h" -#include "base/android/context_utils.h" #include "base/android/jni_android.h" #include "base/android/jni_string.h" #include "base/metrics/histogram_macros.h" @@ -152,6 +151,13 @@ void BluetoothDeviceAndroid::GetConnectionInfo( callback.Run(ConnectionInfo()); } +void BluetoothDeviceAndroid::SetConnectionLatency( + ConnectionLatency connection_latency, + const base::Closure& callback, + const ErrorCallback& error_callback) { + NOTIMPLEMENTED(); +} + void BluetoothDeviceAndroid::Connect( PairingDelegate* pairing_delegate, const base::Closure& callback, @@ -265,8 +271,8 @@ BluetoothDeviceAndroid::BluetoothDeviceAndroid(BluetoothAdapterAndroid* adapter) : BluetoothDevice(adapter) {} void BluetoothDeviceAndroid::CreateGattConnectionImpl() { - Java_ChromeBluetoothDevice_createGattConnectionImpl( - AttachCurrentThread(), j_device_, base::android::GetApplicationContext()); + Java_ChromeBluetoothDevice_createGattConnectionImpl(AttachCurrentThread(), + j_device_); } void BluetoothDeviceAndroid::DisconnectGatt() { diff --git a/chromium/device/bluetooth/bluetooth_device_android.h b/chromium/device/bluetooth/bluetooth_device_android.h index 228886dddd4..485be65d3d8 100644 --- a/chromium/device/bluetooth/bluetooth_device_android.h +++ b/chromium/device/bluetooth/bluetooth_device_android.h @@ -65,6 +65,9 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothDeviceAndroid final bool ExpectingPasskey() const override; bool ExpectingConfirmation() const override; void GetConnectionInfo(const ConnectionInfoCallback& callback) override; + void SetConnectionLatency(ConnectionLatency connection_latency, + const base::Closure& callback, + const ErrorCallback& error_callback) override; void Connect(device::BluetoothDevice::PairingDelegate* pairing_delegate, const base::Closure& callback, const ConnectErrorCallback& error_callback) override; diff --git a/chromium/device/bluetooth/bluetooth_device_unittest.cc b/chromium/device/bluetooth/bluetooth_device_unittest.cc index b19d78e6998..19fc5cda67c 100644 --- a/chromium/device/bluetooth/bluetooth_device_unittest.cc +++ b/chromium/device/bluetooth/bluetooth_device_unittest.cc @@ -483,11 +483,11 @@ TEST_F(BluetoothTest, GetUUIDs_Connection) { #if defined(OS_MACOSX) // Tests that receiving 2 notifications in a row from macOS that services has -// changed is handled correctly. Each notification should generate a notfication -// that the gatt device has changed, and each notification should ask to macOS -// to scan for services. Only after the second service scan is received, the -// device changed notification should be sent and the characteristic discovery -// procedure should be started. +// changed is handled correctly. Each notification should generate a +// notification that the gatt device has changed, and each notification should +// ask to macOS to scan for services. Only after the second service scan is +// received, the device changed notification should be sent and the +// characteristic discovery procedure should be started. // Android: This test doesn't apply to Android because there is no services // changed event that could arrive during a discovery procedure. TEST_F(BluetoothTest, TwoPendingServiceDiscoveryRequests) { @@ -511,16 +511,21 @@ TEST_F(BluetoothTest, TwoPendingServiceDiscoveryRequests) { EXPECT_EQ(1, observer.device_changed_count()); EXPECT_FALSE(device->IsGattServicesDiscoveryComplete()); - // Fist system call to - // -[id<CBPeripheralDelegate> peripheral:didDiscoverServices:] + // First system call to + // -[id<CBPeripheralDelegate> peripheral:didDiscoverServices:] using + // SimulateDidDiscoverServicesMac(). observer.Reset(); - SimulateDidDiscoverServices(device, {kTestUUIDHeartRate}); + AddServicesToDeviceMac(device, {kTestUUIDHeartRate}); + SimulateDidDiscoverServicesMac(device); EXPECT_EQ(0, observer.device_changed_count()); EXPECT_FALSE(device->IsGattServicesDiscoveryComplete()); EXPECT_EQ(gatt_characteristic_discovery_attempts_, 0); // Second system call to - // -[id<CBPeripheralDelegate> peripheral:didDiscoverServices:] + // -[id<CBPeripheralDelegate> peripheral:didDiscoverServices:] using the + // generic call to SimulateGattServicesDiscovered(). This method triggers + // the full discovery cycles (services, characteristics and descriptors), + // which includes -[id<CBPeripheralDelegate> peripheral:didDiscoverServices:]. SimulateGattServicesDiscovered( device, std::vector<std::string>({kTestUUIDImmediateAlert})); EXPECT_EQ(1, observer.device_changed_count()); @@ -551,7 +556,7 @@ TEST_F(BluetoothTest, ExtraDidDiscoverServicesCall) { EXPECT_FALSE(device->IsGattServicesDiscoveryComplete()); // Legitimate system call to - // -[id<CBPeripheralDelegate> peripheral:didDiscoverServices:] + // -[id<CBPeripheralDelegate> peripheral:didDiscoverServices:]. observer.Reset(); SimulateGattServicesDiscovered( device, std::vector<std::string>({kTestUUIDHeartRate})); @@ -561,8 +566,15 @@ TEST_F(BluetoothTest, ExtraDidDiscoverServicesCall) { EXPECT_EQ(1u, device->GetGattServices().size()); // Unexpected system call to - // -[id<CBPeripheralDelegate> peripheral:didDiscoverServices:] - SimulateDidDiscoverServices(device, {kTestUUIDImmediateAlert}); + // -[id<CBPeripheralDelegate> peripheral:didDiscoverServices:]: + // This system call is expected only once after -[CBCentralManager + // discoverServices:]. The call to -[CBCentralManager discoverServices:] and + // its answer with -[id<CBPeripheralDelegate> peripheral:didDiscoverServices:] + // is done with SimulateGattServicesDiscovered(). So a second system call to + // -[id<CBPeripheralDelegate> peripheral:didDiscoverServices:] is not expected + // and should be ignored. + AddServicesToDeviceMac(device, {kTestUUIDImmediateAlert}); + SimulateDidDiscoverServicesMac(device); EXPECT_EQ(1, observer.device_changed_count()); EXPECT_TRUE(device->IsGattServicesDiscoveryComplete()); @@ -1015,6 +1027,7 @@ TEST_F(BluetoothTest, return; } InitWithFakeAdapter(); + TestBluetoothAdapterObserver observer(adapter_); StartLowEnergyDiscoverySession(); BluetoothDevice* device = SimulateLowEnergyDevice(3); @@ -1027,6 +1040,16 @@ TEST_F(BluetoothTest, SimulateGattConnection(device); base::RunLoop().RunUntilIdle(); +#if defined(OS_ANDROID) + // Android incorrectly starts second discovery for devices that are already + // connected. + // TODO(crbug.com/718168): Remove once Android is fixed. + EXPECT_EQ(2, gatt_discovery_attempts_); + EXPECT_EQ(2, observer.device_changed_count()); +#else // !defined(OS_ANDROID) + EXPECT_EQ(1, gatt_discovery_attempts_); + EXPECT_EQ(1, observer.device_changed_count()); +#endif // defined(OS_ANDROID) EXPECT_EQ(1, gatt_connection_attempts_); EXPECT_EQ(1, callback_count_); EXPECT_EQ(0, error_callback_count_); diff --git a/chromium/device/bluetooth/bluetooth_device_win.cc b/chromium/device/bluetooth/bluetooth_device_win.cc index 18d245a5b43..88bd521b6e1 100644 --- a/chromium/device/bluetooth/bluetooth_device_win.cc +++ b/chromium/device/bluetooth/bluetooth_device_win.cc @@ -149,6 +149,13 @@ void BluetoothDeviceWin::GetConnectionInfo( callback.Run(ConnectionInfo()); } +void BluetoothDeviceWin::SetConnectionLatency( + ConnectionLatency connection_latency, + const base::Closure& callback, + const ErrorCallback& error_callback) { + NOTIMPLEMENTED(); +} + void BluetoothDeviceWin::Connect( PairingDelegate* pairing_delegate, const base::Closure& callback, diff --git a/chromium/device/bluetooth/bluetooth_device_win.h b/chromium/device/bluetooth/bluetooth_device_win.h index 18a380c14e4..ce853e814b4 100644 --- a/chromium/device/bluetooth/bluetooth_device_win.h +++ b/chromium/device/bluetooth/bluetooth_device_win.h @@ -60,6 +60,9 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothDeviceWin : public BluetoothDevice { bool ExpectingPasskey() const override; bool ExpectingConfirmation() const override; void GetConnectionInfo(const ConnectionInfoCallback& callback) override; + void SetConnectionLatency(ConnectionLatency connection_latency, + const base::Closure& callback, + const ErrorCallback& error_callback) override; void Connect(PairingDelegate* pairing_delegate, const base::Closure& callback, const ConnectErrorCallback& error_callback) override; diff --git a/chromium/device/bluetooth/bluetooth_low_energy_device_mac.h b/chromium/device/bluetooth/bluetooth_low_energy_device_mac.h index e2823d16ede..f559e605a8a 100644 --- a/chromium/device/bluetooth/bluetooth_low_energy_device_mac.h +++ b/chromium/device/bluetooth/bluetooth_low_energy_device_mac.h @@ -56,6 +56,9 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothLowEnergyDeviceMac bool ExpectingPasskey() const override; bool ExpectingConfirmation() const override; void GetConnectionInfo(const ConnectionInfoCallback& callback) override; + void SetConnectionLatency(ConnectionLatency connection_latency, + const base::Closure& callback, + const ErrorCallback& error_callback) override; void Connect(PairingDelegate* pairing_delegate, const base::Closure& callback, const ConnectErrorCallback& error_callback) override; @@ -110,7 +113,10 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothLowEnergyDeviceMac friend class BluetoothTestMac; friend class BluetoothRemoteGattServiceMac; - // Calls the macOS to discover primary services. + // Called by the adapter when the device is connected. + void DidConnectPeripheral(); + + // Calls macOS to discover primary services. void DiscoverPrimaryServices(); // Sends notification if this device is ready with all services discovered. @@ -140,8 +146,8 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothLowEnergyDeviceMac base::scoped_nsobject<BluetoothLowEnergyPeripheralDelegate> peripheral_delegate_; - // Whether the device is connectable. - bool connectable_; + // Whether the device is connected. + bool connected_; // The peripheral's identifier, as returned by [CBPeripheral identifier]. std::string identifier_; diff --git a/chromium/device/bluetooth/bluetooth_low_energy_device_mac.mm b/chromium/device/bluetooth/bluetooth_low_energy_device_mac.mm index 6d41c6e10f6..80de028e345 100644 --- a/chromium/device/bluetooth/bluetooth_low_energy_device_mac.mm +++ b/chromium/device/bluetooth/bluetooth_low_energy_device_mac.mm @@ -28,6 +28,7 @@ BluetoothLowEnergyDeviceMac::BluetoothLowEnergyDeviceMac( CBPeripheral* peripheral) : BluetoothDeviceMac(adapter), peripheral_(peripheral, base::scoped_policy::RETAIN), + connected_(false), discovery_pending_count_(0) { DCHECK(BluetoothAdapterMac::IsLowEnergyAvailable()); DCHECK(peripheral_.get()); @@ -96,11 +97,17 @@ bool BluetoothLowEnergyDeviceMac::IsConnected() const { } bool BluetoothLowEnergyDeviceMac::IsGattConnected() const { - return ([peripheral_ state] == CBPeripheralStateConnected); + // |connected_| can be false while |[peripheral_ state]| is + // |CBPeripheralStateConnected|. This happens + // BluetoothAdapterMac::DidConnectPeripheral() is called and + // BluetoothLowEnergyDeviceMac::DidConnectGatt() has not been called yet. + return connected_; } bool BluetoothLowEnergyDeviceMac::IsConnectable() const { - return connectable_; + // Only available for Chrome OS. + NOTIMPLEMENTED(); + return false; } bool BluetoothLowEnergyDeviceMac::IsConnecting() const { @@ -124,6 +131,13 @@ void BluetoothLowEnergyDeviceMac::GetConnectionInfo( NOTIMPLEMENTED(); } +void BluetoothLowEnergyDeviceMac::SetConnectionLatency( + ConnectionLatency connection_latency, + const base::Closure& callback, + const ErrorCallback& error_callback) { + NOTIMPLEMENTED(); +} + void BluetoothLowEnergyDeviceMac::Connect( PairingDelegate* pairing_delegate, const base::Closure& callback, @@ -189,7 +203,7 @@ void BluetoothLowEnergyDeviceMac::DisconnectGatt() { void BluetoothLowEnergyDeviceMac::DidDiscoverPrimaryServices(NSError* error) { --discovery_pending_count_; if (discovery_pending_count_ < 0) { - // This should never happens, just in case it happens with a device, + // This should never happen, just in case it happens with a device, // discovery_pending_count_ is set back to 0. VLOG(1) << *this << ": BluetoothLowEnergyDeviceMac::discovery_pending_count_ " @@ -256,6 +270,13 @@ void BluetoothLowEnergyDeviceMac::DidDiscoverCharacteristics( // Don't create characteristics if the device disconnected. return; } + if (IsGattServicesDiscoveryComplete()) { + // This should never happen, just in case it happens with a device, this + // notification should be ignored. + VLOG(1) << *this + << ": Discovery complete, ignoring DidDiscoverCharacteristics."; + return; + } BluetoothRemoteGattServiceMac* gatt_service = GetBluetoothRemoteGattService(cb_service); @@ -327,6 +348,13 @@ void BluetoothLowEnergyDeviceMac::DidDiscoverDescriptors( // Don't discover descriptors if the device disconnected. return; } + if (IsGattServicesDiscoveryComplete()) { + // This should never happen, just in case it happens with a device, this + // notification should be ignored. + VLOG(1) << *this + << ": Discovery complete, ignoring DidDiscoverDescriptors."; + return; + } BluetoothRemoteGattServiceMac* gatt_service = GetBluetoothRemoteGattService(cb_characteristic.service); DCHECK(gatt_service); @@ -372,6 +400,20 @@ std::string BluetoothLowEnergyDeviceMac::GetPeripheralHashAddress( return BluetoothDevice::CanonicalizeAddress(hash); } +void BluetoothLowEnergyDeviceMac::DidConnectPeripheral() { + VLOG(1) << *this << ": GATT connected."; + if (!connected_) { + connected_ = true; + DidConnectGatt(); + DiscoverPrimaryServices(); + } else { + // -[<CBCentralManagerDelegate> centralManager:didConnectPeripheral:] can be + // called twice because of a macOS bug. This second call should be ignored. + // See crbug.com/681414. + VLOG(1) << *this << ": Already connected, ignoring event."; + } +} + void BluetoothLowEnergyDeviceMac::DiscoverPrimaryServices() { VLOG(1) << *this << ": DiscoverPrimaryServices, pending count " << discovery_pending_count_; @@ -380,6 +422,7 @@ void BluetoothLowEnergyDeviceMac::DiscoverPrimaryServices() { } void BluetoothLowEnergyDeviceMac::SendNotificationIfDiscoveryComplete() { + DCHECK(!IsGattServicesDiscoveryComplete()); // Notify when all services have been discovered. bool discovery_complete = discovery_pending_count_ == 0 && @@ -435,6 +478,7 @@ BluetoothLowEnergyDeviceMac::GetBluetoothRemoteGattDescriptor( } void BluetoothLowEnergyDeviceMac::DidDisconnectPeripheral(NSError* error) { + connected_ = false; VLOG(1) << *this << ": Disconnected from peripheral."; if (error) { VLOG(1) << *this @@ -468,8 +512,10 @@ std::ostream& operator<<(std::ostream& out, // TODO(crbug.com/703878): Should use // BluetoothLowEnergyDeviceMac::GetNameForDisplay() instead. base::Optional<std::string> name = device.GetName(); - const char* name_cstr = name ? name->c_str() : ""; + const char* is_gatt_connected = + device.IsGattConnected() ? "GATT connected" : "GATT disconnected"; return out << "<BluetoothLowEnergyDeviceMac " << device.GetAddress() << "/" - << &device << ", \"" << name_cstr << "\">"; + << &device << ", " << is_gatt_connected << ", \"" + << name.value_or("Unnamed device") << "\">"; } } // namespace device diff --git a/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_mac.h b/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_mac.h index 15c8e51c1cb..1f54f8645fe 100644 --- a/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_mac.h +++ b/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_mac.h @@ -99,8 +99,18 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothRemoteGattCharacteristicMac // Returns BluetoothRemoteGattDescriptorMac from CBDescriptor. BluetoothRemoteGattDescriptorMac* GetBluetoothRemoteGattDescriptorMac( CBDescriptor* cb_descriptor) const; - // Is true if the characteristic has been discovered with all its descriptors. + bool HasPendingRead() const { + return !read_characteristic_value_callbacks_.first.is_null(); + }; + bool HasPendingWrite() const { + return !write_characteristic_value_callbacks_.first.is_null(); + }; + // Is true if the characteristic has been discovered with all its descriptors + // and discovery_pending_count_ is 0. bool is_discovery_complete_; + // Increased each time DiscoverDescriptors() is called. And decreased when + // DidDiscoverDescriptors() is called. + int discovery_pending_count_; // gatt_service_ owns instances of this class. BluetoothRemoteGattServiceMac* gatt_service_; // A characteristic from CBPeripheral.services.characteristics. @@ -111,8 +121,6 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothRemoteGattCharacteristicMac BluetoothUUID uuid_; // Characteristic value. std::vector<uint8_t> value_; - // True if a gatt read or write request is in progress. - bool characteristic_value_read_or_write_in_progress_; // ReadRemoteCharacteristic request callbacks. std::pair<ValueCallback, ErrorCallback> read_characteristic_value_callbacks_; // WriteRemoteCharacteristic request callbacks. diff --git a/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_mac.mm b/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_mac.mm index 5e07ade67d9..4c9d99f8261 100644 --- a/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_mac.mm +++ b/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_mac.mm @@ -69,9 +69,10 @@ static BluetoothGattCharacteristic::Properties ConvertProperties( BluetoothRemoteGattCharacteristicMac::BluetoothRemoteGattCharacteristicMac( BluetoothRemoteGattServiceMac* gatt_service, CBCharacteristic* cb_characteristic) - : gatt_service_(gatt_service), + : is_discovery_complete_(false), + discovery_pending_count_(0), + gatt_service_(gatt_service), cb_characteristic_(cb_characteristic, base::scoped_policy::RETAIN), - characteristic_value_read_or_write_in_progress_(false), weak_ptr_factory_(this) { uuid_ = BluetoothAdapterMac::BluetoothUUIDWithCBUUID( [cb_characteristic_.get() UUID]); @@ -81,12 +82,12 @@ BluetoothRemoteGattCharacteristicMac::BluetoothRemoteGattCharacteristicMac( } BluetoothRemoteGattCharacteristicMac::~BluetoothRemoteGattCharacteristicMac() { - if (!read_characteristic_value_callbacks_.first.is_null()) { + if (HasPendingRead()) { std::pair<ValueCallback, ErrorCallback> callbacks; callbacks.swap(read_characteristic_value_callbacks_); callbacks.second.Run(BluetoothGattService::GATT_ERROR_FAILED); } - if (!write_characteristic_value_callbacks_.first.is_null()) { + if (HasPendingWrite()) { std::pair<base::Closure, ErrorCallback> callbacks; callbacks.swap(write_characteristic_value_callbacks_); callbacks.second.Run(BluetoothGattService::GATT_ERROR_FAILED); @@ -160,7 +161,7 @@ void BluetoothRemoteGattCharacteristicMac::ReadRemoteCharacteristic( BluetoothRemoteGattService::GATT_ERROR_NOT_SUPPORTED)); return; } - if (characteristic_value_read_or_write_in_progress_) { + if (HasPendingRead() || HasPendingWrite()) { VLOG(1) << *this << ": Characteristic read already in progress."; base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, @@ -169,7 +170,6 @@ void BluetoothRemoteGattCharacteristicMac::ReadRemoteCharacteristic( return; } VLOG(1) << *this << ": Read characteristic."; - characteristic_value_read_or_write_in_progress_ = true; read_characteristic_value_callbacks_ = std::make_pair(callback, error_callback); [GetCBPeripheral() readValueForCharacteristic:cb_characteristic_]; @@ -187,7 +187,7 @@ void BluetoothRemoteGattCharacteristicMac::WriteRemoteCharacteristic( BluetoothRemoteGattService::GATT_ERROR_NOT_PERMITTED)); return; } - if (characteristic_value_read_or_write_in_progress_) { + if (HasPendingRead() || HasPendingWrite()) { VLOG(1) << *this << ": Characteristic write already in progress."; base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, @@ -196,7 +196,6 @@ void BluetoothRemoteGattCharacteristicMac::WriteRemoteCharacteristic( return; } VLOG(1) << *this << ": Write characteristic."; - characteristic_value_read_or_write_in_progress_ = true; write_characteristic_value_callbacks_ = std::make_pair(callback, error_callback); base::scoped_nsobject<NSData> nsdata_value( @@ -246,6 +245,7 @@ void BluetoothRemoteGattCharacteristicMac::UnsubscribeFromNotifications( void BluetoothRemoteGattCharacteristicMac::DiscoverDescriptors() { VLOG(1) << *this << ": Discover descriptors."; is_discovery_complete_ = false; + ++discovery_pending_count_; [GetCBPeripheral() discoverDescriptorsForCharacteristic:cb_characteristic_.get()]; } @@ -254,10 +254,9 @@ void BluetoothRemoteGattCharacteristicMac::DidUpdateValue(NSError* error) { CHECK_EQ(GetCBPeripheral().state, CBPeripheralStateConnected); // This method is called when the characteristic is read and when a // notification is received. - if (characteristic_value_read_or_write_in_progress_) { + if (HasPendingRead()) { std::pair<ValueCallback, ErrorCallback> callbacks; callbacks.swap(read_characteristic_value_callbacks_); - characteristic_value_read_or_write_in_progress_ = false; if (error) { BluetoothGattService::GattErrorCode error_code = BluetoothDeviceMac::GetGattErrorCodeFromNSError(error); @@ -293,17 +292,30 @@ void BluetoothRemoteGattCharacteristicMac::UpdateValue() { } void BluetoothRemoteGattCharacteristicMac::DidWriteValue(NSError* error) { + // We could have called cancelPeripheralConnection, which causes + // [CBPeripheral state] to be CBPeripheralStateDisconnected, before or during + // a write without response callback so we flush all pending writes. + // TODO(crbug.com/726534): Remove once we can avoid calling DidWriteValue + // when we disconnect before or during a write without response call. + if (HasPendingWrite() && + GetCBPeripheral().state != CBPeripheralStateConnected) { + std::pair<base::Closure, ErrorCallback> callbacks; + callbacks.swap(write_characteristic_value_callbacks_); + callbacks.second.Run(BluetoothGattService::GATT_ERROR_FAILED); + return; + } + CHECK_EQ(GetCBPeripheral().state, CBPeripheralStateConnected); - if (!characteristic_value_read_or_write_in_progress_) { + if (!HasPendingWrite()) { // In case of buggy device, nothing should be done if receiving extra // write confirmation. VLOG(1) << *this << ": Write notification while no write operation pending."; return; } + std::pair<base::Closure, ErrorCallback> callbacks; callbacks.swap(write_characteristic_value_callbacks_); - characteristic_value_read_or_write_in_progress_ = false; if (error) { BluetoothGattService::GattErrorCode error_code = BluetoothDeviceMac::GetGattErrorCodeFromNSError(error); @@ -346,8 +358,15 @@ void BluetoothRemoteGattCharacteristicMac::DidUpdateNotificationState( } void BluetoothRemoteGattCharacteristicMac::DidDiscoverDescriptors() { - DCHECK(!is_discovery_complete_); + if (discovery_pending_count_ == 0) { + // This should never happen, just in case it happens with a device, this + // notification should be ignored. + VLOG(1) << *this + << ": Unmatch DiscoverDescriptors and DidDiscoverDescriptors."; + return; + } VLOG(1) << *this << ": Did discover descriptors."; + --discovery_pending_count_; std::unordered_set<std::string> descriptor_identifier_to_remove; for (const auto& iter : gatt_descriptor_macs_) { descriptor_identifier_to_remove.insert(iter.first); @@ -380,7 +399,7 @@ void BluetoothRemoteGattCharacteristicMac::DidDiscoverDescriptors() { gatt_descriptor_macs_.erase(pair_to_remove); GetMacAdapter()->NotifyGattDescriptorRemoved(descriptor_to_remove.get()); } - is_discovery_complete_ = true; + is_discovery_complete_ = discovery_pending_count_ == 0; } bool BluetoothRemoteGattCharacteristicMac::IsReadable() const { diff --git a/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_unittest.cc b/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_unittest.cc index 743d684e60e..625b9711a6d 100644 --- a/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_unittest.cc +++ b/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_unittest.cc @@ -1014,6 +1014,99 @@ TEST_F(BluetoothRemoteGattCharacteristicTest, } #endif // defined(OS_ANDROID) || defined(OS_MACOSX) || defined(OS_WIN) +#if defined(OS_ANDROID) || defined(OS_MACOSX) +// TODO(crbug.com/713991): Enable on windows once it better matches +// how other platforms set global variables. +// Tests that a notification arriving during a pending read doesn't +// cause a crash. +TEST_F(BluetoothRemoteGattCharacteristicTest, + Notification_During_ReadRemoteCharacteristic) { + if (!PlatformSupportsLowEnergy()) { + LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test."; + return; + } + ASSERT_NO_FATAL_FAILURE(StartNotifyBoilerplate( + BluetoothRemoteGattCharacteristic::PROPERTY_NOTIFY | + BluetoothRemoteGattCharacteristic::PROPERTY_READ, + NotifyValueState::NOTIFY)); + + TestBluetoothAdapterObserver observer(adapter_); + + characteristic1_->ReadRemoteCharacteristic( + GetReadValueCallback(Call::EXPECTED), + GetGattErrorCallback(Call::NOT_EXPECTED)); + + std::vector<uint8_t> notification_value = {111}; + SimulateGattCharacteristicChanged(characteristic1_, notification_value); + base::RunLoop().RunUntilIdle(); + +#if defined(OS_MACOSX) + // Because macOS uses the same event for notifications and read value + // responses, we can't know what the event was for. Because there is a pending + // read request we assume is a read request on macOS. + EXPECT_EQ(notification_value, last_read_value_); + EXPECT_EQ(notification_value, characteristic1_->GetValue()); + EXPECT_EQ(0, observer.gatt_characteristic_value_changed_count()); +#else // !defined(OS_MACOSX) + EXPECT_EQ(std::vector<uint8_t>(), last_read_value_); + EXPECT_EQ(notification_value, characteristic1_->GetValue()); + EXPECT_EQ(1, observer.gatt_characteristic_value_changed_count()); +#endif // defined(OS_MACOSX) + + observer.Reset(); + std::vector<uint8_t> read_value = {222}; + SimulateGattCharacteristicRead(characteristic1_, read_value); + base::RunLoop().RunUntilIdle(); +#if defined(OS_MACOSX) + // There are no pending read requests anymore so we assume the event + // was a notification. + EXPECT_EQ(notification_value, last_read_value_); + EXPECT_EQ(read_value, characteristic1_->GetValue()); + EXPECT_EQ(1, observer.gatt_characteristic_value_changed_count()); +#else // !defined(OS_MACOSX) + EXPECT_EQ(read_value, last_read_value_); + EXPECT_EQ(read_value, characteristic1_->GetValue()); + EXPECT_EQ(0, observer.gatt_characteristic_value_changed_count()); +#endif // defined(OS_MACOSX) +} +#endif // defined(OS_ANDROID) || defined(OS_MACOSX) + +#if defined(OS_ANDROID) || defined(OS_MACOSX) || defined(OS_WIN) +// Tests that a notification arriving during a pending write doesn't +// cause a crash. +TEST_F(BluetoothRemoteGattCharacteristicTest, + Notification_During_WriteRemoteCharacteristic) { + if (!PlatformSupportsLowEnergy()) { + LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test."; + return; + } + ASSERT_NO_FATAL_FAILURE(StartNotifyBoilerplate( + BluetoothRemoteGattCharacteristic::PROPERTY_NOTIFY | + BluetoothRemoteGattCharacteristic::PROPERTY_WRITE, + NotifyValueState::NOTIFY)); + + TestBluetoothAdapterObserver observer(adapter_); + + std::vector<uint8_t> write_value = {111}; + characteristic1_->WriteRemoteCharacteristic( + write_value, GetCallback(Call::EXPECTED), + GetGattErrorCallback(Call::NOT_EXPECTED)); + + std::vector<uint8_t> notification_value = {222}; + SimulateGattCharacteristicChanged(characteristic1_, notification_value); + base::RunLoop().RunUntilIdle(); + + EXPECT_EQ(notification_value, characteristic1_->GetValue()); + EXPECT_EQ(1, observer.gatt_characteristic_value_changed_count()); + + observer.Reset(); + SimulateGattCharacteristicWrite(characteristic1_); + base::RunLoop().RunUntilIdle(); + + EXPECT_EQ(write_value, last_write_value_); +} +#endif // defined(OS_ANDROID) || defined(OS_MACOSX) || defined(OS_WIN) + #if defined(OS_ANDROID) || defined(OS_MACOSX) || defined(OS_WIN) // StartNotifySession fails if characteristic doesn't have Notify or Indicate // property. @@ -2293,7 +2386,7 @@ TEST_F(BluetoothRemoteGattCharacteristicTest, ReadDuringDisconnect) { EXPECT_EQ(BluetoothRemoteGattService::GATT_ERROR_FAILED, last_gatt_error_code_); } -#endif +#endif // defined(OS_ANDROID) #if defined(OS_ANDROID) // Tests that write requests after a device disconnects but before the @@ -2318,7 +2411,7 @@ TEST_F(BluetoothRemoteGattCharacteristicTest, WriteDuringDisconnect) { EXPECT_EQ(BluetoothRemoteGattService::GATT_ERROR_FAILED, last_gatt_error_code_); } -#endif +#endif // defined(OS_ANDROID) #if defined(OS_MACOSX) // Tests that writing without response during a disconnect results in an error. @@ -2345,6 +2438,62 @@ TEST_F(BluetoothRemoteGattCharacteristicTest, } #endif // defined(OS_MACOSX) +#if defined(OS_MACOSX) +// Tests that disconnecting right after a write without response results in an +// error. +// TODO(crbug.com/726534): Enable on other platforms depending on the resolution +// of crbug.com/726534. +TEST_F(BluetoothRemoteGattCharacteristicTest, + DisconnectCalledDuringWriteWithoutResponse) { + if (!PlatformSupportsLowEnergy()) { + LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test."; + return; + } + ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate( + BluetoothRemoteGattCharacteristic::PROPERTY_WRITE_WITHOUT_RESPONSE)); + + characteristic1_->WriteRemoteCharacteristic( + std::vector<uint8_t>(), GetCallback(Call::NOT_EXPECTED), + GetGattErrorCallback(Call::EXPECTED)); + gatt_connections_[0]->Disconnect(); + base::RunLoop().RunUntilIdle(); + + EXPECT_EQ(BluetoothRemoteGattService::GATT_ERROR_FAILED, + last_gatt_error_code_); + + SimulateGattDisconnection(device_); + base::RunLoop().RunUntilIdle(); +} +#endif // defined(OS_MACOSX) + +#if defined(OS_MACOSX) +// Tests that disconnecting right before a write without response results in an +// error. +// TODO(crbug.com/726534): Enable on other platforms depending on the resolution +// of crbug.com/726534. +TEST_F(BluetoothRemoteGattCharacteristicTest, + DisconnectCalledBeforeWriteWithoutResponse) { + if (!PlatformSupportsLowEnergy()) { + LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test."; + return; + } + ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate( + BluetoothRemoteGattCharacteristic::PROPERTY_WRITE_WITHOUT_RESPONSE)); + + gatt_connections_[0]->Disconnect(); + characteristic1_->WriteRemoteCharacteristic( + std::vector<uint8_t>(), GetCallback(Call::NOT_EXPECTED), + GetGattErrorCallback(Call::EXPECTED)); + base::RunLoop().RunUntilIdle(); + + EXPECT_EQ(BluetoothRemoteGattService::GATT_ERROR_FAILED, + last_gatt_error_code_); + + SimulateGattDisconnection(device_); + base::RunLoop().RunUntilIdle(); +} +#endif // defined(OS_MACOSX) + #if defined(OS_ANDROID) // Tests that start notifications requests after a device disconnects but before // the disconnect task runs result in an error. @@ -2372,7 +2521,7 @@ TEST_F(BluetoothRemoteGattCharacteristicTest, EXPECT_EQ(BluetoothRemoteGattService::GATT_ERROR_FAILED, last_gatt_error_code_); } -#endif +#endif // defined(OS_ANDROID) #if defined(OS_ANDROID) // Tests that stop notifications requests after a device disconnects but before @@ -2393,7 +2542,7 @@ TEST_F(BluetoothRemoteGattCharacteristicTest, notify_sessions_[0]->Stop(GetStopNotifyCallback(Call::EXPECTED)); base::RunLoop().RunUntilIdle(); } -#endif +#endif // defined(OS_ANDROID) #if defined(OS_ANDROID) // Tests that deleting notify sessions after a device disconnects but before the @@ -2414,5 +2563,121 @@ TEST_F(BluetoothRemoteGattCharacteristicTest, notify_sessions_.clear(); base::RunLoop().RunUntilIdle(); } -#endif +#endif // defined(OS_ANDROID) + +#if defined(OS_MACOSX) +// Tests to receive a services changed notification from macOS, while +// discovering descriptors. This test simulate having 2 descriptor scan at the +// same time. Only once both descriptor scanning is done, the gatt device is +// ready. +// Android: This test doesn't apply to Android because there is no services +// changed event that could arrive during a discovery procedure. +TEST_F(BluetoothRemoteGattCharacteristicTest, + SimulateDeviceModificationWhileDiscoveringDescriptors) { + if (!PlatformSupportsLowEnergy()) { + LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test."; + return; + } + InitWithFakeAdapter(); + StartLowEnergyDiscoverySession(); + BluetoothDevice* device = SimulateLowEnergyDevice(3); + device->CreateGattConnection(GetGattConnectionCallback(Call::EXPECTED), + GetConnectErrorCallback(Call::NOT_EXPECTED)); + + TestBluetoothAdapterObserver observer(adapter_); + + // Starts first discovery process. + SimulateGattConnection(device); + EXPECT_EQ(1, observer.device_changed_count()); + AddServicesToDeviceMac(device, {kTestUUIDHeartRate}); + SimulateDidDiscoverServicesMac(device); + EXPECT_EQ(1u, device->GetGattServices().size()); + BluetoothRemoteGattService* service = device->GetGattServices()[0]; + std::string characteristic_uuid = "11111111-0000-1000-8000-00805f9b34fb"; + AddCharacteristicToServiceMac(service, characteristic_uuid, + /* properties */ 0); + SimulateDidDiscoverCharacteristicsMac(service); + EXPECT_EQ(1u, service->GetCharacteristics().size()); + BluetoothRemoteGattCharacteristic* characteristic = + service->GetCharacteristics()[0]; + std::string descriptor_uuid = "22222222-0000-1000-8000-00805f9b34fb"; + AddDescriptorToCharacteristicMac(characteristic, descriptor_uuid); + // Now waiting for descriptor discovery. + + // Starts second discovery process. + SimulateGattServicesChanged(device); + EXPECT_EQ(2, observer.device_changed_count()); + SimulateDidDiscoverServicesMac(device); + SimulateDidDiscoverCharacteristicsMac(service); + // Now waiting for a second descriptor discovery. + + // Finish discovery process. + // First system call to -[id<CBPeripheralDelegate> + // peripheral:didDiscoverDescriptorsForCharacteristic:error:] + SimulateDidDiscoverDescriptorsMac(characteristic); + EXPECT_EQ(0, observer.gatt_service_changed_count()); + EXPECT_EQ(1u, service->GetCharacteristics().size()); + EXPECT_EQ(1u, characteristic->GetDescriptors().size()); + EXPECT_EQ(2, observer.device_changed_count()); + + // Second system call to -[id<CBPeripheralDelegate> + // peripheral:didDiscoverDescriptorsForCharacteristic:error:] + // Finish second discovery process. + observer.Reset(); + SimulateDidDiscoverDescriptorsMac(characteristic); + EXPECT_EQ(1, observer.gatt_service_changed_count()); + EXPECT_EQ(1, observer.device_changed_count()); +} +#endif // defined(OS_MACOSX) + +#if defined(OS_MACOSX) +// Simulates to receive an extra discovery descriptor notifications from macOS. +// Those notifications should be ignored. +// Android: This test doesn't apply to Android because there is no services +// changed event that could arrive during a discovery procedure. +TEST_F(BluetoothRemoteGattCharacteristicTest, ExtraDidDiscoverDescriptorsCall) { + if (!PlatformSupportsLowEnergy()) { + LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test."; + return; + } + InitWithFakeAdapter(); + StartLowEnergyDiscoverySession(); + BluetoothDevice* device = SimulateLowEnergyDevice(3); + device->CreateGattConnection(GetGattConnectionCallback(Call::EXPECTED), + GetConnectErrorCallback(Call::NOT_EXPECTED)); + + TestBluetoothAdapterObserver observer(adapter_); + + // Starts first discovery process. + SimulateGattConnection(device); + AddServicesToDeviceMac(device, {kTestUUIDHeartRate}); + SimulateDidDiscoverServicesMac(device); + EXPECT_EQ(1u, device->GetGattServices().size()); + BluetoothRemoteGattService* service = device->GetGattServices()[0]; + std::string characteristic_uuid = "11111111-0000-1000-8000-00805f9b34fb"; + AddCharacteristicToServiceMac(service, characteristic_uuid, + /* properties */ 0); + SimulateDidDiscoverCharacteristicsMac(service); + EXPECT_EQ(1u, service->GetCharacteristics().size()); + BluetoothRemoteGattCharacteristic* characteristic = + service->GetCharacteristics()[0]; + std::string descriptor_uuid = "22222222-0000-1000-8000-00805f9b34fb"; + AddDescriptorToCharacteristicMac(characteristic, descriptor_uuid); + SimulateDidDiscoverDescriptorsMac(characteristic); + EXPECT_EQ(1, observer.gatt_service_changed_count()); + EXPECT_EQ(1u, service->GetCharacteristics().size()); + EXPECT_EQ(1u, characteristic->GetDescriptors().size()); + + observer.Reset(); + SimulateDidDiscoverDescriptorsMac(characteristic); // Extra system call. + SimulateGattServicesChanged(device); + SimulateDidDiscoverDescriptorsMac(characteristic); // Extra system call. + SimulateDidDiscoverServicesMac(device); + SimulateDidDiscoverDescriptorsMac(characteristic); // Extra system call. + SimulateDidDiscoverCharacteristicsMac(service); + SimulateDidDiscoverDescriptorsMac(characteristic); + SimulateDidDiscoverDescriptorsMac(characteristic); // Extra system call. + EXPECT_EQ(2, observer.device_changed_count()); +} +#endif // defined(OS_MACOSX) } // namespace device diff --git a/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_win.cc b/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_win.cc index 633be1c9041..22d2e095655 100644 --- a/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_win.cc +++ b/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_win.cc @@ -28,7 +28,7 @@ BluetoothRemoteGattCharacteristicWin::BluetoothRemoteGattCharacteristicWin( gatt_event_registeration_in_progress_(false), gatt_event_handle_(nullptr), weak_ptr_factory_(this) { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); DCHECK(parent_service_); DCHECK(characteristic_info_); @@ -45,7 +45,7 @@ BluetoothRemoteGattCharacteristicWin::BluetoothRemoteGattCharacteristicWin( } BluetoothRemoteGattCharacteristicWin::~BluetoothRemoteGattCharacteristicWin() { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); ClearIncludedDescriptors(); @@ -154,7 +154,7 @@ BluetoothRemoteGattCharacteristicWin::GetDescriptor( void BluetoothRemoteGattCharacteristicWin::StartNotifySession( const NotifySessionCallback& callback, const ErrorCallback& error_callback) { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); if (IsNotifying()) { std::unique_ptr<BluetoothGattNotifySession> notify_session( @@ -222,7 +222,7 @@ void BluetoothRemoteGattCharacteristicWin::StopNotifySession( void BluetoothRemoteGattCharacteristicWin::ReadRemoteCharacteristic( const ValueCallback& callback, const ErrorCallback& error_callback) { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); if (!characteristic_info_.get()->IsReadable) { error_callback.Run(BluetoothRemoteGattService::GATT_ERROR_NOT_PERMITTED); @@ -248,7 +248,7 @@ void BluetoothRemoteGattCharacteristicWin::WriteRemoteCharacteristic( const std::vector<uint8_t>& value, const base::Closure& callback, const ErrorCallback& error_callback) { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); if (!characteristic_info_.get()->IsWritable) { error_callback.Run(BluetoothRemoteGattService::GATT_ERROR_NOT_PERMITTED); @@ -271,7 +271,7 @@ void BluetoothRemoteGattCharacteristicWin::WriteRemoteCharacteristic( } void BluetoothRemoteGattCharacteristicWin::Update() { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); task_manager_->PostGetGattIncludedDescriptors( parent_service_->GetServicePath(), characteristic_info_.get(), @@ -304,7 +304,7 @@ void BluetoothRemoteGattCharacteristicWin::OnGetIncludedDescriptorsCallback( std::unique_ptr<BTH_LE_GATT_DESCRIPTOR> descriptors, uint16_t num, HRESULT hr) { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); UpdateIncludedDescriptors(descriptors.get(), num); if (!characteristic_added_notified_) { @@ -386,7 +386,7 @@ void BluetoothRemoteGattCharacteristicWin:: OnReadRemoteCharacteristicValueCallback( std::unique_ptr<BTH_LE_GATT_CHARACTERISTIC_VALUE> value, HRESULT hr) { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); std::pair<ValueCallback, ErrorCallback> callbacks; callbacks.swap(read_characteristic_value_callbacks_); @@ -404,7 +404,7 @@ void BluetoothRemoteGattCharacteristicWin:: void BluetoothRemoteGattCharacteristicWin:: OnWriteRemoteCharacteristicValueCallback(HRESULT hr) { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); std::pair<base::Closure, ErrorCallback> callbacks; callbacks.swap(write_characteristic_value_callbacks_); @@ -438,7 +438,7 @@ BluetoothRemoteGattCharacteristicWin::HRESULTToGattErrorCode(HRESULT hr) { void BluetoothRemoteGattCharacteristicWin::OnGattCharacteristicValueChanged( std::unique_ptr<std::vector<uint8_t>> new_value) { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); characteristic_value_.assign(new_value->begin(), new_value->end()); parent_service_->GetWinAdapter()->NotifyGattCharacteristicValueChanged( @@ -448,7 +448,7 @@ void BluetoothRemoteGattCharacteristicWin::OnGattCharacteristicValueChanged( void BluetoothRemoteGattCharacteristicWin::GattEventRegistrationCallback( BLUETOOTH_GATT_EVENT_HANDLE event_handle, HRESULT hr) { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); gatt_event_registeration_in_progress_ = false; std::vector<std::pair<NotifySessionCallback, ErrorCallback>> callbacks; diff --git a/chromium/device/bluetooth/bluetooth_remote_gatt_descriptor_mac.mm b/chromium/device/bluetooth/bluetooth_remote_gatt_descriptor_mac.mm index d7c5d6c79dc..a8ede9c1490 100644 --- a/chromium/device/bluetooth/bluetooth_remote_gatt_descriptor_mac.mm +++ b/chromium/device/bluetooth/bluetooth_remote_gatt_descriptor_mac.mm @@ -189,7 +189,7 @@ DEVICE_BLUETOOTH_EXPORT std::ostream& operator<<( const BluetoothRemoteGattCharacteristicMac* characteristic_mac = static_cast<const BluetoothRemoteGattCharacteristicMac*>( descriptor.GetCharacteristic()); - return out << "<BluetoothRemoteGattServiceMac " + return out << "<BluetoothRemoteGattDescriptorMac " << descriptor.GetUUID().canonical_value() << "/" << &descriptor << ", characteristic: " << characteristic_mac->GetUUID().canonical_value() << "/" diff --git a/chromium/device/bluetooth/bluetooth_remote_gatt_descriptor_unittest.cc b/chromium/device/bluetooth/bluetooth_remote_gatt_descriptor_unittest.cc index a43c0e7f5dc..6a500a83434 100644 --- a/chromium/device/bluetooth/bluetooth_remote_gatt_descriptor_unittest.cc +++ b/chromium/device/bluetooth/bluetooth_remote_gatt_descriptor_unittest.cc @@ -780,7 +780,7 @@ TEST_F(BluetoothRemoteGattDescriptorTest, ReadRemoteDescriptor_NSString) { EXPECT_EQ(1, gatt_read_descriptor_attempts_); std::string test_string = "Hello"; - SimulateGattDescriptorReadNSString(descriptor1_, test_string); + SimulateGattDescriptorReadNSStringMac(descriptor1_, test_string); base::RunLoop().RunUntilIdle(); std::vector<uint8_t> test_vector(test_string.begin(), test_string.end()); @@ -802,7 +802,7 @@ TEST_F(BluetoothRemoteGattDescriptorTest, ReadRemoteDescriptor_NSNumber) { EXPECT_EQ(1, gatt_read_descriptor_attempts_); const short test_number = 0x1234; - SimulateGattDescriptorReadNSNumber(descriptor1_, test_number); + SimulateGattDescriptorReadNSNumberMac(descriptor1_, test_number); base::RunLoop().RunUntilIdle(); uint8_t values[] = {0x34, 0x12}; diff --git a/chromium/device/bluetooth/bluetooth_remote_gatt_descriptor_win.cc b/chromium/device/bluetooth/bluetooth_remote_gatt_descriptor_win.cc index fb98e1ee70f..4829188af0d 100644 --- a/chromium/device/bluetooth/bluetooth_remote_gatt_descriptor_win.cc +++ b/chromium/device/bluetooth/bluetooth_remote_gatt_descriptor_win.cc @@ -19,7 +19,7 @@ BluetoothRemoteGattDescriptorWin::BluetoothRemoteGattDescriptorWin( descriptor_info_(descriptor_info), ui_task_runner_(ui_task_runner), weak_ptr_factory_(this) { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); DCHECK(parent_characteristic_); DCHECK(descriptor_info_.get()); @@ -38,7 +38,7 @@ BluetoothRemoteGattDescriptorWin::BluetoothRemoteGattDescriptorWin( } BluetoothRemoteGattDescriptorWin::~BluetoothRemoteGattDescriptorWin() { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); parent_characteristic_->GetWinService() ->GetWinAdapter() @@ -72,7 +72,7 @@ BluetoothRemoteGattDescriptorWin::GetPermissions() const { void BluetoothRemoteGattDescriptorWin::ReadRemoteDescriptor( const ValueCallback& callback, const ErrorCallback& error_callback) { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); NOTIMPLEMENTED(); error_callback.Run(BluetoothRemoteGattService::GATT_ERROR_NOT_SUPPORTED); @@ -82,7 +82,7 @@ void BluetoothRemoteGattDescriptorWin::WriteRemoteDescriptor( const std::vector<uint8_t>& new_value, const base::Closure& callback, const ErrorCallback& error_callback) { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); NOTIMPLEMENTED(); error_callback.Run(BluetoothRemoteGattService::GATT_ERROR_NOT_SUPPORTED); diff --git a/chromium/device/bluetooth/bluetooth_remote_gatt_service_mac.h b/chromium/device/bluetooth/bluetooth_remote_gatt_service_mac.h index 1c5d1c834de..832e41d0517 100644 --- a/chromium/device/bluetooth/bluetooth_remote_gatt_service_mac.h +++ b/chromium/device/bluetooth/bluetooth_remote_gatt_service_mac.h @@ -96,8 +96,12 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothRemoteGattServiceMac std::string identifier_; // Service UUID. BluetoothUUID uuid_; - // Is true if the characteristics has been discovered. + // Is true if the characteristics has been discovered and + // discovery_pending_count_ is 0. bool is_discovery_complete_; + // Increased each time DiscoverCharacteristics() is called. And decreased when + // DidDiscoverCharacteristics() is called. + int discovery_pending_count_; DISALLOW_COPY_AND_ASSIGN(BluetoothRemoteGattServiceMac); }; diff --git a/chromium/device/bluetooth/bluetooth_remote_gatt_service_mac.mm b/chromium/device/bluetooth/bluetooth_remote_gatt_service_mac.mm index 5d2b736e551..5fdf6741f9a 100644 --- a/chromium/device/bluetooth/bluetooth_remote_gatt_service_mac.mm +++ b/chromium/device/bluetooth/bluetooth_remote_gatt_service_mac.mm @@ -23,7 +23,8 @@ BluetoothRemoteGattServiceMac::BluetoothRemoteGattServiceMac( : bluetooth_device_mac_(bluetooth_device_mac), service_(service, base::scoped_policy::RETAIN), is_primary_(is_primary), - is_discovery_complete_(false) { + is_discovery_complete_(false), + discovery_pending_count_(0) { uuid_ = BluetoothAdapterMac::BluetoothUUIDWithCBUUID([service_.get() UUID]); identifier_ = [NSString stringWithFormat:@"%s-%p", uuid_.canonical_value().c_str(), @@ -80,12 +81,21 @@ BluetoothRemoteGattServiceMac::GetCharacteristic( void BluetoothRemoteGattServiceMac::DiscoverCharacteristics() { VLOG(1) << *this << ": DiscoverCharacteristics."; is_discovery_complete_ = false; + ++discovery_pending_count_; [GetCBPeripheral() discoverCharacteristics:nil forService:GetService()]; } void BluetoothRemoteGattServiceMac::DidDiscoverCharacteristics() { - DCHECK(!is_discovery_complete_); + if (is_discovery_complete_ || discovery_pending_count_ == 0) { + // This should never happen, just in case it happens with a device, this + // notification should be ignored. + VLOG(1) + << *this + << ": Unmatch DiscoverCharacteristics and DidDiscoverCharacteristics."; + return; + } VLOG(1) << *this << ": DidDiscoverCharacteristics."; + --discovery_pending_count_; std::unordered_set<std::string> characteristic_identifier_to_remove; for (const auto& iter : gatt_characteristic_macs_) { characteristic_identifier_to_remove.insert(iter.first); @@ -111,7 +121,9 @@ void BluetoothRemoteGattServiceMac::DidDiscoverCharacteristics() { DCHECK(result_iter.second); VLOG(1) << *gatt_characteristic_mac << ": New characteristic, properties " << gatt_characteristic_mac->GetProperties(); - gatt_characteristic_mac->DiscoverDescriptors(); + if (discovery_pending_count_ == 0) { + gatt_characteristic_mac->DiscoverDescriptors(); + } GetMacAdapter()->NotifyGattCharacteristicAdded(gatt_characteristic_mac); } @@ -130,7 +142,13 @@ void BluetoothRemoteGattServiceMac::DidDiscoverCharacteristics() { void BluetoothRemoteGattServiceMac::DidDiscoverDescriptors( CBCharacteristic* characteristic) { - DCHECK(!is_discovery_complete_); + if (is_discovery_complete_) { + // This should never happen, just in case it happens with a device, this + // notification should be ignored. + VLOG(1) << *this + << ": Discovery complete, ignoring DidDiscoverDescriptors."; + return; + } BluetoothRemoteGattCharacteristicMac* gatt_characteristic = GetBluetoothRemoteGattCharacteristicMac(characteristic); DCHECK(gatt_characteristic); @@ -142,6 +160,7 @@ void BluetoothRemoteGattServiceMac::SendNotificationIfComplete() { DCHECK(!is_discovery_complete_); // Notify when all characteristics have been fully discovered. is_discovery_complete_ = + discovery_pending_count_ == 0 && std::find_if_not( gatt_characteristic_macs_.begin(), gatt_characteristic_macs_.end(), [](const std::pair< diff --git a/chromium/device/bluetooth/bluetooth_remote_gatt_service_unittest.cc b/chromium/device/bluetooth/bluetooth_remote_gatt_service_unittest.cc index 2c86e620e5b..852d9b0c62a 100644 --- a/chromium/device/bluetooth/bluetooth_remote_gatt_service_unittest.cc +++ b/chromium/device/bluetooth/bluetooth_remote_gatt_service_unittest.cc @@ -171,7 +171,9 @@ TEST_F(BluetoothRemoteGattServiceTest, EXPECT_EQ(service->GetCharacteristic(char_id1), service->GetCharacteristic(char_id1)); } +#endif // defined(OS_ANDROID) || defined(OS_MACOSX) || defined(OS_WIN) +#if defined(OS_ANDROID) || defined(OS_MACOSX) || defined(OS_WIN) TEST_F(BluetoothRemoteGattServiceTest, GetCharacteristicsByUUID) { if (!PlatformSupportsLowEnergy()) { LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test."; @@ -336,6 +338,177 @@ TEST_F(BluetoothRemoteGattServiceTest, SimulateGattServiceRemove) { EXPECT_FALSE(device->GetGattService(removed_service)); EXPECT_EQ(device->GetGattServices()[0], service2); } -#endif // defined(OS_WIN) || defined(OS_MACOSX) +#endif // defined(OS_MACOSX) || defined(OS_WIN) + +#if defined(OS_MACOSX) +// Tests to receive a services changed notification from macOS, while +// discovering characteristics. The gatt device should scan again for services +// and characteristics, before scanning for descriptors. Only after the gatt +// service changed notification should be sent. +// Android: This test doesn't apply to Android because there is no services +// changed event that could arrive during a discovery procedure. +TEST_F(BluetoothRemoteGattServiceTest, + SimulateDeviceModificationWhileDiscoveringCharacteristics) { + if (!PlatformSupportsLowEnergy()) { + LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test."; + return; + } + InitWithFakeAdapter(); + StartLowEnergyDiscoverySession(); + BluetoothDevice* device = SimulateLowEnergyDevice(3); + device->CreateGattConnection(GetGattConnectionCallback(Call::EXPECTED), + GetConnectErrorCallback(Call::NOT_EXPECTED)); + + TestBluetoothAdapterObserver observer(adapter_); + + // Starts first discovery process. + SimulateGattConnection(device); + AddServicesToDeviceMac(device, {kTestUUIDHeartRate}); + SimulateDidDiscoverServicesMac(device); + EXPECT_EQ(1u, device->GetGattServices().size()); + BluetoothRemoteGattService* service = device->GetGattServices()[0]; + std::string characteristic_uuid1 = "11111111-0000-1000-8000-00805f9b34fb"; + AddCharacteristicToServiceMac(service, characteristic_uuid1, + /* properties */ 0); + // Now waiting for characteristic discovery. + + // Starts second discovery process. + SimulateGattServicesChanged(device); + SimulateDidDiscoverServicesMac(device); + // Now waiting for the second characteristic discovery. + + // First system call to -[id<CBPeripheralDelegate> + // peripheral:didDiscoverCharacteristicsForService:error:] + SimulateDidDiscoverCharacteristicsMac(service); + EXPECT_EQ(0, observer.gatt_service_changed_count()); + EXPECT_EQ(1u, service->GetCharacteristics().size()); + + // Finish discovery process. + std::string characteristic_uuid2 = "22222222-0000-1000-8000-00805f9b34fb"; + AddCharacteristicToServiceMac(service, characteristic_uuid2, + /* properties */ 0); + // Second system call to -[id<CBPeripheralDelegate> + // peripheral:didDiscoverCharacteristicsForService:error:] + SimulateDidDiscoverCharacteristicsMac(service); + EXPECT_EQ(2u, service->GetCharacteristics().size()); + EXPECT_EQ(0, observer.gatt_service_changed_count()); + BluetoothRemoteGattCharacteristic* characteristic1 = + service->GetCharacteristics()[0]; + BluetoothRemoteGattCharacteristic* characteristic2 = + service->GetCharacteristics()[1]; + if (characteristic1->GetUUID().canonical_value() == characteristic_uuid2) { + BluetoothRemoteGattCharacteristic* tmp = characteristic1; + characteristic1 = characteristic2; + characteristic2 = tmp; + } + EXPECT_EQ(characteristic_uuid1, characteristic1->GetUUID().canonical_value()); + EXPECT_EQ(characteristic_uuid2, characteristic2->GetUUID().canonical_value()); + SimulateDidDiscoverDescriptorsMac(characteristic1); + SimulateDidDiscoverDescriptorsMac(characteristic2); + EXPECT_EQ(1, observer.gatt_service_changed_count()); +} +#endif // defined(OS_MACOSX) + +#if defined(OS_MACOSX) +// Simulates to receive an extra discovery characteristic notifications from +// macOS. Those notifications should be ignored. +// Android: This test doesn't apply to Android because there is no services +// changed event that could arrive during a discovery procedure. +TEST_F(BluetoothRemoteGattServiceTest, ExtraDidDiscoverServicesCall) { + if (!PlatformSupportsLowEnergy()) { + LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test."; + return; + } + InitWithFakeAdapter(); + StartLowEnergyDiscoverySession(); + BluetoothDevice* device = SimulateLowEnergyDevice(3); + device->CreateGattConnection(GetGattConnectionCallback(Call::EXPECTED), + GetConnectErrorCallback(Call::NOT_EXPECTED)); + + TestBluetoothAdapterObserver observer(adapter_); + + // Starts first discovery process. + SimulateGattConnection(device); + AddServicesToDeviceMac(device, {kTestUUIDHeartRate}); + SimulateDidDiscoverServicesMac(device); + EXPECT_EQ(1u, device->GetGattServices().size()); + BluetoothRemoteGattService* service = device->GetGattServices()[0]; + std::string characteristic_uuid = "11111111-0000-1000-8000-00805f9b34fb"; + AddCharacteristicToServiceMac(service, characteristic_uuid, + /* properties */ 0); + SimulateDidDiscoverCharacteristicsMac(service); + EXPECT_EQ(1u, service->GetCharacteristics().size()); + BluetoothRemoteGattCharacteristic* characteristic = + service->GetCharacteristics()[0]; + std::string descriptor_uuid = "22222222-0000-1000-8000-00805f9b34fb"; + AddDescriptorToCharacteristicMac(characteristic, descriptor_uuid); + SimulateDidDiscoverDescriptorsMac(characteristic); + EXPECT_EQ(1, observer.gatt_service_changed_count()); + EXPECT_EQ(1u, service->GetCharacteristics().size()); + EXPECT_EQ(1u, characteristic->GetDescriptors().size()); + + observer.Reset(); + SimulateDidDiscoverServicesMac(device); // Extra system call. + SimulateGattServicesChanged(device); + SimulateDidDiscoverServicesMac(device); + SimulateDidDiscoverServicesMac(device); // Extra system call. + SimulateDidDiscoverCharacteristicsMac(service); + SimulateDidDiscoverServicesMac(device); // Extra system call. + SimulateDidDiscoverDescriptorsMac(characteristic); + SimulateDidDiscoverServicesMac(device); // Extra system call. + EXPECT_EQ(2, observer.device_changed_count()); +} +#endif // defined(OS_MACOSX) + +#if defined(OS_MACOSX) +// Simulates to receive an extra discovery characteristic notifications from +// macOS. Those notifications should be ignored. +// Android: This test doesn't apply to Android because there is no services +// changed event that could arrive during a discovery procedure. +TEST_F(BluetoothRemoteGattServiceTest, ExtraDidDiscoverCharacteristicsCall) { + if (!PlatformSupportsLowEnergy()) { + LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test."; + return; + } + InitWithFakeAdapter(); + StartLowEnergyDiscoverySession(); + BluetoothDevice* device = SimulateLowEnergyDevice(3); + device->CreateGattConnection(GetGattConnectionCallback(Call::EXPECTED), + GetConnectErrorCallback(Call::NOT_EXPECTED)); + + TestBluetoothAdapterObserver observer(adapter_); + + // Starts first discovery process. + SimulateGattConnection(device); + AddServicesToDeviceMac(device, {kTestUUIDHeartRate}); + SimulateDidDiscoverServicesMac(device); + EXPECT_EQ(1u, device->GetGattServices().size()); + BluetoothRemoteGattService* service = device->GetGattServices()[0]; + std::string characteristic_uuid = "11111111-0000-1000-8000-00805f9b34fb"; + AddCharacteristicToServiceMac(service, characteristic_uuid, + /* properties */ 0); + SimulateDidDiscoverCharacteristicsMac(service); + EXPECT_EQ(1u, service->GetCharacteristics().size()); + BluetoothRemoteGattCharacteristic* characteristic = + service->GetCharacteristics()[0]; + std::string descriptor_uuid = "22222222-0000-1000-8000-00805f9b34fb"; + AddDescriptorToCharacteristicMac(characteristic, descriptor_uuid); + SimulateDidDiscoverDescriptorsMac(characteristic); + EXPECT_EQ(1, observer.gatt_service_changed_count()); + EXPECT_EQ(1u, service->GetCharacteristics().size()); + EXPECT_EQ(1u, characteristic->GetDescriptors().size()); + + observer.Reset(); + SimulateDidDiscoverCharacteristicsMac(service); // Extra system call. + SimulateGattServicesChanged(device); + SimulateDidDiscoverCharacteristicsMac(service); // Extra system call. + SimulateDidDiscoverServicesMac(device); + SimulateDidDiscoverCharacteristicsMac(service); + SimulateDidDiscoverCharacteristicsMac(service); // Extra system call. + SimulateDidDiscoverDescriptorsMac(characteristic); + SimulateDidDiscoverCharacteristicsMac(service); // Extra system call. + EXPECT_EQ(2, observer.device_changed_count()); +} +#endif // defined(OS_MACOSX) } // namespace device diff --git a/chromium/device/bluetooth/bluetooth_remote_gatt_service_win.cc b/chromium/device/bluetooth/bluetooth_remote_gatt_service_win.cc index 5394abe4254..82d701a572f 100644 --- a/chromium/device/bluetooth/bluetooth_remote_gatt_service_win.cc +++ b/chromium/device/bluetooth/bluetooth_remote_gatt_service_win.cc @@ -33,7 +33,7 @@ BluetoothRemoteGattServiceWin::BluetoothRemoteGattServiceWin( discovery_complete_notified_(false), included_characteristics_discovered_(false), weak_ptr_factory_(this) { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); DCHECK(!service_path_.empty()); DCHECK(service_uuid_.IsValid()); DCHECK(service_attribute_handle_); @@ -51,7 +51,7 @@ BluetoothRemoteGattServiceWin::BluetoothRemoteGattServiceWin( } BluetoothRemoteGattServiceWin::~BluetoothRemoteGattServiceWin() { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); ClearIncludedCharacteristics(); @@ -101,7 +101,7 @@ BluetoothRemoteGattServiceWin::GetCharacteristic( void BluetoothRemoteGattServiceWin::GattCharacteristicDiscoveryComplete( BluetoothRemoteGattCharacteristicWin* characteristic) { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); DCHECK(included_characteristics_.find(characteristic->GetIdentifier()) != included_characteristics_.end()); @@ -112,7 +112,7 @@ void BluetoothRemoteGattServiceWin::GattCharacteristicDiscoveryComplete( } void BluetoothRemoteGattServiceWin::Update() { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); task_manager_->PostGetGattIncludedCharacteristics( service_path_, service_uuid_, service_attribute_handle_, @@ -124,7 +124,7 @@ void BluetoothRemoteGattServiceWin::OnGetIncludedCharacteristics( std::unique_ptr<BTH_LE_GATT_CHARACTERISTIC> characteristics, uint16_t num, HRESULT hr) { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); UpdateIncludedCharacteristics(characteristics.get(), num); included_characteristics_discovered_ = true; diff --git a/chromium/device/bluetooth/bluetooth_remote_gatt_service_win.h b/chromium/device/bluetooth/bluetooth_remote_gatt_service_win.h index 8f6fa43b057..32a3933955b 100644 --- a/chromium/device/bluetooth/bluetooth_remote_gatt_service_win.h +++ b/chromium/device/bluetooth/bluetooth_remote_gatt_service_win.h @@ -7,6 +7,7 @@ #include <memory> #include <set> +#include <unordered_map> #include "base/files/file.h" #include "base/memory/weak_ptr.h" diff --git a/chromium/device/bluetooth/bluetooth_socket_net.cc b/chromium/device/bluetooth/bluetooth_socket_net.cc index 0be52c8d225..e029f4d7763 100644 --- a/chromium/device/bluetooth/bluetooth_socket_net.cc +++ b/chromium/device/bluetooth/bluetooth_socket_net.cc @@ -44,7 +44,7 @@ BluetoothSocketNet::BluetoothSocketNet( scoped_refptr<BluetoothSocketThread> socket_thread) : ui_task_runner_(ui_task_runner), socket_thread_(socket_thread) { - DCHECK(ui_task_runner->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner->RunsTasksInCurrentSequence()); socket_thread_->OnSocketActivate(); } @@ -55,14 +55,14 @@ BluetoothSocketNet::~BluetoothSocketNet() { } void BluetoothSocketNet::Close() { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); socket_thread_->task_runner()->PostTask( FROM_HERE, base::Bind(&BluetoothSocketNet::DoClose, this)); } void BluetoothSocketNet::Disconnect( const base::Closure& success_callback) { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); socket_thread_->task_runner()->PostTask( FROM_HERE, base::Bind( @@ -77,7 +77,7 @@ void BluetoothSocketNet::Receive( int buffer_size, const ReceiveCompletionCallback& success_callback, const ReceiveErrorCompletionCallback& error_callback) { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); socket_thread_->task_runner()->PostTask( FROM_HERE, base::Bind( @@ -97,7 +97,7 @@ void BluetoothSocketNet::Send( int buffer_size, const SendCompletionCallback& success_callback, const ErrorCompletionCallback& error_callback) { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); socket_thread_->task_runner()->PostTask( FROM_HERE, base::Bind( @@ -136,7 +136,7 @@ void BluetoothSocketNet::PostErrorCompletion( } void BluetoothSocketNet::DoClose() { - DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread()); + DCHECK(socket_thread_->task_runner()->RunsTasksInCurrentSequence()); base::ThreadRestrictions::AssertIOAllowed(); if (tcp_socket_) { @@ -155,7 +155,7 @@ void BluetoothSocketNet::DoClose() { } void BluetoothSocketNet::DoDisconnect(const base::Closure& callback) { - DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread()); + DCHECK(socket_thread_->task_runner()->RunsTasksInCurrentSequence()); base::ThreadRestrictions::AssertIOAllowed(); DoClose(); @@ -166,7 +166,7 @@ void BluetoothSocketNet::DoReceive( int buffer_size, const ReceiveCompletionCallback& success_callback, const ReceiveErrorCompletionCallback& error_callback) { - DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread()); + DCHECK(socket_thread_->task_runner()->RunsTasksInCurrentSequence()); base::ThreadRestrictions::AssertIOAllowed(); if (!tcp_socket_) { @@ -200,7 +200,7 @@ void BluetoothSocketNet::OnSocketReadComplete( const ReceiveCompletionCallback& success_callback, const ReceiveErrorCompletionCallback& error_callback, int read_result) { - DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread()); + DCHECK(socket_thread_->task_runner()->RunsTasksInCurrentSequence()); base::ThreadRestrictions::AssertIOAllowed(); scoped_refptr<net::IOBufferWithSize> buffer; @@ -223,7 +223,7 @@ void BluetoothSocketNet::DoSend( int buffer_size, const SendCompletionCallback& success_callback, const ErrorCompletionCallback& error_callback) { - DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread()); + DCHECK(socket_thread_->task_runner()->RunsTasksInCurrentSequence()); base::ThreadRestrictions::AssertIOAllowed(); if (!tcp_socket_) { @@ -244,7 +244,7 @@ void BluetoothSocketNet::DoSend( } void BluetoothSocketNet::SendFrontWriteRequest() { - DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread()); + DCHECK(socket_thread_->task_runner()->RunsTasksInCurrentSequence()); base::ThreadRestrictions::AssertIOAllowed(); if (!tcp_socket_) @@ -270,7 +270,7 @@ void BluetoothSocketNet::OnSocketWriteComplete( const SendCompletionCallback& success_callback, const ErrorCompletionCallback& error_callback, int send_result) { - DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread()); + DCHECK(socket_thread_->task_runner()->RunsTasksInCurrentSequence()); base::ThreadRestrictions::AssertIOAllowed(); write_queue_.pop(); diff --git a/chromium/device/bluetooth/bluetooth_socket_thread.cc b/chromium/device/bluetooth/bluetooth_socket_thread.cc index 3788916cc69..c9fbb8adfb5 100644 --- a/chromium/device/bluetooth/bluetooth_socket_thread.cc +++ b/chromium/device/bluetooth/bluetooth_socket_thread.cc @@ -5,6 +5,7 @@ #include "device/bluetooth/bluetooth_socket_thread.h" #include "base/lazy_instance.h" +#include "base/message_loop/message_loop.h" #include "base/sequenced_task_runner.h" #include "base/threading/thread.h" diff --git a/chromium/device/bluetooth/bluetooth_socket_win.cc b/chromium/device/bluetooth/bluetooth_socket_win.cc index 0db3156a1e7..1906b0bce3d 100644 --- a/chromium/device/bluetooth/bluetooth_socket_win.cc +++ b/chromium/device/bluetooth/bluetooth_socket_win.cc @@ -78,7 +78,7 @@ scoped_refptr<BluetoothSocketWin> BluetoothSocketWin::CreateBluetoothSocket( scoped_refptr<base::SequencedTaskRunner> ui_task_runner, scoped_refptr<device::BluetoothSocketThread> socket_thread) { - DCHECK(ui_task_runner->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner->RunsTasksInCurrentSequence()); return make_scoped_refptr( new BluetoothSocketWin(ui_task_runner, socket_thread)); @@ -101,7 +101,7 @@ void BluetoothSocketWin::Connect( const BluetoothUUID& uuid, const base::Closure& success_callback, const ErrorCompletionCallback& error_callback) { - DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner()->RunsTasksInCurrentSequence()); DCHECK(device); if (!uuid.IsValid()) { @@ -138,7 +138,7 @@ void BluetoothSocketWin::Listen(scoped_refptr<BluetoothAdapter> adapter, const BluetoothAdapter::ServiceOptions& options, const base::Closure& success_callback, const ErrorCompletionCallback& error_callback) { - DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner()->RunsTasksInCurrentSequence()); adapter_ = adapter; int rfcomm_channel = options.channel ? *options.channel : 0; @@ -167,7 +167,7 @@ void BluetoothSocketWin::ResetData() { void BluetoothSocketWin::Accept( const AcceptCompletionCallback& success_callback, const ErrorCompletionCallback& error_callback) { - DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner()->RunsTasksInCurrentSequence()); socket_thread()->task_runner()->PostTask( FROM_HERE, @@ -180,7 +180,7 @@ void BluetoothSocketWin::Accept( void BluetoothSocketWin::DoConnect( const base::Closure& success_callback, const ErrorCompletionCallback& error_callback) { - DCHECK(socket_thread()->task_runner()->RunsTasksOnCurrentThread()); + DCHECK(socket_thread()->task_runner()->RunsTasksInCurrentSequence()); base::ThreadRestrictions::AssertIOAllowed(); if (tcp_socket()) { @@ -237,7 +237,7 @@ void BluetoothSocketWin::DoListen( int rfcomm_channel, const base::Closure& success_callback, const ErrorCompletionCallback& error_callback) { - DCHECK(socket_thread()->task_runner()->RunsTasksOnCurrentThread()); + DCHECK(socket_thread()->task_runner()->RunsTasksInCurrentSequence()); DCHECK(!tcp_socket() && !service_reg_data_); // The valid range is 0-30. 0 means BT_PORT_ANY and 1-30 are the @@ -263,7 +263,7 @@ void BluetoothSocketWin::DoListen( // is called on |socket_fd| directly. std::unique_ptr<net::TCPSocket> scoped_socket( new net::TCPSocket(NULL, NULL, net::NetLogSource())); - scoped_socket->AdoptListenSocket(socket_fd); + scoped_socket->AdoptUnconnectedSocket(socket_fd); SOCKADDR_BTH sa; struct sockaddr* sock_addr = reinterpret_cast<struct sockaddr*>(&sa); @@ -337,7 +337,7 @@ void BluetoothSocketWin::DoListen( void BluetoothSocketWin::DoAccept( const AcceptCompletionCallback& success_callback, const ErrorCompletionCallback& error_callback) { - DCHECK(socket_thread()->task_runner()->RunsTasksOnCurrentThread()); + DCHECK(socket_thread()->task_runner()->RunsTasksInCurrentSequence()); int result = tcp_socket()->Accept( &accept_socket_, &accept_address_, @@ -355,7 +355,7 @@ void BluetoothSocketWin::OnAcceptOnSocketThread( const AcceptCompletionCallback& success_callback, const ErrorCompletionCallback& error_callback, int accept_result) { - DCHECK(socket_thread()->task_runner()->RunsTasksOnCurrentThread()); + DCHECK(socket_thread()->task_runner()->RunsTasksInCurrentSequence()); if (accept_result != net::OK) { LOG(WARNING) << "OnAccept error, net err=" << accept_result; PostErrorCompletion(error_callback, kFailedToAccept); @@ -377,7 +377,7 @@ void BluetoothSocketWin::OnAcceptOnUI( const net::IPEndPoint& peer_address, const AcceptCompletionCallback& success_callback, const ErrorCompletionCallback& error_callback) { - DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner()->RunsTasksInCurrentSequence()); const std::string peer_device_address = IPEndPointToBluetoothAddress(peer_address); diff --git a/chromium/device/bluetooth/bluetooth_socket_win.h b/chromium/device/bluetooth/bluetooth_socket_win.h index 644cf14f39c..42985b8beed 100644 --- a/chromium/device/bluetooth/bluetooth_socket_win.h +++ b/chromium/device/bluetooth/bluetooth_socket_win.h @@ -13,6 +13,7 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" +#include "base/sequenced_task_runner.h" #include "device/bluetooth/bluetooth_adapter.h" #include "device/bluetooth/bluetooth_service_record_win.h" #include "device/bluetooth/bluetooth_socket.h" diff --git a/chromium/device/bluetooth/bluetooth_task_manager_win.cc b/chromium/device/bluetooth/bluetooth_task_manager_win.cc index 2d709a497ad..3ff03651596 100644 --- a/chromium/device/bluetooth/bluetooth_task_manager_win.cc +++ b/chromium/device/bluetooth/bluetooth_task_manager_win.cc @@ -13,11 +13,10 @@ #include "base/bind.h" #include "base/memory/ptr_util.h" #include "base/memory/ref_counted.h" -#include "base/message_loop/message_loop.h" #include "base/sequenced_task_runner.h" #include "base/strings/stringprintf.h" #include "base/strings/sys_string_conversions.h" -#include "base/threading/sequenced_worker_pool.h" +#include "base/task_scheduler/post_task.h" #include "device/bluetooth/bluetooth_classic_win.h" #include "device/bluetooth/bluetooth_device.h" #include "device/bluetooth/bluetooth_init_win.h" @@ -26,8 +25,6 @@ namespace { -const int kNumThreadsInWorkerPool = 3; -const char kBluetoothThreadName[] = "BluetoothPollingThreadWin"; const int kMaxNumDeviceAddressChar = 127; const int kServiceDiscoveryResultBufferSize = 5000; @@ -246,30 +243,26 @@ BluetoothUUID BluetoothTaskManagerWin::BluetoothLowEnergyUuidToBluetoothUuid( void BluetoothTaskManagerWin::AddObserver(Observer* observer) { DCHECK(observer); - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); observers_.AddObserver(observer); } void BluetoothTaskManagerWin::RemoveObserver(Observer* observer) { DCHECK(observer); - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); observers_.RemoveObserver(observer); } void BluetoothTaskManagerWin::Initialize() { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); - worker_pool_ = new base::SequencedWorkerPool( - kNumThreadsInWorkerPool, kBluetoothThreadName, - base::TaskPriority::USER_VISIBLE); - InitializeWithBluetoothTaskRunner( - worker_pool_->GetSequencedTaskRunnerWithShutdownBehavior( - worker_pool_->GetSequenceToken(), - base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN)); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); + InitializeWithBluetoothTaskRunner(base::CreateSequencedTaskRunnerWithTraits( + {base::MayBlock(), base::TaskPriority::BACKGROUND, + base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN})); } void BluetoothTaskManagerWin::InitializeWithBluetoothTaskRunner( scoped_refptr<base::SequencedTaskRunner> bluetooth_task_runner) { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); bluetooth_task_runner_ = bluetooth_task_runner; bluetooth_task_runner_->PostTask( FROM_HERE, @@ -277,7 +270,7 @@ void BluetoothTaskManagerWin::InitializeWithBluetoothTaskRunner( } void BluetoothTaskManagerWin::StartPolling() { - DCHECK(bluetooth_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(bluetooth_task_runner_->RunsTasksInCurrentSequence()); if (device::bluetooth_init_win::HasBluetoothStack()) { PollAdapter(); @@ -294,17 +287,11 @@ void BluetoothTaskManagerWin::StartPolling() { } } -void BluetoothTaskManagerWin::Shutdown() { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); - if (worker_pool_.get()) - worker_pool_->Shutdown(); -} - void BluetoothTaskManagerWin::PostSetPoweredBluetoothTask( bool powered, const base::Closure& callback, const BluetoothAdapter::ErrorCallback& error_callback) { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); bluetooth_task_runner_->PostTask( FROM_HERE, base::Bind(&BluetoothTaskManagerWin::SetPowered, @@ -315,14 +302,14 @@ void BluetoothTaskManagerWin::PostSetPoweredBluetoothTask( } void BluetoothTaskManagerWin::PostStartDiscoveryTask() { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); bluetooth_task_runner_->PostTask( FROM_HERE, base::Bind(&BluetoothTaskManagerWin::StartDiscovery, this)); } void BluetoothTaskManagerWin::PostStopDiscoveryTask() { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); bluetooth_task_runner_->PostTask( FROM_HERE, base::Bind(&BluetoothTaskManagerWin::StopDiscovery, this)); @@ -361,32 +348,32 @@ void BluetoothTaskManagerWin::LogPollingError(const char* message, } void BluetoothTaskManagerWin::OnAdapterStateChanged(const AdapterState* state) { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); for (auto& observer : observers_) observer.AdapterStateChanged(*state); } void BluetoothTaskManagerWin::OnDiscoveryStarted(bool success) { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); for (auto& observer : observers_) observer.DiscoveryStarted(success); } void BluetoothTaskManagerWin::OnDiscoveryStopped() { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); for (auto& observer : observers_) observer.DiscoveryStopped(); } void BluetoothTaskManagerWin::OnDevicesPolled( std::vector<std::unique_ptr<DeviceState>> devices) { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); for (auto& observer : observers_) observer.DevicesPolled(devices); } void BluetoothTaskManagerWin::PollAdapter() { - DCHECK(bluetooth_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(bluetooth_task_runner_->RunsTasksInCurrentSequence()); // Skips updating the adapter info if the adapter is in discovery mode. if (!discovering_) { @@ -415,7 +402,7 @@ void BluetoothTaskManagerWin::PollAdapter() { } void BluetoothTaskManagerWin::PostAdapterStateToUi() { - DCHECK(bluetooth_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(bluetooth_task_runner_->RunsTasksInCurrentSequence()); AdapterState* state = new AdapterState(); GetAdapterState(adapter_handle_, state); ui_task_runner_->PostTask( @@ -429,7 +416,7 @@ void BluetoothTaskManagerWin::SetPowered( bool powered, const base::Closure& callback, const BluetoothAdapter::ErrorCallback& error_callback) { - DCHECK(bluetooth_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(bluetooth_task_runner_->RunsTasksInCurrentSequence()); bool success = false; if (adapter_handle_) { if (!powered) { @@ -449,7 +436,7 @@ void BluetoothTaskManagerWin::SetPowered( } void BluetoothTaskManagerWin::StartDiscovery() { - DCHECK(bluetooth_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(bluetooth_task_runner_->RunsTasksInCurrentSequence()); ui_task_runner_->PostTask( FROM_HERE, base::Bind(&BluetoothTaskManagerWin::OnDiscoveryStarted, this, !!adapter_handle_)); @@ -461,7 +448,7 @@ void BluetoothTaskManagerWin::StartDiscovery() { } void BluetoothTaskManagerWin::StopDiscovery() { - DCHECK(bluetooth_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(bluetooth_task_runner_->RunsTasksInCurrentSequence()); discovering_ = false; ui_task_runner_->PostTask( FROM_HERE, @@ -469,7 +456,7 @@ void BluetoothTaskManagerWin::StopDiscovery() { } void BluetoothTaskManagerWin::DiscoverDevices(int timeout_multiplier) { - DCHECK(bluetooth_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(bluetooth_task_runner_->RunsTasksInCurrentSequence()); if (!discovering_ || !adapter_handle_) { ui_task_runner_->PostTask( FROM_HERE, @@ -603,7 +590,7 @@ bool BluetoothTaskManagerWin::SearchLowEnergyDevices( bool BluetoothTaskManagerWin::DiscoverServices( std::vector<std::unique_ptr<DeviceState>>* device_list, bool search_cached_services_only) { - DCHECK(bluetooth_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(bluetooth_task_runner_->RunsTasksInCurrentSequence()); net::EnsureWinsockInit(); for (const auto& device : *device_list) { std::vector<std::unique_ptr<ServiceRecordState>>* service_record_states = @@ -897,7 +884,7 @@ void BluetoothTaskManagerWin::RegisterGattCharacteristicValueChangedEvent( BTH_LE_GATT_DESCRIPTOR ccc_descriptor, const GattEventRegistrationCallback& callback, const GattCharacteristicValueChangedCallback& registered_callback) { - DCHECK(bluetooth_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(bluetooth_task_runner_->RunsTasksInCurrentSequence()); BLUETOOTH_GATT_EVENT_HANDLE win_event_handle = NULL; BLUETOOTH_GATT_VALUE_CHANGED_EVENT_REGISTRATION win_event_parameter; @@ -945,7 +932,7 @@ void BluetoothTaskManagerWin::RegisterGattCharacteristicValueChangedEvent( void BluetoothTaskManagerWin::UnregisterGattCharacteristicValueChangedEvent( PVOID event_handle) { - DCHECK(bluetooth_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(bluetooth_task_runner_->RunsTasksInCurrentSequence()); base::AutoLock auto_lock(g_characteristic_value_changed_registrations_lock); CharacteristicValueChangedRegistrationMap::const_iterator it = @@ -962,7 +949,7 @@ void BluetoothTaskManagerWin::PostGetGattIncludedCharacteristics( const BluetoothUUID& uuid, uint16_t attribute_handle, const GetGattIncludedCharacteristicsCallback& callback) { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); bluetooth_task_runner_->PostTask( FROM_HERE, base::Bind(&BluetoothTaskManagerWin::GetGattIncludedCharacteristics, this, @@ -973,7 +960,7 @@ void BluetoothTaskManagerWin::PostGetGattIncludedDescriptors( const base::FilePath& service_path, const PBTH_LE_GATT_CHARACTERISTIC characteristic, const GetGattIncludedDescriptorsCallback& callback) { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); bluetooth_task_runner_->PostTask( FROM_HERE, base::Bind(&BluetoothTaskManagerWin::GetGattIncludedDescriptors, this, @@ -984,7 +971,7 @@ void BluetoothTaskManagerWin::PostReadGattCharacteristicValue( const base::FilePath& service_path, const PBTH_LE_GATT_CHARACTERISTIC characteristic, const ReadGattCharacteristicValueCallback& callback) { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); bluetooth_task_runner_->PostTask( FROM_HERE, base::Bind(&BluetoothTaskManagerWin::ReadGattCharacteristicValue, this, @@ -996,7 +983,7 @@ void BluetoothTaskManagerWin::PostWriteGattCharacteristicValue( const PBTH_LE_GATT_CHARACTERISTIC characteristic, const std::vector<uint8_t>& new_value, const HResultCallback& callback) { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); bluetooth_task_runner_->PostTask( FROM_HERE, base::Bind(&BluetoothTaskManagerWin::WriteGattCharacteristicValue, this, @@ -1009,7 +996,7 @@ void BluetoothTaskManagerWin::PostRegisterGattCharacteristicValueChangedEvent( const PBTH_LE_GATT_DESCRIPTOR ccc_descriptor, const GattEventRegistrationCallback& callback, const GattCharacteristicValueChangedCallback& registered_callback) { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); bluetooth_task_runner_->PostTask( FROM_HERE, base::Bind( @@ -1020,7 +1007,7 @@ void BluetoothTaskManagerWin::PostRegisterGattCharacteristicValueChangedEvent( void BluetoothTaskManagerWin::PostUnregisterGattCharacteristicValueChangedEvent( PVOID event_handle) { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); bluetooth_task_runner_->PostTask( FROM_HERE, base::Bind(&BluetoothTaskManagerWin:: UnregisterGattCharacteristicValueChangedEvent, diff --git a/chromium/device/bluetooth/bluetooth_task_manager_win.h b/chromium/device/bluetooth/bluetooth_task_manager_win.h index 765dead2141..e10eb522f70 100644 --- a/chromium/device/bluetooth/bluetooth_task_manager_win.h +++ b/chromium/device/bluetooth/bluetooth_task_manager_win.h @@ -24,7 +24,6 @@ namespace base { class SequencedTaskRunner; -class SequencedWorkerPool; } // namespace base @@ -121,7 +120,6 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothTaskManagerWin void Initialize(); void InitializeWithBluetoothTaskRunner( scoped_refptr<base::SequencedTaskRunner> bluetooth_task_runner); - void Shutdown(); void PostSetPoweredBluetoothTask( bool powered, @@ -316,7 +314,6 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothTaskManagerWin // UI task runner reference. scoped_refptr<base::SequencedTaskRunner> ui_task_runner_; - scoped_refptr<base::SequencedWorkerPool> worker_pool_; scoped_refptr<base::SequencedTaskRunner> bluetooth_task_runner_; // List of observers interested in event notifications. diff --git a/chromium/device/bluetooth/bluez/bluetooth_adapter_bluez.cc b/chromium/device/bluetooth/bluez/bluetooth_adapter_bluez.cc index 83ade15bece..eb330ee637f 100644 --- a/chromium/device/bluetooth/bluez/bluetooth_adapter_bluez.cc +++ b/chromium/device/bluetooth/bluez/bluetooth_adapter_bluez.cc @@ -1455,17 +1455,12 @@ void BluetoothAdapterBlueZ::SetDiscoveryFilter( return; } - // If old and new filter are equal (null) then don't make request, just call - // succes callback - if (!current_filter_ && !discovery_filter.get()) { - callback.Run(); - return; - } - - // If old and new filter are not null and equal then don't make request, just - // call succes callback - if (current_filter_ && discovery_filter && - current_filter_->Equals(*discovery_filter)) { + // If the old and new filter are both null then don't make the request, and + // just call the success callback. + // Do the same if the old and new filter are both not null and equal. + if ((!current_filter_ && !discovery_filter.get()) || + (current_filter_ && discovery_filter && + current_filter_->Equals(*discovery_filter))) { callback.Run(); return; } diff --git a/chromium/device/bluetooth/bluez/bluetooth_adapter_profile_bluez_unittest.cc b/chromium/device/bluetooth/bluez/bluetooth_adapter_profile_bluez_unittest.cc index 779e9b702e7..a969fb07eed 100644 --- a/chromium/device/bluetooth/bluez/bluetooth_adapter_profile_bluez_unittest.cc +++ b/chromium/device/bluetooth/bluez/bluetooth_adapter_profile_bluez_unittest.cc @@ -7,8 +7,9 @@ #include <memory> #include "base/bind.h" +#include "base/message_loop/message_loop.h" #include "base/run_loop.h" -#include "base/test/scoped_task_scheduler.h" +#include "base/test/scoped_task_environment.h" #include "device/bluetooth/bluetooth_adapter.h" #include "device/bluetooth/bluetooth_adapter_factory.h" #include "device/bluetooth/bluetooth_uuid.h" @@ -78,10 +79,8 @@ class BluetoothAdapterProfileBlueZTest : public testing::Test { void AdapterCallback(scoped_refptr<BluetoothAdapter> adapter) { adapter_ = adapter; - if (base::MessageLoop::current() && - base::MessageLoop::current()->is_running()) { + if (base::RunLoop::IsRunningOnCurrentThread()) base::MessageLoop::current()->QuitWhenIdle(); - } } class FakeDelegate : public bluez::BluetoothProfileServiceProvider::Delegate { @@ -150,7 +149,7 @@ class BluetoothAdapterProfileBlueZTest : public testing::Test { } protected: - base::test::ScopedTaskScheduler scoped_task_scheduler_; + base::test::ScopedTaskEnvironment scoped_task_environment_; scoped_refptr<BluetoothAdapter> adapter_; diff --git a/chromium/device/bluetooth/bluez/bluetooth_advertisement_bluez_unittest.cc b/chromium/device/bluetooth/bluez/bluetooth_advertisement_bluez_unittest.cc index 1d2200535a4..3c7addf719a 100644 --- a/chromium/device/bluetooth/bluez/bluetooth_advertisement_bluez_unittest.cc +++ b/chromium/device/bluetooth/bluez/bluetooth_advertisement_bluez_unittest.cc @@ -93,10 +93,8 @@ class BluetoothAdvertisementBlueZTest : public testing::Test { adapter_ = adapter; ASSERT_NE(adapter_.get(), nullptr); ASSERT_TRUE(adapter_->IsInitialized()); - if (base::MessageLoop::current() && - base::MessageLoop::current()->is_running()) { + if (base::RunLoop::IsRunningOnCurrentThread()) base::MessageLoop::current()->QuitWhenIdle(); - } } std::unique_ptr<BluetoothAdvertisement::Data> CreateAdvertisementData() { diff --git a/chromium/device/bluetooth/bluez/bluetooth_bluez_unittest.cc b/chromium/device/bluetooth/bluez/bluetooth_bluez_unittest.cc index 74d88017fc7..6632d545665 100644 --- a/chromium/device/bluetooth/bluez/bluetooth_bluez_unittest.cc +++ b/chromium/device/bluetooth/bluez/bluetooth_bluez_unittest.cc @@ -164,10 +164,8 @@ class TestPairingDelegate : public BluetoothDevice::PairingDelegate { // Some tests use a message loop since background processing is simulated; // break out of those loops. void QuitMessageLoop() { - if (base::MessageLoop::current() && - base::MessageLoop::current()->is_running()) { + if (base::RunLoop::IsRunningOnCurrentThread()) base::MessageLoop::current()->QuitWhenIdle(); - } } }; @@ -362,10 +360,8 @@ class BluetoothBlueZTest : public testing::Test { // Some tests use a message loop since background processing is simulated; // break out of those loops. void QuitMessageLoop() { - if (base::MessageLoop::current() && - base::MessageLoop::current()->is_running()) { + if (base::RunLoop::IsRunningOnCurrentThread()) base::MessageLoop::current()->QuitWhenIdle(); - } } }; const char BluetoothBlueZTest::kGapUuid[] = diff --git a/chromium/device/bluetooth/bluez/bluetooth_device_bluez.cc b/chromium/device/bluetooth/bluez/bluetooth_device_bluez.cc index e89b725ba49..b56c0c006d8 100644 --- a/chromium/device/bluetooth/bluez/bluetooth_device_bluez.cc +++ b/chromium/device/bluetooth/bluez/bluetooth_device_bluez.cc @@ -40,6 +40,14 @@ using device::BluetoothUUID; namespace { +// The unit for connection interval values are in multiples of 1.25ms. +const uint16_t MIN_CONNECTION_INTERVAL_LOW = 6; +const uint16_t MAX_CONNECTION_INTERVAL_LOW = 6; +const uint16_t MIN_CONNECTION_INTERVAL_MEDIUM = 40; +const uint16_t MAX_CONNECTION_INTERVAL_MEDIUM = 56; +const uint16_t MIN_CONNECTION_INTERVAL_HIGH = 80; +const uint16_t MAX_CONNECTION_INTERVAL_HIGH = 100; + // Histogram enumerations for pairing results. enum UMAPairingResult { UMA_PAIRING_RESULT_SUCCESS, @@ -443,6 +451,47 @@ void BluetoothDeviceBlueZ::GetConnectionInfo( weak_ptr_factory_.GetWeakPtr(), callback)); } +void BluetoothDeviceBlueZ::SetConnectionLatency( + ConnectionLatency connection_latency, + const base::Closure& callback, + const ErrorCallback& error_callback) { + uint16_t min_connection_interval = MIN_CONNECTION_INTERVAL_MEDIUM; + uint16_t max_connection_interval = MAX_CONNECTION_INTERVAL_MEDIUM; + switch (connection_latency) { + case ConnectionLatency::CONNECTION_LATENCY_LOW: + min_connection_interval = MIN_CONNECTION_INTERVAL_LOW; + max_connection_interval = MAX_CONNECTION_INTERVAL_LOW; + break; + case ConnectionLatency::CONNECTION_LATENCY_MEDIUM: + min_connection_interval = MIN_CONNECTION_INTERVAL_MEDIUM; + max_connection_interval = MAX_CONNECTION_INTERVAL_MEDIUM; + break; + case ConnectionLatency::CONNECTION_LATENCY_HIGH: + min_connection_interval = MIN_CONNECTION_INTERVAL_HIGH; + max_connection_interval = MAX_CONNECTION_INTERVAL_HIGH; + break; + default: + NOTREACHED(); + break; + } + + BLUETOOTH_LOG(EVENT) << "Setting LE connection parameters: min=" + << min_connection_interval + << ", max=" << max_connection_interval; + bluez::BluetoothDeviceClient::ConnectionParameters connection_parameters; + connection_parameters.min_connection_interval = min_connection_interval; + connection_parameters.max_connection_interval = max_connection_interval; + + bluez::BluetoothDeviceClient* client = + bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient(); + client->SetLEConnectionParameters( + object_path_, connection_parameters, + base::Bind(&BluetoothDeviceBlueZ::OnSetLEConnectionParameters, + weak_ptr_factory_.GetWeakPtr(), callback), + base::Bind(&BluetoothDeviceBlueZ::OnSetLEConnectionParametersError, + weak_ptr_factory_.GetWeakPtr(), error_callback)); +} + void BluetoothDeviceBlueZ::Connect( BluetoothDevice::PairingDelegate* pairing_delegate, const base::Closure& callback, @@ -784,6 +833,21 @@ void BluetoothDeviceBlueZ::OnGetConnInfoError( callback.Run(ConnectionInfo()); } +void BluetoothDeviceBlueZ::OnSetLEConnectionParameters( + const base::Closure& callback) { + callback.Run(); +} + +void BluetoothDeviceBlueZ::OnSetLEConnectionParametersError( + const ErrorCallback& callback, + const std::string& error_name, + const std::string& error_message) { + BLUETOOTH_LOG(ERROR) << object_path_.value() + << ": Failed to set connection parameters: " + << error_name << ": " << error_message; + callback.Run(); +} + void BluetoothDeviceBlueZ::OnGetServiceRecordsError( const GetServiceRecordsErrorCallback& error_callback, const std::string& error_name, diff --git a/chromium/device/bluetooth/bluez/bluetooth_device_bluez.h b/chromium/device/bluetooth/bluez/bluetooth_device_bluez.h index 89e7ce77ef3..b6ddef83785 100644 --- a/chromium/device/bluetooth/bluez/bluetooth_device_bluez.h +++ b/chromium/device/bluetooth/bluez/bluetooth_device_bluez.h @@ -73,6 +73,9 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothDeviceBlueZ bool ExpectingPasskey() const override; bool ExpectingConfirmation() const override; void GetConnectionInfo(const ConnectionInfoCallback& callback) override; + void SetConnectionLatency(ConnectionLatency connection_latency, + const base::Closure& callback, + const ErrorCallback& error_callback) override; void Connect(device::BluetoothDevice::PairingDelegate* pairing_delegate, const base::Closure& callback, const ConnectErrorCallback& error_callback) override; @@ -187,6 +190,13 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothDeviceBlueZ const std::string& error_name, const std::string& error_message); + // Called by dbus:: on completion of the D-Bus method call to set the + // connection parameters of the device. + void OnSetLEConnectionParameters(const base::Closure& callback); + void OnSetLEConnectionParametersError(const ErrorCallback& callback, + const std::string& error_name, + const std::string& error_message); + // Called by dbus:: in case of an error during the GetServiceRecords API call. void OnGetServiceRecordsError( const GetServiceRecordsErrorCallback& error_callback, diff --git a/chromium/device/bluetooth/bluez/bluetooth_gatt_bluez_unittest.cc b/chromium/device/bluetooth/bluez/bluetooth_gatt_bluez_unittest.cc index 30eed1b86ea..fb0a052b07a 100644 --- a/chromium/device/bluetooth/bluez/bluetooth_gatt_bluez_unittest.cc +++ b/chromium/device/bluetooth/bluez/bluetooth_gatt_bluez_unittest.cc @@ -238,10 +238,8 @@ class BluetoothGattBlueZTest : public testing::Test { void AdapterCallback(scoped_refptr<BluetoothAdapter> adapter) { adapter_ = adapter; - if (base::MessageLoop::current() && - base::MessageLoop::current()->is_running()) { + if (base::RunLoop::IsRunningOnCurrentThread()) base::MessageLoop::current()->QuitWhenIdle(); - } } void SuccessCallback() { ++success_callback_count_; } @@ -281,8 +279,7 @@ class BluetoothGattBlueZTest : public testing::Test { protected: void QuitMessageLoop() { - if (base::MessageLoop::current() && - base::MessageLoop::current()->is_running()) + if (base::RunLoop::IsRunningOnCurrentThread()) base::MessageLoop::current()->QuitWhenIdle(); } diff --git a/chromium/device/bluetooth/bluez/bluetooth_socket_bluez.cc b/chromium/device/bluetooth/bluez/bluetooth_socket_bluez.cc index 98317efe034..bfa941d4438 100644 --- a/chromium/device/bluetooth/bluez/bluetooth_socket_bluez.cc +++ b/chromium/device/bluetooth/bluez/bluetooth_socket_bluez.cc @@ -23,7 +23,6 @@ #include "base/task_runner_util.h" #include "base/threading/thread_restrictions.h" #include "base/threading/thread_task_runner_handle.h" -#include "base/threading/worker_pool.h" #include "dbus/bus.h" #include "dbus/object_path.h" #include "device/bluetooth/bluetooth_adapter.h" @@ -61,7 +60,7 @@ namespace bluez { scoped_refptr<BluetoothSocketBlueZ> BluetoothSocketBlueZ::CreateBluetoothSocket( scoped_refptr<base::SequencedTaskRunner> ui_task_runner, scoped_refptr<BluetoothSocketThread> socket_thread) { - DCHECK(ui_task_runner->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner->RunsTasksInCurrentSequence()); return make_scoped_refptr( new BluetoothSocketBlueZ(ui_task_runner, socket_thread)); @@ -96,7 +95,7 @@ void BluetoothSocketBlueZ::Connect( SecurityLevel security_level, const base::Closure& success_callback, const ErrorCompletionCallback& error_callback) { - DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner()->RunsTasksInCurrentSequence()); DCHECK(!profile_); if (!uuid.IsValid()) { @@ -123,7 +122,7 @@ void BluetoothSocketBlueZ::Listen( const BluetoothAdapter::ServiceOptions& service_options, const base::Closure& success_callback, const ErrorCompletionCallback& error_callback) { - DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner()->RunsTasksInCurrentSequence()); DCHECK(!profile_); if (!uuid.IsValid()) { @@ -157,7 +156,7 @@ void BluetoothSocketBlueZ::Listen( } void BluetoothSocketBlueZ::Close() { - DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner()->RunsTasksInCurrentSequence()); if (profile_) UnregisterProfile(); @@ -179,7 +178,7 @@ void BluetoothSocketBlueZ::Close() { } void BluetoothSocketBlueZ::Disconnect(const base::Closure& callback) { - DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner()->RunsTasksInCurrentSequence()); if (profile_) UnregisterProfile(); @@ -195,7 +194,7 @@ void BluetoothSocketBlueZ::Disconnect(const base::Closure& callback) { void BluetoothSocketBlueZ::Accept( const AcceptCompletionCallback& success_callback, const ErrorCompletionCallback& error_callback) { - DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner()->RunsTasksInCurrentSequence()); if (!device_path_.value().empty()) { error_callback.Run(kSocketNotListening); @@ -221,7 +220,7 @@ void BluetoothSocketBlueZ::RegisterProfile( BluetoothAdapterBlueZ* adapter, const base::Closure& success_callback, const ErrorCompletionCallback& error_callback) { - DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner()->RunsTasksInCurrentSequence()); DCHECK(!profile_); DCHECK(adapter); @@ -249,7 +248,7 @@ void BluetoothSocketBlueZ::OnRegisterProfile( const base::Closure& success_callback, const ErrorCompletionCallback& error_callback, BluetoothAdapterProfileBlueZ* profile) { - DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner()->RunsTasksInCurrentSequence()); DCHECK(!profile_); profile_ = profile; @@ -274,7 +273,7 @@ void BluetoothSocketBlueZ::OnRegisterProfile( void BluetoothSocketBlueZ::OnRegisterProfileError( const ErrorCompletionCallback& error_callback, const std::string& error_message) { - DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner()->RunsTasksInCurrentSequence()); LOG(WARNING) << uuid_.canonical_value() << ": Failed to register profile: " << error_message; @@ -283,7 +282,7 @@ void BluetoothSocketBlueZ::OnRegisterProfileError( void BluetoothSocketBlueZ::OnConnectProfile( const base::Closure& success_callback) { - DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner()->RunsTasksInCurrentSequence()); DCHECK(profile_); VLOG(1) << profile_->object_path().value() << ": Profile connected."; @@ -295,7 +294,7 @@ void BluetoothSocketBlueZ::OnConnectProfileError( const ErrorCompletionCallback& error_callback, const std::string& error_name, const std::string& error_message) { - DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner()->RunsTasksInCurrentSequence()); DCHECK(profile_); LOG(WARNING) << profile_->object_path().value() @@ -307,7 +306,7 @@ void BluetoothSocketBlueZ::OnConnectProfileError( void BluetoothSocketBlueZ::AdapterPresentChanged(BluetoothAdapter* adapter, bool present) { - DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner()->RunsTasksInCurrentSequence()); if (!present) { // Adapter removed, we can't use the profile anymore. @@ -328,7 +327,7 @@ void BluetoothSocketBlueZ::AdapterPresentChanged(BluetoothAdapter* adapter, void BluetoothSocketBlueZ::OnInternalRegisterProfile( BluetoothAdapterProfileBlueZ* profile) { - DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner()->RunsTasksInCurrentSequence()); DCHECK(!profile_); profile_ = profile; @@ -338,13 +337,13 @@ void BluetoothSocketBlueZ::OnInternalRegisterProfile( void BluetoothSocketBlueZ::OnInternalRegisterProfileError( const std::string& error_message) { - DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner()->RunsTasksInCurrentSequence()); LOG(WARNING) << "Failed to re-register profile: " << error_message; } void BluetoothSocketBlueZ::Released() { - DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner()->RunsTasksInCurrentSequence()); DCHECK(profile_); VLOG(1) << profile_->object_path().value() << ": Release"; @@ -355,7 +354,7 @@ void BluetoothSocketBlueZ::NewConnection( base::ScopedFD fd, const bluez::BluetoothProfileServiceProvider::Delegate::Options& options, const ConfirmationCallback& callback) { - DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner()->RunsTasksInCurrentSequence()); VLOG(1) << uuid_.canonical_value() << ": New connection from device: " << device_path.value(); @@ -385,7 +384,7 @@ void BluetoothSocketBlueZ::NewConnection( void BluetoothSocketBlueZ::RequestDisconnection( const dbus::ObjectPath& device_path, const ConfirmationCallback& callback) { - DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner()->RunsTasksInCurrentSequence()); DCHECK(profile_); VLOG(1) << profile_->object_path().value() << ": Request disconnection"; @@ -393,7 +392,7 @@ void BluetoothSocketBlueZ::RequestDisconnection( } void BluetoothSocketBlueZ::Cancel() { - DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner()->RunsTasksInCurrentSequence()); DCHECK(profile_); VLOG(1) << profile_->object_path().value() << ": Cancel"; @@ -412,7 +411,7 @@ void BluetoothSocketBlueZ::Cancel() { } void BluetoothSocketBlueZ::AcceptConnectionRequest() { - DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner()->RunsTasksInCurrentSequence()); DCHECK(accept_request_.get()); DCHECK(connection_request_queue_.size() >= 1); DCHECK(profile_); @@ -450,7 +449,7 @@ void BluetoothSocketBlueZ::DoNewConnection( base::ScopedFD fd, const bluez::BluetoothProfileServiceProvider::Delegate::Options& options, const ConfirmationCallback& callback) { - DCHECK(socket_thread()->task_runner()->RunsTasksOnCurrentThread()); + DCHECK(socket_thread()->task_runner()->RunsTasksInCurrentSequence()); base::ThreadRestrictions::AssertIOAllowed(); if (!fd.is_valid()) { @@ -485,7 +484,7 @@ void BluetoothSocketBlueZ::OnNewConnection( scoped_refptr<BluetoothSocket> socket, const ConfirmationCallback& callback, Status status) { - DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner()->RunsTasksInCurrentSequence()); DCHECK(accept_request_.get()); DCHECK(connection_request_queue_.size() >= 1); @@ -508,7 +507,7 @@ void BluetoothSocketBlueZ::OnNewConnection( } void BluetoothSocketBlueZ::DoCloseListening() { - DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner()->RunsTasksInCurrentSequence()); if (accept_request_) { accept_request_->error_callback.Run( @@ -524,7 +523,7 @@ void BluetoothSocketBlueZ::DoCloseListening() { } void BluetoothSocketBlueZ::UnregisterProfile() { - DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner()->RunsTasksInCurrentSequence()); DCHECK(profile_); VLOG(1) << profile_->object_path().value() << ": Release profile"; diff --git a/chromium/device/bluetooth/bluez/bluetooth_socket_bluez.h b/chromium/device/bluetooth/bluez/bluetooth_socket_bluez.h index 9c484b49dcb..b136fa56600 100644 --- a/chromium/device/bluetooth/bluez/bluetooth_socket_bluez.h +++ b/chromium/device/bluetooth/bluez/bluetooth_socket_bluez.h @@ -11,6 +11,7 @@ #include "base/macros.h" #include "base/memory/linked_ptr.h" +#include "base/sequenced_task_runner.h" #include "dbus/object_path.h" #include "device/bluetooth/bluetooth_adapter.h" #include "device/bluetooth/bluetooth_export.h" diff --git a/chromium/device/bluetooth/bluez/bluetooth_socket_bluez_unittest.cc b/chromium/device/bluetooth/bluez/bluetooth_socket_bluez_unittest.cc index 74ac10a4d10..d536eb08901 100644 --- a/chromium/device/bluetooth/bluez/bluetooth_socket_bluez_unittest.cc +++ b/chromium/device/bluetooth/bluez/bluetooth_socket_bluez_unittest.cc @@ -81,10 +81,13 @@ class BluetoothSocketBlueZTest : public testing::Test { BluetoothSocketThread::Get(); // Grab a pointer to the adapter. - device::BluetoothAdapterFactory::GetAdapter(base::Bind( - &BluetoothSocketBlueZTest::AdapterCallback, base::Unretained(this))); - - base::RunLoop().Run(); + { + base::RunLoop run_loop; + device::BluetoothAdapterFactory::GetAdapter( + base::Bind(&BluetoothSocketBlueZTest::AdapterCallback, + base::Unretained(this), run_loop.QuitWhenIdleClosure())); + run_loop.Run(); + } ASSERT_TRUE(adapter_.get() != nullptr); ASSERT_TRUE(adapter_->IsInitialized()); @@ -102,74 +105,69 @@ class BluetoothSocketBlueZTest : public testing::Test { bluez::BluezDBusManager::Shutdown(); } - void AdapterCallback(scoped_refptr<BluetoothAdapter> adapter) { + void AdapterCallback(base::OnceClosure continuation, + scoped_refptr<BluetoothAdapter> adapter) { adapter_ = adapter; - if (base::MessageLoop::current() && - base::MessageLoop::current()->is_running()) { - base::MessageLoop::current()->QuitWhenIdle(); - } + std::move(continuation).Run(); } - void SuccessCallback() { + void SuccessCallback(base::OnceClosure continuation) { ++success_callback_count_; - message_loop_.QuitWhenIdle(); + std::move(continuation).Run(); } - void ErrorCallback(const std::string& message) { + void ErrorCallback(base::OnceClosure continuation, + const std::string& message) { ++error_callback_count_; last_message_ = message; - - if (message_loop_.is_running()) - message_loop_.QuitWhenIdle(); + std::move(continuation).Run(); } - void ConnectToServiceSuccessCallback(scoped_refptr<BluetoothSocket> socket) { + void ConnectToServiceSuccessCallback(base::OnceClosure continuation, + scoped_refptr<BluetoothSocket> socket) { ++success_callback_count_; last_socket_ = socket; - - message_loop_.QuitWhenIdle(); + std::move(continuation).Run(); } - void SendSuccessCallback(int bytes_sent) { + void SendSuccessCallback(base::OnceClosure continuation, int bytes_sent) { ++success_callback_count_; last_bytes_sent_ = bytes_sent; - - message_loop_.QuitWhenIdle(); + std::move(continuation).Run(); } - void ReceiveSuccessCallback(int bytes_received, + void ReceiveSuccessCallback(base::OnceClosure continuation, + int bytes_received, scoped_refptr<net::IOBuffer> io_buffer) { ++success_callback_count_; last_bytes_received_ = bytes_received; last_io_buffer_ = io_buffer; - - message_loop_.QuitWhenIdle(); + std::move(continuation).Run(); } - void ReceiveErrorCallback(BluetoothSocket::ErrorReason reason, + void ReceiveErrorCallback(base::OnceClosure continuation, + BluetoothSocket::ErrorReason reason, const std::string& error_message) { ++error_callback_count_; last_reason_ = reason; last_message_ = error_message; - - message_loop_.QuitWhenIdle(); + std::move(continuation).Run(); } - void CreateServiceSuccessCallback(scoped_refptr<BluetoothSocket> socket) { + void CreateServiceSuccessCallback(base::OnceClosure continuation, + scoped_refptr<BluetoothSocket> socket) { ++success_callback_count_; last_socket_ = socket; - - if (message_loop_.is_running()) - message_loop_.QuitWhenIdle(); + std::move(continuation).Run(); } - void AcceptSuccessCallback(const BluetoothDevice* device, + void AcceptSuccessCallback(base::OnceClosure continuation, + const BluetoothDevice* device, scoped_refptr<BluetoothSocket> socket) { ++success_callback_count_; last_device_ = device; last_socket_ = socket; - - message_loop_.QuitWhenIdle(); + std::move(continuation).Run(); } void ImmediateSuccessCallback() { ++success_callback_count_; } @@ -197,13 +195,16 @@ TEST_F(BluetoothSocketBlueZTest, Connect) { bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress); ASSERT_TRUE(device != nullptr); - device->ConnectToService( - BluetoothUUID(bluez::FakeBluetoothProfileManagerClient::kRfcommUuid), - base::Bind(&BluetoothSocketBlueZTest::ConnectToServiceSuccessCallback, - base::Unretained(this)), - base::Bind(&BluetoothSocketBlueZTest::ErrorCallback, - base::Unretained(this))); - base::RunLoop().Run(); + { + base::RunLoop run_loop; + device->ConnectToService( + BluetoothUUID(bluez::FakeBluetoothProfileManagerClient::kRfcommUuid), + base::Bind(&BluetoothSocketBlueZTest::ConnectToServiceSuccessCallback, + base::Unretained(this), run_loop.QuitWhenIdleClosure()), + base::Bind(&BluetoothSocketBlueZTest::ErrorCallback, + base::Unretained(this), run_loop.QuitWhenIdleClosure())); + run_loop.Run(); + } EXPECT_EQ(1U, success_callback_count_); EXPECT_EQ(0U, error_callback_count_); @@ -219,12 +220,16 @@ TEST_F(BluetoothSocketBlueZTest, Connect) { scoped_refptr<net::StringIOBuffer> write_buffer( new net::StringIOBuffer("test")); - socket->Send(write_buffer.get(), write_buffer->size(), - base::Bind(&BluetoothSocketBlueZTest::SendSuccessCallback, - base::Unretained(this)), - base::Bind(&BluetoothSocketBlueZTest::ErrorCallback, - base::Unretained(this))); - base::RunLoop().Run(); + { + base::RunLoop run_loop; + socket->Send( + write_buffer.get(), write_buffer->size(), + base::Bind(&BluetoothSocketBlueZTest::SendSuccessCallback, + base::Unretained(this), run_loop.QuitWhenIdleClosure()), + base::Bind(&BluetoothSocketBlueZTest::ErrorCallback, + base::Unretained(this), run_loop.QuitWhenIdleClosure())); + run_loop.Run(); + } EXPECT_EQ(1U, success_callback_count_); EXPECT_EQ(0U, error_callback_count_); @@ -235,12 +240,16 @@ TEST_F(BluetoothSocketBlueZTest, Connect) { // Receive data from the socket, and fetch the buffer from the callback; since // the fake is an echo server, we expect to receive what we wrote. - socket->Receive(4096, - base::Bind(&BluetoothSocketBlueZTest::ReceiveSuccessCallback, - base::Unretained(this)), - base::Bind(&BluetoothSocketBlueZTest::ReceiveErrorCallback, - base::Unretained(this))); - base::RunLoop().Run(); + { + base::RunLoop run_loop; + socket->Receive( + 4096, + base::Bind(&BluetoothSocketBlueZTest::ReceiveSuccessCallback, + base::Unretained(this), run_loop.QuitWhenIdleClosure()), + base::Bind(&BluetoothSocketBlueZTest::ReceiveErrorCallback, + base::Unretained(this), run_loop.QuitWhenIdleClosure())); + run_loop.Run(); + } EXPECT_EQ(1U, success_callback_count_); EXPECT_EQ(0U, error_callback_count_); @@ -260,12 +269,16 @@ TEST_F(BluetoothSocketBlueZTest, Connect) { // Receive data again; the socket will have been closed, this should cause a // disconnected error to be returned via the error callback. - socket->Receive(4096, - base::Bind(&BluetoothSocketBlueZTest::ReceiveSuccessCallback, - base::Unretained(this)), - base::Bind(&BluetoothSocketBlueZTest::ReceiveErrorCallback, - base::Unretained(this))); - base::RunLoop().Run(); + { + base::RunLoop run_loop; + socket->Receive( + 4096, + base::Bind(&BluetoothSocketBlueZTest::ReceiveSuccessCallback, + base::Unretained(this), run_loop.QuitWhenIdleClosure()), + base::Bind(&BluetoothSocketBlueZTest::ReceiveErrorCallback, + base::Unretained(this), run_loop.QuitWhenIdleClosure())); + run_loop.Run(); + } EXPECT_EQ(0U, success_callback_count_); EXPECT_EQ(1U, error_callback_count_); @@ -279,12 +292,16 @@ TEST_F(BluetoothSocketBlueZTest, Connect) { // equivalent to the connection reset error. write_buffer = new net::StringIOBuffer("second test"); - socket->Send(write_buffer.get(), write_buffer->size(), - base::Bind(&BluetoothSocketBlueZTest::SendSuccessCallback, - base::Unretained(this)), - base::Bind(&BluetoothSocketBlueZTest::ErrorCallback, - base::Unretained(this))); - base::RunLoop().Run(); + { + base::RunLoop run_loop; + socket->Send( + write_buffer.get(), write_buffer->size(), + base::Bind(&BluetoothSocketBlueZTest::SendSuccessCallback, + base::Unretained(this), run_loop.QuitWhenIdleClosure()), + base::Bind(&BluetoothSocketBlueZTest::ErrorCallback, + base::Unretained(this), run_loop.QuitWhenIdleClosure())); + run_loop.Run(); + } EXPECT_EQ(0U, success_callback_count_); EXPECT_EQ(1U, error_callback_count_); @@ -294,23 +311,28 @@ TEST_F(BluetoothSocketBlueZTest, Connect) { error_callback_count_ = 0; // Close our end of the socket. - socket->Disconnect(base::Bind(&BluetoothSocketBlueZTest::SuccessCallback, - base::Unretained(this))); - - base::RunLoop().Run(); + { + base::RunLoop run_loop; + socket->Disconnect(base::Bind(&BluetoothSocketBlueZTest::SuccessCallback, + base::Unretained(this), + run_loop.QuitWhenIdleClosure())); + run_loop.Run(); + } EXPECT_EQ(1U, success_callback_count_); } TEST_F(BluetoothSocketBlueZTest, Listen) { - adapter_->CreateRfcommService( - BluetoothUUID(bluez::FakeBluetoothProfileManagerClient::kRfcommUuid), - BluetoothAdapter::ServiceOptions(), - base::Bind(&BluetoothSocketBlueZTest::CreateServiceSuccessCallback, - base::Unretained(this)), - base::Bind(&BluetoothSocketBlueZTest::ErrorCallback, - base::Unretained(this))); - - base::RunLoop().Run(); + { + base::RunLoop run_loop; + adapter_->CreateRfcommService( + BluetoothUUID(bluez::FakeBluetoothProfileManagerClient::kRfcommUuid), + BluetoothAdapter::ServiceOptions(), + base::Bind(&BluetoothSocketBlueZTest::CreateServiceSuccessCallback, + base::Unretained(this), run_loop.QuitWhenIdleClosure()), + base::Bind(&BluetoothSocketBlueZTest::ErrorCallback, + base::Unretained(this), run_loop.QuitWhenIdleClosure())); + run_loop.Run(); + } EXPECT_EQ(1U, success_callback_count_); EXPECT_EQ(0U, error_callback_count_); @@ -334,20 +356,23 @@ TEST_F(BluetoothSocketBlueZTest, Listen) { BluetoothDevice* device = adapter_->GetDevice( bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress); ASSERT_TRUE(device != nullptr); - fake_bluetooth_device_client->ConnectProfile( - static_cast<BluetoothDeviceBlueZ*>(device)->object_path(), - bluez::FakeBluetoothProfileManagerClient::kRfcommUuid, - base::Bind(&base::DoNothing), base::Bind(&DoNothingDBusErrorCallback)); - - base::RunLoop().RunUntilIdle(); - - server_socket->Accept( - base::Bind(&BluetoothSocketBlueZTest::AcceptSuccessCallback, - base::Unretained(this)), - base::Bind(&BluetoothSocketBlueZTest::ErrorCallback, - base::Unretained(this))); - - base::RunLoop().Run(); + { + base::RunLoop run_loop; + fake_bluetooth_device_client->ConnectProfile( + static_cast<BluetoothDeviceBlueZ*>(device)->object_path(), + bluez::FakeBluetoothProfileManagerClient::kRfcommUuid, + base::Bind(&base::DoNothing), base::Bind(&DoNothingDBusErrorCallback)); + run_loop.RunUntilIdle(); + } + { + base::RunLoop run_loop; + server_socket->Accept( + base::Bind(&BluetoothSocketBlueZTest::AcceptSuccessCallback, + base::Unretained(this), run_loop.QuitWhenIdleClosure()), + base::Bind(&BluetoothSocketBlueZTest::ErrorCallback, + base::Unretained(this), run_loop.QuitWhenIdleClosure())); + run_loop.Run(); + } EXPECT_EQ(1U, success_callback_count_); EXPECT_EQ(0U, error_callback_count_); @@ -360,10 +385,13 @@ TEST_F(BluetoothSocketBlueZTest, Listen) { error_callback_count_ = 0; // Close our end of the client socket. - client_socket->Disconnect(base::Bind( - &BluetoothSocketBlueZTest::SuccessCallback, base::Unretained(this))); - - base::RunLoop().Run(); + { + base::RunLoop run_loop; + client_socket->Disconnect( + base::Bind(&BluetoothSocketBlueZTest::SuccessCallback, + base::Unretained(this), run_loop.QuitWhenIdleClosure())); + run_loop.Run(); + } EXPECT_EQ(1U, success_callback_count_); client_socket = nullptr; @@ -372,20 +400,25 @@ TEST_F(BluetoothSocketBlueZTest, Listen) { // Run a second connection test, this time calling Accept() before the // incoming connection comes in. - server_socket->Accept( - base::Bind(&BluetoothSocketBlueZTest::AcceptSuccessCallback, - base::Unretained(this)), - base::Bind(&BluetoothSocketBlueZTest::ErrorCallback, - base::Unretained(this))); - - base::RunLoop().RunUntilIdle(); - - fake_bluetooth_device_client->ConnectProfile( - static_cast<BluetoothDeviceBlueZ*>(device)->object_path(), - bluez::FakeBluetoothProfileManagerClient::kRfcommUuid, - base::Bind(&base::DoNothing), base::Bind(&DoNothingDBusErrorCallback)); - - base::RunLoop().Run(); + { + base::RunLoop run_loop1; + // |run_loop2| is expected to be quit in ConnectProfile() through the quit + // closures saved in the Accept() call. + base::RunLoop run_loop2; + + server_socket->Accept( + base::Bind(&BluetoothSocketBlueZTest::AcceptSuccessCallback, + base::Unretained(this), run_loop2.QuitWhenIdleClosure()), + base::Bind(&BluetoothSocketBlueZTest::ErrorCallback, + base::Unretained(this), run_loop2.QuitWhenIdleClosure())); + run_loop1.RunUntilIdle(); + + fake_bluetooth_device_client->ConnectProfile( + static_cast<BluetoothDeviceBlueZ*>(device)->object_path(), + bluez::FakeBluetoothProfileManagerClient::kRfcommUuid, + base::Bind(&base::DoNothing), base::Bind(&DoNothingDBusErrorCallback)); + run_loop2.Run(); + } EXPECT_EQ(1U, success_callback_count_); EXPECT_EQ(0U, error_callback_count_); @@ -398,10 +431,13 @@ TEST_F(BluetoothSocketBlueZTest, Listen) { error_callback_count_ = 0; // Close our end of the client socket. - client_socket->Disconnect(base::Bind( - &BluetoothSocketBlueZTest::SuccessCallback, base::Unretained(this))); - - base::RunLoop().Run(); + { + base::RunLoop run_loop; + client_socket->Disconnect( + base::Bind(&BluetoothSocketBlueZTest::SuccessCallback, + base::Unretained(this), run_loop.QuitWhenIdleClosure())); + run_loop.Run(); + } EXPECT_EQ(1U, success_callback_count_); client_socket = nullptr; @@ -409,11 +445,13 @@ TEST_F(BluetoothSocketBlueZTest, Listen) { error_callback_count_ = 0; // Now close the server socket. - server_socket->Disconnect( - base::Bind(&BluetoothSocketBlueZTest::ImmediateSuccessCallback, - base::Unretained(this))); - - base::RunLoop().RunUntilIdle(); + { + base::RunLoop run_loop; + server_socket->Disconnect( + base::Bind(&BluetoothSocketBlueZTest::ImmediateSuccessCallback, + base::Unretained(this))); + run_loop.RunUntilIdle(); + } EXPECT_EQ(1U, success_callback_count_); } @@ -426,14 +464,17 @@ TEST_F(BluetoothSocketBlueZTest, ListenBeforeAdapterStart) { bluez::BluezDBusManager::Get()->GetBluetoothAdapterClient()); fake_bluetooth_adapter_client->SetVisible(false); - adapter_->CreateRfcommService( - BluetoothUUID(bluez::FakeBluetoothProfileManagerClient::kRfcommUuid), - BluetoothAdapter::ServiceOptions(), - base::Bind(&BluetoothSocketBlueZTest::CreateServiceSuccessCallback, - base::Unretained(this)), - base::Bind(&BluetoothSocketBlueZTest::ErrorCallback, - base::Unretained(this))); - base::RunLoop().Run(); + { + base::RunLoop run_loop; + adapter_->CreateRfcommService( + BluetoothUUID(bluez::FakeBluetoothProfileManagerClient::kRfcommUuid), + BluetoothAdapter::ServiceOptions(), + base::Bind(&BluetoothSocketBlueZTest::CreateServiceSuccessCallback, + base::Unretained(this), run_loop.QuitWhenIdleClosure()), + base::Bind(&BluetoothSocketBlueZTest::ErrorCallback, + base::Unretained(this), run_loop.QuitWhenIdleClosure())); + run_loop.Run(); + } EXPECT_EQ(1U, success_callback_count_); EXPECT_EQ(0U, error_callback_count_); @@ -457,9 +498,11 @@ TEST_F(BluetoothSocketBlueZTest, ListenBeforeAdapterStart) { EXPECT_TRUE(profile_service_provider == nullptr); // Make the adapter visible. This should register a profile. - fake_bluetooth_adapter_client->SetVisible(true); - - base::RunLoop().RunUntilIdle(); + { + base::RunLoop run_loop; + fake_bluetooth_adapter_client->SetVisible(true); + run_loop.RunUntilIdle(); + } profile_service_provider = fake_bluetooth_profile_manager_client->GetProfileServiceProvider( @@ -467,11 +510,13 @@ TEST_F(BluetoothSocketBlueZTest, ListenBeforeAdapterStart) { EXPECT_TRUE(profile_service_provider != nullptr); // Cleanup the socket. - socket->Disconnect( - base::Bind(&BluetoothSocketBlueZTest::ImmediateSuccessCallback, - base::Unretained(this))); - - base::RunLoop().RunUntilIdle(); + { + base::RunLoop run_loop; + socket->Disconnect( + base::Bind(&BluetoothSocketBlueZTest::ImmediateSuccessCallback, + base::Unretained(this))); + run_loop.RunUntilIdle(); + } EXPECT_EQ(1U, success_callback_count_); } @@ -482,14 +527,17 @@ TEST_F(BluetoothSocketBlueZTest, ListenAcrossAdapterRestart) { static_cast<bluez::FakeBluetoothAdapterClient*>( bluez::BluezDBusManager::Get()->GetBluetoothAdapterClient()); - adapter_->CreateRfcommService( - BluetoothUUID(bluez::FakeBluetoothProfileManagerClient::kRfcommUuid), - BluetoothAdapter::ServiceOptions(), - base::Bind(&BluetoothSocketBlueZTest::CreateServiceSuccessCallback, - base::Unretained(this)), - base::Bind(&BluetoothSocketBlueZTest::ErrorCallback, - base::Unretained(this))); - base::RunLoop().Run(); + { + base::RunLoop run_loop; + adapter_->CreateRfcommService( + BluetoothUUID(bluez::FakeBluetoothProfileManagerClient::kRfcommUuid), + BluetoothAdapter::ServiceOptions(), + base::Bind(&BluetoothSocketBlueZTest::CreateServiceSuccessCallback, + base::Unretained(this), run_loop.QuitWhenIdleClosure()), + base::Bind(&BluetoothSocketBlueZTest::ErrorCallback, + base::Unretained(this), run_loop.QuitWhenIdleClosure())); + run_loop.Run(); + } EXPECT_EQ(1U, success_callback_count_); EXPECT_EQ(0U, error_callback_count_); @@ -514,14 +562,18 @@ TEST_F(BluetoothSocketBlueZTest, ListenAcrossAdapterRestart) { // Make the adapter invisible, and fiddle with the profile fake to unregister // the profile since this doesn't happen automatically. - fake_bluetooth_adapter_client->SetVisible(false); - - base::RunLoop().RunUntilIdle(); + { + base::RunLoop run_loop; + fake_bluetooth_adapter_client->SetVisible(false); + run_loop.RunUntilIdle(); + } // Then make the adapter visible again. This should re-register the profile. - fake_bluetooth_adapter_client->SetVisible(true); - - base::RunLoop().RunUntilIdle(); + { + base::RunLoop run_loop; + fake_bluetooth_adapter_client->SetVisible(true); + run_loop.RunUntilIdle(); + } profile_service_provider = fake_bluetooth_profile_manager_client->GetProfileServiceProvider( @@ -529,11 +581,13 @@ TEST_F(BluetoothSocketBlueZTest, ListenAcrossAdapterRestart) { EXPECT_TRUE(profile_service_provider != nullptr); // Cleanup the socket. - socket->Disconnect( - base::Bind(&BluetoothSocketBlueZTest::ImmediateSuccessCallback, - base::Unretained(this))); - - base::RunLoop().RunUntilIdle(); + { + base::RunLoop run_loop; + socket->Disconnect( + base::Bind(&BluetoothSocketBlueZTest::ImmediateSuccessCallback, + base::Unretained(this))); + run_loop.RunUntilIdle(); + } EXPECT_EQ(1U, success_callback_count_); } @@ -543,25 +597,31 @@ TEST_F(BluetoothSocketBlueZTest, PairedConnectFails) { bluez::FakeBluetoothDeviceClient::kPairedUnconnectableDeviceAddress); ASSERT_TRUE(device != nullptr); - device->ConnectToService( - BluetoothUUID(bluez::FakeBluetoothProfileManagerClient::kRfcommUuid), - base::Bind(&BluetoothSocketBlueZTest::ConnectToServiceSuccessCallback, - base::Unretained(this)), - base::Bind(&BluetoothSocketBlueZTest::ErrorCallback, - base::Unretained(this))); - base::RunLoop().Run(); + { + base::RunLoop run_loop; + device->ConnectToService( + BluetoothUUID(bluez::FakeBluetoothProfileManagerClient::kRfcommUuid), + base::Bind(&BluetoothSocketBlueZTest::ConnectToServiceSuccessCallback, + base::Unretained(this), run_loop.QuitWhenIdleClosure()), + base::Bind(&BluetoothSocketBlueZTest::ErrorCallback, + base::Unretained(this), run_loop.QuitWhenIdleClosure())); + run_loop.Run(); + } EXPECT_EQ(0U, success_callback_count_); EXPECT_EQ(1U, error_callback_count_); EXPECT_TRUE(last_socket_.get() == nullptr); - device->ConnectToService( - BluetoothUUID(bluez::FakeBluetoothProfileManagerClient::kRfcommUuid), - base::Bind(&BluetoothSocketBlueZTest::ConnectToServiceSuccessCallback, - base::Unretained(this)), - base::Bind(&BluetoothSocketBlueZTest::ErrorCallback, - base::Unretained(this))); - base::RunLoop().Run(); + { + base::RunLoop run_loop; + device->ConnectToService( + BluetoothUUID(bluez::FakeBluetoothProfileManagerClient::kRfcommUuid), + base::Bind(&BluetoothSocketBlueZTest::ConnectToServiceSuccessCallback, + base::Unretained(this), run_loop.QuitWhenIdleClosure()), + base::Bind(&BluetoothSocketBlueZTest::ErrorCallback, + base::Unretained(this), run_loop.QuitWhenIdleClosure())); + run_loop.Run(); + } EXPECT_EQ(0U, success_callback_count_); EXPECT_EQ(2U, error_callback_count_); @@ -569,15 +629,17 @@ TEST_F(BluetoothSocketBlueZTest, PairedConnectFails) { } TEST_F(BluetoothSocketBlueZTest, SocketListenTwice) { - adapter_->CreateRfcommService( - BluetoothUUID(bluez::FakeBluetoothProfileManagerClient::kRfcommUuid), - BluetoothAdapter::ServiceOptions(), - base::Bind(&BluetoothSocketBlueZTest::CreateServiceSuccessCallback, - base::Unretained(this)), - base::Bind(&BluetoothSocketBlueZTest::ErrorCallback, - base::Unretained(this))); - - base::RunLoop().Run(); + { + base::RunLoop run_loop; + adapter_->CreateRfcommService( + BluetoothUUID(bluez::FakeBluetoothProfileManagerClient::kRfcommUuid), + BluetoothAdapter::ServiceOptions(), + base::Bind(&BluetoothSocketBlueZTest::CreateServiceSuccessCallback, + base::Unretained(this), run_loop.QuitWhenIdleClosure()), + base::Bind(&BluetoothSocketBlueZTest::ErrorCallback, + base::Unretained(this), run_loop.QuitWhenIdleClosure())); + run_loop.Run(); + } EXPECT_EQ(1U, success_callback_count_); EXPECT_EQ(0U, error_callback_count_); @@ -587,30 +649,34 @@ TEST_F(BluetoothSocketBlueZTest, SocketListenTwice) { scoped_refptr<BluetoothSocket> server_socket; server_socket.swap(last_socket_); - server_socket->Accept( - base::Bind(&BluetoothSocketBlueZTest::AcceptSuccessCallback, - base::Unretained(this)), - base::Bind(&BluetoothSocketBlueZTest::ErrorCallback, - base::Unretained(this))); - - server_socket->Close(); + { + base::RunLoop run_loop; + server_socket->Accept( + base::Bind(&BluetoothSocketBlueZTest::AcceptSuccessCallback, + base::Unretained(this), run_loop.QuitWhenIdleClosure()), + base::Bind(&BluetoothSocketBlueZTest::ErrorCallback, + base::Unretained(this), run_loop.QuitWhenIdleClosure())); - server_socket = nullptr; + server_socket->Close(); - base::RunLoop().RunUntilIdle(); + server_socket = nullptr; + run_loop.RunUntilIdle(); + } EXPECT_EQ(1U, success_callback_count_); EXPECT_EQ(1U, error_callback_count_); - adapter_->CreateRfcommService( - BluetoothUUID(bluez::FakeBluetoothProfileManagerClient::kRfcommUuid), - BluetoothAdapter::ServiceOptions(), - base::Bind(&BluetoothSocketBlueZTest::CreateServiceSuccessCallback, - base::Unretained(this)), - base::Bind(&BluetoothSocketBlueZTest::ErrorCallback, - base::Unretained(this))); - - base::RunLoop().Run(); + { + base::RunLoop run_loop; + adapter_->CreateRfcommService( + BluetoothUUID(bluez::FakeBluetoothProfileManagerClient::kRfcommUuid), + BluetoothAdapter::ServiceOptions(), + base::Bind(&BluetoothSocketBlueZTest::CreateServiceSuccessCallback, + base::Unretained(this), run_loop.QuitWhenIdleClosure()), + base::Bind(&BluetoothSocketBlueZTest::ErrorCallback, + base::Unretained(this), run_loop.QuitWhenIdleClosure())); + run_loop.Run(); + } EXPECT_EQ(2U, success_callback_count_); EXPECT_EQ(1U, error_callback_count_); @@ -619,17 +685,19 @@ TEST_F(BluetoothSocketBlueZTest, SocketListenTwice) { // Take control of this socket. server_socket.swap(last_socket_); - server_socket->Accept( - base::Bind(&BluetoothSocketBlueZTest::AcceptSuccessCallback, - base::Unretained(this)), - base::Bind(&BluetoothSocketBlueZTest::ErrorCallback, - base::Unretained(this))); - - server_socket->Close(); + { + base::RunLoop run_loop; + server_socket->Accept( + base::Bind(&BluetoothSocketBlueZTest::AcceptSuccessCallback, + base::Unretained(this), run_loop.QuitWhenIdleClosure()), + base::Bind(&BluetoothSocketBlueZTest::ErrorCallback, + base::Unretained(this), run_loop.QuitWhenIdleClosure())); - server_socket = nullptr; + server_socket->Close(); - base::RunLoop().RunUntilIdle(); + server_socket = nullptr; + run_loop.RunUntilIdle(); + } EXPECT_EQ(2U, success_callback_count_); EXPECT_EQ(2U, error_callback_count_); diff --git a/chromium/device/bluetooth/dbus/bluetooth_device_client.cc b/chromium/device/bluetooth/dbus/bluetooth_device_client.cc index 53199eba4bb..142a72ba8f7 100644 --- a/chromium/device/bluetooth/dbus/bluetooth_device_client.cc +++ b/chromium/device/bluetooth/dbus/bluetooth_device_client.cc @@ -433,6 +433,53 @@ class BluetoothDeviceClientImpl : public BluetoothDeviceClient, weak_ptr_factory_.GetWeakPtr(), error_callback)); } + void SetLEConnectionParameters(const dbus::ObjectPath& object_path, + const ConnectionParameters& conn_params, + const base::Closure& callback, + const ErrorCallback& error_callback) override { + dbus::ObjectProxy* object_proxy = + object_manager_->GetObjectProxy(object_path); + if (!object_proxy) { + error_callback.Run(kUnknownDeviceError, ""); + return; + } + + // TODO(crbug.com/725367): Use constants in cros_system_api once it is + // rolled. + dbus::MethodCall method_call( + bluetooth_plugin_device::kBluetoothPluginInterface, + "SetLEConnectionParameters"); + + dbus::MessageWriter writer(&method_call); + dbus::MessageWriter dict_writer(nullptr); + writer.OpenArray("{sq}", &dict_writer); + + { + dbus::MessageWriter dict_entry_writer(nullptr); + dict_writer.OpenDictEntry(&dict_entry_writer); + dict_entry_writer.AppendString("MinimumConnectionInterval"); + dict_entry_writer.AppendUint16(conn_params.min_connection_interval); + dict_writer.CloseContainer(&dict_entry_writer); + } + + { + dbus::MessageWriter dict_entry_writer(nullptr); + dict_writer.OpenDictEntry(&dict_entry_writer); + dict_entry_writer.AppendString("MaximumConnectionInterval"); + dict_entry_writer.AppendUint16(conn_params.max_connection_interval); + dict_writer.CloseContainer(&dict_entry_writer); + } + + writer.CloseContainer(&dict_writer); + + object_proxy->CallMethodWithErrorCallback( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&BluetoothDeviceClientImpl::OnSuccess, + weak_ptr_factory_.GetWeakPtr(), callback), + base::Bind(&BluetoothDeviceClientImpl::OnError, + weak_ptr_factory_.GetWeakPtr(), error_callback)); + } + void GetServiceRecords(const dbus::ObjectPath& object_path, const ServiceRecordsCallback& callback, const ErrorCallback& error_callback) override { diff --git a/chromium/device/bluetooth/dbus/bluetooth_device_client.h b/chromium/device/bluetooth/dbus/bluetooth_device_client.h index d42aa76f374..921c70c9c7d 100644 --- a/chromium/device/bluetooth/dbus/bluetooth_device_client.h +++ b/chromium/device/bluetooth/dbus/bluetooth_device_client.h @@ -131,6 +131,17 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothDeviceClient : public BluezDBusClient { ~Properties() override; }; + // Connection parameters that can be passed to SetLEConnectionParameters(). + struct ConnectionParameters { + // The lower bound to request for the connection interval. + // In units of 1.25ms. + uint16_t min_connection_interval; + + // The upper bound to request for the connection interval. + // In units of 1.25ms. + uint16_t max_connection_interval; + }; + // Interface for observing changes from a remote bluetooth device. class Observer { public: @@ -216,6 +227,13 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothDeviceClient : public BluezDBusClient { const ConnInfoCallback& callback, const ErrorCallback& error_callback) = 0; + // Sets the connection parameters (e.g. connection interval) for the device. + virtual void SetLEConnectionParameters( + const dbus::ObjectPath& object_path, + const ConnectionParameters& conn_params, + const base::Closure& callback, + const ErrorCallback& error_callback) = 0; + // Returns the currently discovered service records for the device with // object path |object_path|. If the device is not connected, then an error // will be returned. diff --git a/chromium/device/bluetooth/dbus/dbus_thread_manager_linux.cc b/chromium/device/bluetooth/dbus/dbus_thread_manager_linux.cc index adffe9b746a..ecaed41bae4 100644 --- a/chromium/device/bluetooth/dbus/dbus_thread_manager_linux.cc +++ b/chromium/device/bluetooth/dbus/dbus_thread_manager_linux.cc @@ -4,6 +4,7 @@ #include "device/bluetooth/dbus/dbus_thread_manager_linux.h" +#include "base/message_loop/message_loop.h" #include "base/threading/thread.h" #include "dbus/bus.h" diff --git a/chromium/device/bluetooth/dbus/fake_bluetooth_device_client.cc b/chromium/device/bluetooth/dbus/fake_bluetooth_device_client.cc index 3ce62c3519c..cc4eaefd168 100644 --- a/chromium/device/bluetooth/dbus/fake_bluetooth_device_client.cc +++ b/chromium/device/bluetooth/dbus/fake_bluetooth_device_client.cc @@ -519,10 +519,8 @@ void FakeBluetoothDeviceClient::ConnectProfile( } base::PostTaskWithTraits( - FROM_HERE, base::TaskTraits() - .WithShutdownBehavior( - base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN) - .MayBlock(), + FROM_HERE, + {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}, base::Bind(&SimulatedProfileSocket, fds[0])); base::ScopedFD fd(fds[1]); @@ -597,6 +595,20 @@ void FakeBluetoothDeviceClient::GetConnInfo( callback.Run(connection_rssi_, transmit_power_, max_transmit_power_); } +void FakeBluetoothDeviceClient::SetLEConnectionParameters( + const dbus::ObjectPath& object_path, + const ConnectionParameters& conn_params, + const base::Closure& callback, + const ErrorCallback& error_callback) { + Properties* properties = GetProperties(object_path); + if (!properties->connected.value()) { + error_callback.Run(bluetooth_device::kErrorNotConnected, "Not Connected"); + return; + } + + callback.Run(); +} + void FakeBluetoothDeviceClient::GetServiceRecords( const dbus::ObjectPath& object_path, const ServiceRecordsCallback& callback, diff --git a/chromium/device/bluetooth/dbus/fake_bluetooth_device_client.h b/chromium/device/bluetooth/dbus/fake_bluetooth_device_client.h index abf086faed4..37446d2741a 100644 --- a/chromium/device/bluetooth/dbus/fake_bluetooth_device_client.h +++ b/chromium/device/bluetooth/dbus/fake_bluetooth_device_client.h @@ -102,6 +102,10 @@ class DEVICE_BLUETOOTH_EXPORT FakeBluetoothDeviceClient void GetConnInfo(const dbus::ObjectPath& object_path, const ConnInfoCallback& callback, const ErrorCallback& error_callback) override; + void SetLEConnectionParameters(const dbus::ObjectPath& object_path, + const ConnectionParameters& conn_params, + const base::Closure& callback, + const ErrorCallback& error_callback) override; void GetServiceRecords(const dbus::ObjectPath& object_path, const ServiceRecordsCallback& callback, const ErrorCallback& error_callback) override; diff --git a/chromium/device/bluetooth/dbus/fake_bluetooth_media_endpoint_service_provider.h b/chromium/device/bluetooth/dbus/fake_bluetooth_media_endpoint_service_provider.h index 6a9e6ae6757..f907e4da732 100644 --- a/chromium/device/bluetooth/dbus/fake_bluetooth_media_endpoint_service_provider.h +++ b/chromium/device/bluetooth/dbus/fake_bluetooth_media_endpoint_service_provider.h @@ -14,7 +14,7 @@ #include "dbus/object_path.h" #include "device/bluetooth/bluetooth_export.h" #include "device/bluetooth/dbus/bluetooth_media_endpoint_service_provider.h" -#include "testing/gtest/include/gtest/gtest_prod.h" +#include "testing/gtest/include/gtest/gtest_prod.h" // nogncheck namespace bluez { diff --git a/chromium/device/bluetooth/device.cc b/chromium/device/bluetooth/device.cc index acba3d246cb..d037b341b69 100644 --- a/chromium/device/bluetooth/device.cc +++ b/chromium/device/bluetooth/device.cc @@ -74,37 +74,38 @@ void Device::Disconnect() { binding_->Close(); } -void Device::GetInfo(const GetInfoCallback& callback) { +void Device::GetInfo(GetInfoCallback callback) { device::BluetoothDevice* device = adapter_->GetDevice(GetAddress()); DCHECK(device); - callback.Run(ConstructDeviceInfoStruct(device)); + std::move(callback).Run(ConstructDeviceInfoStruct(device)); } -void Device::GetServices(const GetServicesCallback& callback) { +void Device::GetServices(GetServicesCallback callback) { device::BluetoothDevice* device = adapter_->GetDevice(GetAddress()); DCHECK(device); if (device->IsGattServicesDiscoveryComplete()) { - GetServicesImpl(callback); + GetServicesImpl(std::move(callback)); return; } // pending_services_requests_ is owned by Device, so base::Unretained is // safe. - pending_services_requests_.push_back( - base::Bind(&Device::GetServicesImpl, base::Unretained(this), callback)); + pending_services_requests_.push_back(base::Bind(&Device::GetServicesImpl, + base::Unretained(this), + base::Passed(&callback))); } void Device::GetCharacteristics(const std::string& service_id, - const GetCharacteristicsCallback& callback) { + GetCharacteristicsCallback callback) { device::BluetoothDevice* device = adapter_->GetDevice(GetAddress()); DCHECK(device); device::BluetoothRemoteGattService* service = device->GetGattService(service_id); if (service == nullptr) { - callback.Run(base::nullopt); + std::move(callback).Run(base::nullopt); return; } @@ -121,88 +122,91 @@ void Device::GetCharacteristics(const std::string& service_id, characteristics.push_back(std::move(characteristic_info)); } - callback.Run(std::move(characteristics)); + std::move(callback).Run(std::move(characteristics)); } void Device::ReadValueForCharacteristic( const std::string& service_id, const std::string& characteristic_id, - const ReadValueForCharacteristicCallback& callback) { + ReadValueForCharacteristicCallback callback) { device::BluetoothDevice* device = adapter_->GetDevice(GetAddress()); DCHECK(device); device::BluetoothRemoteGattService* service = device->GetGattService(service_id); if (service == nullptr) { - callback.Run(mojom::GattResult::SERVICE_NOT_FOUND, - base::nullopt /* value */); + std::move(callback).Run(mojom::GattResult::SERVICE_NOT_FOUND, + base::nullopt /* value */); return; } device::BluetoothRemoteGattCharacteristic* characteristic = service->GetCharacteristic(characteristic_id); if (characteristic == nullptr) { - callback.Run(mojom::GattResult::CHARACTERISTIC_NOT_FOUND, - base::nullopt /* value */); + std::move(callback).Run(mojom::GattResult::CHARACTERISTIC_NOT_FOUND, + base::nullopt /* value */); return; } + auto copyable_callback = base::AdaptCallbackForRepeating(std::move(callback)); characteristic->ReadRemoteCharacteristic( base::Bind(&Device::OnReadRemoteCharacteristic, - weak_ptr_factory_.GetWeakPtr(), callback), + weak_ptr_factory_.GetWeakPtr(), copyable_callback), base::Bind(&Device::OnReadRemoteCharacteristicError, - weak_ptr_factory_.GetWeakPtr(), callback)); + weak_ptr_factory_.GetWeakPtr(), copyable_callback)); } void Device::WriteValueForCharacteristic( const std::string& service_id, const std::string& characteristic_id, const std::vector<uint8_t>& value, - const WriteValueForCharacteristicCallback& callback) { + WriteValueForCharacteristicCallback callback) { device::BluetoothDevice* device = adapter_->GetDevice(GetAddress()); DCHECK(device); device::BluetoothRemoteGattService* service = device->GetGattService(service_id); if (service == nullptr) { - callback.Run(mojom::GattResult::SERVICE_NOT_FOUND); + std::move(callback).Run(mojom::GattResult::SERVICE_NOT_FOUND); return; } device::BluetoothRemoteGattCharacteristic* characteristic = service->GetCharacteristic(characteristic_id); if (characteristic == nullptr) { - callback.Run(mojom::GattResult::CHARACTERISTIC_NOT_FOUND); + std::move(callback).Run(mojom::GattResult::CHARACTERISTIC_NOT_FOUND); return; } + auto copyable_callback = base::AdaptCallbackForRepeating(std::move(callback)); characteristic->WriteRemoteCharacteristic( - value, base::Bind(&Device::OnWriteRemoteCharacteristic, - weak_ptr_factory_.GetWeakPtr(), callback), + value, + base::Bind(&Device::OnWriteRemoteCharacteristic, + weak_ptr_factory_.GetWeakPtr(), copyable_callback), base::Bind(&Device::OnWriteRemoteCharacteristicError, - weak_ptr_factory_.GetWeakPtr(), callback)); + weak_ptr_factory_.GetWeakPtr(), copyable_callback)); } void Device::GetDescriptors(const std::string& service_id, const std::string& characteristic_id, - const GetDescriptorsCallback& callback) { + GetDescriptorsCallback callback) { device::BluetoothDevice* device = adapter_->GetDevice(GetAddress()); if (!device) { - callback.Run(base::nullopt); + std::move(callback).Run(base::nullopt); return; } device::BluetoothRemoteGattService* service = device->GetGattService(service_id); if (!service) { - callback.Run(base::nullopt); + std::move(callback).Run(base::nullopt); return; } device::BluetoothRemoteGattCharacteristic* characteristic = service->GetCharacteristic(characteristic_id); if (!characteristic) { - callback.Run(base::nullopt); + std::move(callback).Run(base::nullopt); return; } @@ -218,83 +222,84 @@ void Device::GetDescriptors(const std::string& service_id, descriptors.push_back(std::move(descriptor_info)); } - callback.Run(std::move(descriptors)); + std::move(callback).Run(std::move(descriptors)); } -void Device::ReadValueForDescriptor( - const std::string& service_id, - const std::string& characteristic_id, - const std::string& descriptor_id, - const ReadValueForDescriptorCallback& callback) { +void Device::ReadValueForDescriptor(const std::string& service_id, + const std::string& characteristic_id, + const std::string& descriptor_id, + ReadValueForDescriptorCallback callback) { device::BluetoothDevice* device = adapter_->GetDevice(GetAddress()); DCHECK(device); device::BluetoothRemoteGattService* service = device->GetGattService(service_id); if (!service) { - callback.Run(mojom::GattResult::SERVICE_NOT_FOUND, - base::nullopt /* value */); + std::move(callback).Run(mojom::GattResult::SERVICE_NOT_FOUND, + base::nullopt /* value */); return; } device::BluetoothRemoteGattCharacteristic* characteristic = service->GetCharacteristic(characteristic_id); if (!characteristic) { - callback.Run(mojom::GattResult::CHARACTERISTIC_NOT_FOUND, - base::nullopt /* value */); + std::move(callback).Run(mojom::GattResult::CHARACTERISTIC_NOT_FOUND, + base::nullopt /* value */); return; } device::BluetoothRemoteGattDescriptor* descriptor = characteristic->GetDescriptor(descriptor_id); if (!descriptor) { - callback.Run(mojom::GattResult::DESCRIPTOR_NOT_FOUND, - base::nullopt /* value */); + std::move(callback).Run(mojom::GattResult::DESCRIPTOR_NOT_FOUND, + base::nullopt /* value */); return; } + auto copyable_callback = base::AdaptCallbackForRepeating(std::move(callback)); descriptor->ReadRemoteDescriptor( base::Bind(&Device::OnReadRemoteDescriptor, - weak_ptr_factory_.GetWeakPtr(), callback), + weak_ptr_factory_.GetWeakPtr(), copyable_callback), base::Bind(&Device::OnReadRemoteDescriptorError, - weak_ptr_factory_.GetWeakPtr(), callback)); + weak_ptr_factory_.GetWeakPtr(), copyable_callback)); } -void Device::WriteValueForDescriptor( - const std::string& service_id, - const std::string& characteristic_id, - const std::string& descriptor_id, - const std::vector<uint8_t>& value, - const WriteValueForDescriptorCallback& callback) { +void Device::WriteValueForDescriptor(const std::string& service_id, + const std::string& characteristic_id, + const std::string& descriptor_id, + const std::vector<uint8_t>& value, + WriteValueForDescriptorCallback callback) { device::BluetoothDevice* device = adapter_->GetDevice(GetAddress()); DCHECK(device); device::BluetoothRemoteGattService* service = device->GetGattService(service_id); if (!service) { - callback.Run(mojom::GattResult::SERVICE_NOT_FOUND); + std::move(callback).Run(mojom::GattResult::SERVICE_NOT_FOUND); return; } device::BluetoothRemoteGattCharacteristic* characteristic = service->GetCharacteristic(characteristic_id); if (!characteristic) { - callback.Run(mojom::GattResult::CHARACTERISTIC_NOT_FOUND); + std::move(callback).Run(mojom::GattResult::CHARACTERISTIC_NOT_FOUND); return; } device::BluetoothRemoteGattDescriptor* descriptor = characteristic->GetDescriptor(descriptor_id); if (!descriptor) { - callback.Run(mojom::GattResult::DESCRIPTOR_NOT_FOUND); + std::move(callback).Run(mojom::GattResult::DESCRIPTOR_NOT_FOUND); return; } + auto copyable_callback = base::AdaptCallbackForRepeating(std::move(callback)); descriptor->WriteRemoteDescriptor( - value, base::Bind(&Device::OnWriteRemoteDescriptor, - weak_ptr_factory_.GetWeakPtr(), callback), + value, + base::Bind(&Device::OnWriteRemoteDescriptor, + weak_ptr_factory_.GetWeakPtr(), copyable_callback), base::Bind(&Device::OnWriteRemoteDescriptorError, - weak_ptr_factory_.GetWeakPtr(), callback)); + weak_ptr_factory_.GetWeakPtr(), copyable_callback)); } Device::Device(scoped_refptr<device::BluetoothAdapter> adapter, @@ -305,7 +310,7 @@ Device::Device(scoped_refptr<device::BluetoothAdapter> adapter, adapter_->AddObserver(this); } -void Device::GetServicesImpl(const GetServicesCallback& callback) { +void Device::GetServicesImpl(GetServicesCallback callback) { device::BluetoothDevice* device = adapter_->GetDevice(GetAddress()); DCHECK(device); @@ -316,7 +321,7 @@ void Device::GetServicesImpl(const GetServicesCallback& callback) { services.push_back(ConstructServiceInfoStruct(*service)); } - callback.Run(std::move(services)); + std::move(callback).Run(std::move(services)); } mojom::ServiceInfoPtr Device::ConstructServiceInfoStruct( @@ -331,51 +336,49 @@ mojom::ServiceInfoPtr Device::ConstructServiceInfoStruct( } void Device::OnReadRemoteCharacteristic( - const ReadValueForCharacteristicCallback& callback, + ReadValueForCharacteristicCallback callback, const std::vector<uint8_t>& value) { - callback.Run(mojom::GattResult::SUCCESS, std::move(value)); + std::move(callback).Run(mojom::GattResult::SUCCESS, std::move(value)); } void Device::OnReadRemoteCharacteristicError( - const ReadValueForCharacteristicCallback& callback, + ReadValueForCharacteristicCallback callback, device::BluetoothGattService::GattErrorCode error_code) { - callback.Run(mojo::ConvertTo<mojom::GattResult>(error_code), - base::nullopt /* value */); + std::move(callback).Run(mojo::ConvertTo<mojom::GattResult>(error_code), + base::nullopt /* value */); } void Device::OnWriteRemoteCharacteristic( - const WriteValueForCharacteristicCallback& callback) { - callback.Run(mojom::GattResult::SUCCESS); + WriteValueForCharacteristicCallback callback) { + std::move(callback).Run(mojom::GattResult::SUCCESS); } void Device::OnWriteRemoteCharacteristicError( - const WriteValueForCharacteristicCallback& callback, + WriteValueForCharacteristicCallback callback, device::BluetoothGattService::GattErrorCode error_code) { - callback.Run(mojo::ConvertTo<mojom::GattResult>(error_code)); + std::move(callback).Run(mojo::ConvertTo<mojom::GattResult>(error_code)); } -void Device::OnReadRemoteDescriptor( - const ReadValueForDescriptorCallback& callback, - const std::vector<uint8_t>& value) { - callback.Run(mojom::GattResult::SUCCESS, std::move(value)); +void Device::OnReadRemoteDescriptor(ReadValueForDescriptorCallback callback, + const std::vector<uint8_t>& value) { + std::move(callback).Run(mojom::GattResult::SUCCESS, std::move(value)); } void Device::OnReadRemoteDescriptorError( - const ReadValueForDescriptorCallback& callback, + ReadValueForDescriptorCallback callback, device::BluetoothGattService::GattErrorCode error_code) { - callback.Run(mojo::ConvertTo<mojom::GattResult>(error_code), - base::nullopt /* value */); + std::move(callback).Run(mojo::ConvertTo<mojom::GattResult>(error_code), + base::nullopt /* value */); } -void Device::OnWriteRemoteDescriptor( - const WriteValueForDescriptorCallback& callback) { - callback.Run(mojom::GattResult::SUCCESS); +void Device::OnWriteRemoteDescriptor(WriteValueForDescriptorCallback callback) { + std::move(callback).Run(mojom::GattResult::SUCCESS); } void Device::OnWriteRemoteDescriptorError( - const WriteValueForDescriptorCallback& callback, + WriteValueForDescriptorCallback callback, device::BluetoothGattService::GattErrorCode error_code) { - callback.Run(mojo::ConvertTo<mojom::GattResult>(error_code)); + std::move(callback).Run(mojo::ConvertTo<mojom::GattResult>(error_code)); } const std::string& Device::GetAddress() { diff --git a/chromium/device/bluetooth/device.h b/chromium/device/bluetooth/device.h index 223f19d7f7a..ceda813bd84 100644 --- a/chromium/device/bluetooth/device.h +++ b/chromium/device/bluetooth/device.h @@ -51,69 +51,67 @@ class Device : public mojom::Device, public device::BluetoothAdapter::Observer { // mojom::Device overrides: void Disconnect() override; - void GetInfo(const GetInfoCallback& callback) override; - void GetServices(const GetServicesCallback& callback) override; + void GetInfo(GetInfoCallback callback) override; + void GetServices(GetServicesCallback callback) override; void GetCharacteristics(const std::string& service_id, - const GetCharacteristicsCallback& callback) override; + GetCharacteristicsCallback callback) override; void ReadValueForCharacteristic( const std::string& service_id, const std::string& characteristic_id, - const ReadValueForCharacteristicCallback& callback) override; + ReadValueForCharacteristicCallback callback) override; void WriteValueForCharacteristic( const std::string& service_id, const std::string& characteristic_id, const std::vector<uint8_t>& value, - const WriteValueForCharacteristicCallback& callback) override; + WriteValueForCharacteristicCallback callback) override; void GetDescriptors(const std::string& service_id, const std::string& characteristic_id, - const GetDescriptorsCallback& callback) override; - void ReadValueForDescriptor( - const std::string& service_id, - const std::string& characteristic_id, - const std::string& descriptor_id, - const ReadValueForDescriptorCallback& callback) override; + GetDescriptorsCallback callback) override; + void ReadValueForDescriptor(const std::string& service_id, + const std::string& characteristic_id, + const std::string& descriptor_id, + ReadValueForDescriptorCallback callback) override; void WriteValueForDescriptor( const std::string& service_id, const std::string& characteristic_id, const std::string& descriptor_id, const std::vector<uint8_t>& value, - const WriteValueForDescriptorCallback& callback) override; + WriteValueForDescriptorCallback callback) override; private: Device(scoped_refptr<device::BluetoothAdapter> adapter, std::unique_ptr<device::BluetoothGattConnection> connection); - void GetServicesImpl(const GetServicesCallback& callback); + void GetServicesImpl(GetServicesCallback callback); mojom::ServiceInfoPtr ConstructServiceInfoStruct( const device::BluetoothRemoteGattService& service); - void OnReadRemoteCharacteristic( - const ReadValueForCharacteristicCallback& callback, - const std::vector<uint8_t>& value); + void OnReadRemoteCharacteristic(ReadValueForCharacteristicCallback callback, + const std::vector<uint8_t>& value); void OnReadRemoteCharacteristicError( - const ReadValueForCharacteristicCallback& callback, + ReadValueForCharacteristicCallback callback, device::BluetoothGattService::GattErrorCode error_code); void OnWriteRemoteCharacteristic( - const WriteValueForCharacteristicCallback& callback); + WriteValueForCharacteristicCallback callback); void OnWriteRemoteCharacteristicError( - const WriteValueForCharacteristicCallback& callback, + WriteValueForCharacteristicCallback callback, device::BluetoothGattService::GattErrorCode error_code); - void OnReadRemoteDescriptor(const ReadValueForDescriptorCallback& callback, + void OnReadRemoteDescriptor(ReadValueForDescriptorCallback callback, const std::vector<uint8_t>& value); void OnReadRemoteDescriptorError( - const ReadValueForDescriptorCallback& callback, + ReadValueForDescriptorCallback callback, device::BluetoothGattService::GattErrorCode error_code); - void OnWriteRemoteDescriptor(const WriteValueForDescriptorCallback& callback); + void OnWriteRemoteDescriptor(WriteValueForDescriptorCallback callback); void OnWriteRemoteDescriptorError( - const WriteValueForDescriptorCallback& callback, + WriteValueForDescriptorCallback callback, device::BluetoothGattService::GattErrorCode error_code); const std::string& GetAddress(); diff --git a/chromium/device/bluetooth/discovery_session.cc b/chromium/device/bluetooth/discovery_session.cc index 0ecc1cf056e..5e4d62f3bf4 100644 --- a/chromium/device/bluetooth/discovery_session.cc +++ b/chromium/device/bluetooth/discovery_session.cc @@ -2,9 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/bind_helpers.h" #include "device/bluetooth/discovery_session.h" +#include "base/bind_helpers.h" +#include "base/callback_helpers.h" + namespace bluetooth { DiscoverySession::DiscoverySession( std::unique_ptr<device::BluetoothDiscoverySession> session) @@ -12,24 +14,25 @@ DiscoverySession::DiscoverySession( DiscoverySession::~DiscoverySession() {} -void DiscoverySession::IsActive(const IsActiveCallback& callback) { - callback.Run(discovery_session_->IsActive()); +void DiscoverySession::IsActive(IsActiveCallback callback) { + std::move(callback).Run(discovery_session_->IsActive()); } -void DiscoverySession::Stop(const StopCallback& callback) { +void DiscoverySession::Stop(StopCallback callback) { + auto copyable_callback = base::AdaptCallbackForRepeating(std::move(callback)); discovery_session_->Stop( base::Bind(&DiscoverySession::OnStop, weak_ptr_factory_.GetWeakPtr(), - callback), + copyable_callback), base::Bind(&DiscoverySession::OnStopError, weak_ptr_factory_.GetWeakPtr(), - callback)); + copyable_callback)); } -void DiscoverySession::OnStop(const StopCallback& callback) { - callback.Run(true /* success */); +void DiscoverySession::OnStop(StopCallback callback) { + std::move(callback).Run(true /* success */); } -void DiscoverySession::OnStopError(const StopCallback& callback) { - callback.Run(false /* success */); +void DiscoverySession::OnStopError(StopCallback callback) { + std::move(callback).Run(false /* success */); } } // namespace bluetooth diff --git a/chromium/device/bluetooth/discovery_session.h b/chromium/device/bluetooth/discovery_session.h index 0967b845adb..b2ba5dcf795 100644 --- a/chromium/device/bluetooth/discovery_session.h +++ b/chromium/device/bluetooth/discovery_session.h @@ -27,12 +27,12 @@ class DiscoverySession : public mojom::DiscoverySession { ~DiscoverySession() override; // mojom::DiscoverySession overrides: - void IsActive(const IsActiveCallback& callback) override; - void Stop(const StopCallback& callback) override; + void IsActive(IsActiveCallback callback) override; + void Stop(StopCallback callback) override; private: - void OnStop(const StopCallback& callback); - void OnStopError(const StopCallback& callback); + void OnStop(StopCallback callback); + void OnStopError(StopCallback callback); // The underlying discovery session. std::unique_ptr<device::BluetoothDiscoverySession> discovery_session_; diff --git a/chromium/device/bluetooth/public/interfaces/BUILD.gn b/chromium/device/bluetooth/public/interfaces/BUILD.gn index 810489bc065..4ef85b8de62 100644 --- a/chromium/device/bluetooth/public/interfaces/BUILD.gn +++ b/chromium/device/bluetooth/public/interfaces/BUILD.gn @@ -10,6 +10,18 @@ mojom("interfaces") { ] } +mojom("fake_bluetooth_interfaces") { + sources = [ + "test/fake_bluetooth.mojom", + ] + + public_deps = [ + ":interfaces", + ] + + use_once_callback = true +} + mojom("experimental_interfaces") { sources = [ "adapter.mojom", diff --git a/chromium/device/bluetooth/public/interfaces/test/fake_bluetooth.mojom b/chromium/device/bluetooth/public/interfaces/test/fake_bluetooth.mojom new file mode 100644 index 00000000000..a9d71faed3b --- /dev/null +++ b/chromium/device/bluetooth/public/interfaces/test/fake_bluetooth.mojom @@ -0,0 +1,54 @@ +// Copyright 2017 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. + +module bluetooth.mojom; + +import "device/bluetooth/public/interfaces/uuid.mojom"; + +// FakeBluetooth and its related interfaces allow clients to control the global +// Bluetooth State as well as simulate Bluetooth events including finding new +// devices, simulating GATT attributes and its descendants, and simulating +// success and error responses. + +// Indicates the various states of Central. +enum CentralState { + ABSENT, + POWERED_ON, + POWERED_OFF, +}; + +// FakeBluetooth allows clients to control the global Bluetooth state. +interface FakeBluetooth { + // Set it to indicate whether the platform supports BLE. For example, Windows + // 7 is a platform that doesn't support Low Energy. On the other hand Windows + // 10 is a platform that does support LE, even if there is no Bluetooth radio + // available. + SetLESupported(bool available) => (); + + // Initializes a fake Central with |state| as the initial state. + SimulateCentral(CentralState state) => (FakeCentral fake_central); +}; + +// FakeCentral allows clients to simulate events that a device in the +// Central/Observer role would receive as well as monitor the operations +// performed by the device in the Central/Observer role. +// +// A "Central" interface would allow its clients to receive advertising events +// and initiate connections to peripherals i.e. operations of two roles +// defined by the Bluetooth Spec: Observer and Central. +// See Bluetooth 4.2 Vol 3 Part C 2.2.2 "Roles when Operating over an +// LE Physical Transport". +interface FakeCentral { + // Simulates a peripheral with |address|, |name| and |known_service_uuids| + // that has already been connected to the system. If the peripheral existed + // already it updates its name and known UUIDs. + // + // Platforms offer methods to retrieve devices that have already been + // connected to the system or weren't connected through the UA e.g. a user + // connected a peripheral through the system's settings. This method is + // intended to simulate peripherals that those methods would return. + SimulatePreconnectedPeripheral(string address, + string name, + array<UUID> known_service_uuids) => (); +}; diff --git a/chromium/device/bluetooth/strings/bluetooth_strings_fi.xtb b/chromium/device/bluetooth/strings/bluetooth_strings_fi.xtb index f3ab9aa1126..151ff2b6abd 100644 --- a/chromium/device/bluetooth/strings/bluetooth_strings_fi.xtb +++ b/chromium/device/bluetooth/strings/bluetooth_strings_fi.xtb @@ -6,7 +6,7 @@ <translation id="3273951168350045122">Näppäimistö (<ph name="ADDRESS" />)</translation> <translation id="4287283380557401002">Auton ääni (<ph name="ADDRESS" />)</translation> <translation id="430326050669417502">Joystick (<ph name="ADDRESS" />)</translation> -<translation id="5271696982761495740">Tablet-laite (<ph name="ADDRESS" />)</translation> +<translation id="5271696982761495740">Tabletti (<ph name="ADDRESS" />)</translation> <translation id="5376363957846771741">Tuntematon tai ei-tuettu laite (<ph name="ADDRESS" />)</translation> <translation id="654594702871184195">Ääni (<ph name="ADDRESS" />)</translation> <translation id="6744468237221042970">Tietokone (<ph name="ADDRESS" />)</translation> diff --git a/chromium/device/gamepad/BUILD.gn b/chromium/device/gamepad/BUILD.gn index f9634734982..2cbc2e5c139 100644 --- a/chromium/device/gamepad/BUILD.gn +++ b/chromium/device/gamepad/BUILD.gn @@ -60,6 +60,7 @@ component("gamepad") { "//base", "//base/third_party/dynamic_annotations", "//device/base/synchronization", + "//device/gamepad/public/cpp:shared_with_blink", "//device/gamepad/public/interfaces", "//mojo/public/cpp/system", "//third_party/WebKit/public:blink_headers", @@ -104,6 +105,7 @@ static_library("test_helpers") { public_deps = [ ":gamepad", "//base", + "//device/gamepad/public/cpp:shared_with_blink", "//third_party/WebKit/public:blink_headers", ] } diff --git a/chromium/device/gamepad/DEPS b/chromium/device/gamepad/DEPS index 299c60a1056..c80012b5621 100644 --- a/chromium/device/gamepad/DEPS +++ b/chromium/device/gamepad/DEPS @@ -1,5 +1,3 @@ include_rules = [ "+jni", - "+third_party/WebKit/public/platform/WebGamepad.h", - "+third_party/WebKit/public/platform/WebGamepads.h", ] diff --git a/chromium/device/gamepad/game_controller_data_fetcher_mac.mm b/chromium/device/gamepad/game_controller_data_fetcher_mac.mm index 797831cbfed..9be2d8fcfdd 100644 --- a/chromium/device/gamepad/game_controller_data_fetcher_mac.mm +++ b/chromium/device/gamepad/game_controller_data_fetcher_mac.mm @@ -14,19 +14,16 @@ #import <GameController/GameController.h> -using blink::WebGamepad; -using blink::WebGamepads; - namespace device { namespace { void CopyNSStringAsUTF16LittleEndian(NSString* src, - blink::WebUChar* dest, + UChar* dest, size_t dest_len) { NSData* as16 = [src dataUsingEncoding:NSUTF16LittleEndianStringEncoding]; memset(dest, 0, dest_len); - [as16 getBytes:dest length:dest_len - sizeof(blink::WebUChar)]; + [as16 getBytes:dest length:dest_len - sizeof(UChar)]; } } // namespace @@ -55,7 +52,7 @@ void GameControllerDataFetcherMac::GetGamepadData(bool) { if (!state) continue; - WebGamepad& pad = state->data; + Gamepad& pad = state->data; // This first time we encounter a gamepad, set its name, mapping, and // axes/button counts. This information is static, so it only needs to be diff --git a/chromium/device/gamepad/gamepad_consumer.h b/chromium/device/gamepad/gamepad_consumer.h index 7c9201a0ae2..f80183d2e55 100644 --- a/chromium/device/gamepad/gamepad_consumer.h +++ b/chromium/device/gamepad/gamepad_consumer.h @@ -6,7 +6,7 @@ #define DEVICE_GAMEPAD_GAMEPAD_CONSUMER_H_ #include "device/gamepad/gamepad_export.h" -#include "third_party/WebKit/public/platform/WebGamepad.h" +#include "device/gamepad/public/cpp/gamepad.h" namespace device { @@ -15,10 +15,9 @@ class DEVICE_GAMEPAD_EXPORT GamepadConsumer { GamepadConsumer(); virtual ~GamepadConsumer(); - virtual void OnGamepadConnected(unsigned index, - const blink::WebGamepad& gamepad) = 0; + virtual void OnGamepadConnected(unsigned index, const Gamepad& gamepad) = 0; virtual void OnGamepadDisconnected(unsigned index, - const blink::WebGamepad& gamepad) = 0; + const Gamepad& gamepad) = 0; }; } // namespace device diff --git a/chromium/device/gamepad/gamepad_monitor.cc b/chromium/device/gamepad/gamepad_monitor.cc index 93990d3711a..7ba2e834915 100644 --- a/chromium/device/gamepad/gamepad_monitor.cc +++ b/chromium/device/gamepad/gamepad_monitor.cc @@ -4,6 +4,8 @@ #include "device/gamepad/gamepad_monitor.h" +#include <utility> + #include "base/memory/ptr_util.h" #include "base/memory/shared_memory.h" #include "device/gamepad/gamepad_service.h" @@ -20,40 +22,39 @@ GamepadMonitor::~GamepadMonitor() { } // static -void GamepadMonitor::Create(mojom::GamepadMonitorRequest request) { +void GamepadMonitor::Create(const service_manager::BindSourceInfo& source_info, + mojom::GamepadMonitorRequest request) { mojo::MakeStrongBinding(base::MakeUnique<GamepadMonitor>(), std::move(request)); } void GamepadMonitor::OnGamepadConnected(unsigned index, - const blink::WebGamepad& gamepad) { + const Gamepad& gamepad) { if (gamepad_observer_) gamepad_observer_->GamepadConnected(index, gamepad); } void GamepadMonitor::OnGamepadDisconnected(unsigned index, - const blink::WebGamepad& gamepad) { + const Gamepad& gamepad) { if (gamepad_observer_) gamepad_observer_->GamepadDisconnected(index, gamepad); } -void GamepadMonitor::GamepadStartPolling( - const GamepadStartPollingCallback& callback) { +void GamepadMonitor::GamepadStartPolling(GamepadStartPollingCallback callback) { DCHECK(!is_started_); is_started_ = true; GamepadService* service = GamepadService::GetInstance(); service->ConsumerBecameActive(this); - callback.Run(service->GetSharedBufferHandle()); + std::move(callback).Run(service->GetSharedBufferHandle()); } -void GamepadMonitor::GamepadStopPolling( - const GamepadStopPollingCallback& callback) { +void GamepadMonitor::GamepadStopPolling(GamepadStopPollingCallback callback) { DCHECK(is_started_); is_started_ = false; GamepadService::GetInstance()->ConsumerBecameInactive(this); - callback.Run(); + std::move(callback).Run(); } void GamepadMonitor::SetObserver(mojom::GamepadObserverPtr gamepad_observer) { diff --git a/chromium/device/gamepad/gamepad_monitor.h b/chromium/device/gamepad/gamepad_monitor.h index fab371e3f47..19d0d0d931a 100644 --- a/chromium/device/gamepad/gamepad_monitor.h +++ b/chromium/device/gamepad/gamepad_monitor.h @@ -11,6 +11,10 @@ #include "device/gamepad/gamepad_export.h" #include "device/gamepad/public/interfaces/gamepad.mojom.h" +namespace service_manager { +struct BindSourceInfo; +} + namespace device { class DEVICE_GAMEPAD_EXPORT GamepadMonitor @@ -20,18 +24,16 @@ class DEVICE_GAMEPAD_EXPORT GamepadMonitor GamepadMonitor(); ~GamepadMonitor() override; - static void Create(mojom::GamepadMonitorRequest request); + static void Create(const service_manager::BindSourceInfo& source_info, + mojom::GamepadMonitorRequest request); // GamepadConsumer implementation. - void OnGamepadConnected(unsigned index, - const blink::WebGamepad& gamepad) override; - void OnGamepadDisconnected(unsigned index, - const blink::WebGamepad& gamepad) override; + void OnGamepadConnected(unsigned index, const Gamepad& gamepad) override; + void OnGamepadDisconnected(unsigned index, const Gamepad& gamepad) override; // mojom::GamepadMonitor implementation. - void GamepadStartPolling( - const GamepadStartPollingCallback& callback) override; - void GamepadStopPolling(const GamepadStopPollingCallback& callback) override; + void GamepadStartPolling(GamepadStartPollingCallback callback) override; + void GamepadStopPolling(GamepadStopPollingCallback callback) override; void SetObserver(mojom::GamepadObserverPtr gamepad_observer) override; private: diff --git a/chromium/device/gamepad/gamepad_pad_state_provider.cc b/chromium/device/gamepad/gamepad_pad_state_provider.cc index afc8beb798e..8f525cb4d1e 100644 --- a/chromium/device/gamepad/gamepad_pad_state_provider.cc +++ b/chromium/device/gamepad/gamepad_pad_state_provider.cc @@ -7,10 +7,7 @@ #include <cmath> #include "device/gamepad/gamepad_data_fetcher.h" -#include "third_party/WebKit/public/platform/WebGamepads.h" - -using blink::WebGamepad; -using blink::WebGamepads; +#include "device/gamepad/public/cpp/gamepads.h" namespace device { @@ -21,9 +18,9 @@ const float kMinAxisResetValue = 0.1f; } // namespace GamepadPadStateProvider::GamepadPadStateProvider() { - pad_states_.reset(new PadState[WebGamepads::kItemsLengthCap]); + pad_states_.reset(new PadState[Gamepads::kItemsLengthCap]); - for (unsigned i = 0; i < WebGamepads::kItemsLengthCap; ++i) + for (unsigned i = 0; i < Gamepads::kItemsLengthCap; ++i) ClearPadState(pad_states_.get()[i]); } @@ -33,7 +30,7 @@ PadState* GamepadPadStateProvider::GetPadState(GamepadSource source, int source_id) { // Check to see if the device already has a reserved slot PadState* empty_slot = nullptr; - for (size_t i = 0; i < WebGamepads::kItemsLengthCap; ++i) { + for (size_t i = 0; i < Gamepads::kItemsLengthCap; ++i) { PadState& state = pad_states_.get()[i]; if (state.source == source && state.source_id == source_id) { // Retrieving the pad state marks this gamepad as active. @@ -61,13 +58,13 @@ void GamepadPadStateProvider::InitializeDataFetcher( } void GamepadPadStateProvider::MapAndSanitizeGamepadData(PadState* pad_state, - WebGamepad* pad, + Gamepad* pad, bool sanitize) { DCHECK(pad_state); DCHECK(pad); if (!pad_state->data.connected) { - memset(pad, 0, sizeof(WebGamepad)); + memset(pad, 0, sizeof(Gamepad)); return; } diff --git a/chromium/device/gamepad/gamepad_pad_state_provider.h b/chromium/device/gamepad/gamepad_pad_state_provider.h index 3ba83420eda..64356711f2d 100644 --- a/chromium/device/gamepad/gamepad_pad_state_provider.h +++ b/chromium/device/gamepad/gamepad_pad_state_provider.h @@ -12,7 +12,7 @@ #include "device/gamepad/gamepad_export.h" #include "device/gamepad/gamepad_standard_mappings.h" -#include "third_party/WebKit/public/platform/WebGamepad.h" +#include "device/gamepad/public/cpp/gamepad.h" namespace device { @@ -22,10 +22,12 @@ enum GamepadSource { GAMEPAD_SOURCE_NONE = 0, GAMEPAD_SOURCE_ANDROID, GAMEPAD_SOURCE_GVR, + GAMEPAD_SOURCE_CARDBOARD, GAMEPAD_SOURCE_LINUX_UDEV, GAMEPAD_SOURCE_MAC_GC, GAMEPAD_SOURCE_MAC_HID, GAMEPAD_SOURCE_MAC_XBOX, + GAMEPAD_SOURCE_OPENVR, GAMEPAD_SOURCE_TEST, GAMEPAD_SOURCE_WIN_XINPUT, GAMEPAD_SOURCE_WIN_RAW, @@ -47,7 +49,7 @@ struct PadState { GamepadActiveState active_state; // Gamepad data, unmapped. - blink::WebGamepad data; + Gamepad data; // Functions to map from device data to standard layout, if available. May // be null if no mapping is available or needed. @@ -59,13 +61,13 @@ struct PadState { // corresponding bit will be set to 1. // If we ever increase the max axis count this will need to be updated. - static_assert(blink::WebGamepad::kAxesLengthCap <= + static_assert(Gamepad::kAxesLengthCap <= std::numeric_limits<uint32_t>::digits, "axis_mask is not large enough"); uint32_t axis_mask; // If we ever increase the max button count this will need to be updated. - static_assert(blink::WebGamepad::kButtonsLengthCap <= + static_assert(Gamepad::kButtonsLengthCap <= std::numeric_limits<uint32_t>::digits, "button_mask is not large enough"); uint32_t button_mask; @@ -87,7 +89,7 @@ class DEVICE_GAMEPAD_EXPORT GamepadPadStateProvider { void InitializeDataFetcher(GamepadDataFetcher* fetcher); void MapAndSanitizeGamepadData(PadState* pad_state, - blink::WebGamepad* pad, + Gamepad* pad, bool sanitize); // Tracks the state of each gamepad slot. diff --git a/chromium/device/gamepad/gamepad_platform_data_fetcher_android.cc b/chromium/device/gamepad/gamepad_platform_data_fetcher_android.cc index d57649ccd06..f925b07291b 100644 --- a/chromium/device/gamepad/gamepad_platform_data_fetcher_android.cc +++ b/chromium/device/gamepad/gamepad_platform_data_fetcher_android.cc @@ -16,16 +16,12 @@ #include "jni/GamepadList_jni.h" -#include "third_party/WebKit/public/platform/WebGamepads.h" - using base::android::AttachCurrentThread; using base::android::CheckException; using base::android::ClearException; using base::android::ConvertJavaStringToUTF8; using base::android::JavaParamRef; using base::android::ScopedJavaLocalRef; -using blink::WebGamepad; -using blink::WebGamepads; namespace device { @@ -81,7 +77,7 @@ static void SetGamepadData(JNIEnv* env, DCHECK(data_fetcher); GamepadPlatformDataFetcherAndroid* fetcher = reinterpret_cast<GamepadPlatformDataFetcherAndroid*>(data_fetcher); - DCHECK_LT(index, static_cast<int>(blink::WebGamepads::kItemsLengthCap)); + DCHECK_LT(index, static_cast<int>(Gamepads::kItemsLengthCap)); // Do not set gamepad parameters for all the gamepad devices that are not // attached. @@ -93,25 +89,25 @@ static void SetGamepadData(JNIEnv* env, if (!state) return; - blink::WebGamepad& pad = state->data; + Gamepad& pad = state->data; // Is this the first time we've seen this device? if (state->active_state == GAMEPAD_NEWLY_ACTIVE) { - // Map the Gamepad DeviceName String to the WebGamepad Id. Ideally it should + // Map the Gamepad DeviceName String to the Gamepad Id. Ideally it should // be mapped to vendor and product information but it is only available at // kernel level and it can not be queried using class // android.hardware.input.InputManager. base::string16 device_name; base::android::ConvertJavaStringToUTF16(env, devicename, &device_name); const size_t name_to_copy = - std::min(device_name.size(), WebGamepad::kIdLengthCap - 1); + std::min(device_name.size(), Gamepad::kIdLengthCap - 1); memcpy(pad.id, device_name.data(), name_to_copy * sizeof(base::string16::value_type)); pad.id[name_to_copy] = 0; base::string16 mapping_name = base::UTF8ToUTF16(mapping ? "standard" : ""); const size_t mapping_to_copy = - std::min(mapping_name.size(), WebGamepad::kMappingLengthCap - 1); + std::min(mapping_name.size(), Gamepad::kMappingLengthCap - 1); memcpy(pad.mapping, mapping_name.data(), mapping_to_copy * sizeof(base::string16::value_type)); pad.mapping[mapping_to_copy] = 0; @@ -123,13 +119,13 @@ static void SetGamepadData(JNIEnv* env, std::vector<float> axes; base::android::JavaFloatArrayToFloatVector(env, jaxes, &axes); - // Set WebGamepad axeslength to total number of axes on the gamepad device. + // Set Gamepad axeslength to total number of axes on the gamepad device. // Only return the first axesLengthCap if axeslength captured by GamepadList // is larger than axesLengthCap. pad.axes_length = std::min(static_cast<int>(axes.size()), - static_cast<int>(WebGamepad::kAxesLengthCap)); + static_cast<int>(Gamepad::kAxesLengthCap)); - // Copy axes state to the WebGamepad axes[]. + // Copy axes state to the Gamepad axes[]. for (unsigned int i = 0; i < pad.axes_length; i++) { pad.axes[i] = static_cast<double>(axes[i]); } @@ -137,14 +133,13 @@ static void SetGamepadData(JNIEnv* env, std::vector<float> buttons; base::android::JavaFloatArrayToFloatVector(env, jbuttons, &buttons); - // Set WebGamepad buttonslength to total number of axes on the gamepad + // Set Gamepad buttonslength to total number of axes on the gamepad // device. Only return the first buttonsLengthCap if axeslength captured by // GamepadList is larger than buttonsLengthCap. - pad.buttons_length = - std::min(static_cast<int>(buttons.size()), - static_cast<int>(WebGamepad::kButtonsLengthCap)); + pad.buttons_length = std::min(static_cast<int>(buttons.size()), + static_cast<int>(Gamepad::kButtonsLengthCap)); - // Copy buttons state to the WebGamepad buttons[]. + // Copy buttons state to the Gamepad buttons[]. for (unsigned int j = 0; j < pad.buttons_length; j++) { pad.buttons[j].pressed = buttons[j]; pad.buttons[j].value = buttons[j]; diff --git a/chromium/device/gamepad/gamepad_platform_data_fetcher_android.h b/chromium/device/gamepad/gamepad_platform_data_fetcher_android.h index 760ef9b346b..158b5ccf043 100644 --- a/chromium/device/gamepad/gamepad_platform_data_fetcher_android.h +++ b/chromium/device/gamepad/gamepad_platform_data_fetcher_android.h @@ -15,7 +15,7 @@ #include "device/gamepad/gamepad_data_fetcher.h" #include "device/gamepad/gamepad_provider.h" #include "device/gamepad/gamepad_standard_mappings.h" -#include "third_party/WebKit/public/platform/WebGamepads.h" +#include "device/gamepad/public/cpp/gamepads.h" namespace device { diff --git a/chromium/device/gamepad/gamepad_platform_data_fetcher_linux.cc b/chromium/device/gamepad/gamepad_platform_data_fetcher_linux.cc index bfd23d93dd6..d33f0de75f2 100644 --- a/chromium/device/gamepad/gamepad_platform_data_fetcher_linux.cc +++ b/chromium/device/gamepad/gamepad_platform_data_fetcher_linux.cc @@ -52,7 +52,7 @@ bool IsGamepad(udev_device* dev, int* index, std::string* path) { if (!base::StringToInt(str, &tmp_idx)) return false; if (tmp_idx < 0 || - tmp_idx >= static_cast<int>(blink::WebGamepads::kItemsLengthCap)) { + tmp_idx >= static_cast<int>(device::Gamepads::kItemsLengthCap)) { return false; } *index = tmp_idx; @@ -64,9 +64,6 @@ bool IsGamepad(udev_device* dev, int* index, std::string* path) { namespace device { -using blink::WebGamepad; -using blink::WebGamepads; - GamepadPlatformDataFetcherLinux::GamepadPlatformDataFetcherLinux() { for (size_t i = 0; i < arraysize(device_fd_); ++i) { device_fd_[i] = -1; @@ -74,7 +71,7 @@ GamepadPlatformDataFetcherLinux::GamepadPlatformDataFetcherLinux() { } GamepadPlatformDataFetcherLinux::~GamepadPlatformDataFetcherLinux() { - for (size_t i = 0; i < WebGamepads::kItemsLengthCap; ++i) + for (size_t i = 0; i < Gamepads::kItemsLengthCap; ++i) CloseFileDescriptorIfValid(device_fd_[i]); } @@ -96,7 +93,7 @@ void GamepadPlatformDataFetcherLinux::GetGamepadData(bool) { TRACE_EVENT0("GAMEPAD", "GetGamepadData"); // Update our internal state. - for (size_t i = 0; i < WebGamepads::kItemsLengthCap; ++i) { + for (size_t i = 0; i < Gamepads::kItemsLengthCap; ++i) { if (device_fd_[i] >= 0) { ReadDeviceData(i); } @@ -138,7 +135,7 @@ void GamepadPlatformDataFetcherLinux::RefreshDevice(udev_device* dev) { return; } - WebGamepad& pad = state->data; + Gamepad& pad = state->data; GamepadStandardMappingFunction& mapper = state->mapper; const char* vendor_id = udev_device_get_sysattr_value(dev, "id/vendor"); @@ -181,14 +178,14 @@ void GamepadPlatformDataFetcherLinux::RefreshDevice(udev_device* dev) { name_string + base::StringPrintf(" (%sVendor: %s Product: %s)", mapper ? "STANDARD GAMEPAD " : "", vendor_id, product_id); - base::TruncateUTF8ToByteSize(id, WebGamepad::kIdLengthCap - 1, &id); + base::TruncateUTF8ToByteSize(id, Gamepad::kIdLengthCap - 1, &id); base::string16 tmp16 = base::UTF8ToUTF16(id); memset(pad.id, 0, sizeof(pad.id)); tmp16.copy(pad.id, arraysize(pad.id) - 1); if (mapper) { std::string mapping = "standard"; - base::TruncateUTF8ToByteSize(mapping, WebGamepad::kMappingLengthCap - 1, + base::TruncateUTF8ToByteSize(mapping, Gamepad::kMappingLengthCap - 1, &mapping); tmp16 = base::UTF8ToUTF16(mapping); memset(pad.mapping, 0, sizeof(pad.mapping)); @@ -228,8 +225,8 @@ void GamepadPlatformDataFetcherLinux::EnumerateDevices() { } void GamepadPlatformDataFetcherLinux::ReadDeviceData(size_t index) { - // Linker does not like CHECK_LT(index, WebGamepads::itemsLengthCap). =/ - if (index >= WebGamepads::kItemsLengthCap) { + // Linker does not like CHECK_LT(index, Gamepads::kItemsLengthCap). =/ + if (index >= Gamepads::kItemsLengthCap) { CHECK(false); return; } @@ -241,13 +238,13 @@ void GamepadPlatformDataFetcherLinux::ReadDeviceData(size_t index) { int fd = device_fd_[index]; DCHECK_GE(fd, 0); - WebGamepad& pad = state->data; + Gamepad& pad = state->data; js_event event; while (HANDLE_EINTR(read(fd, &event, sizeof(struct js_event))) > 0) { size_t item = event.number; if (event.type & JS_EVENT_AXIS) { - if (item >= WebGamepad::kAxesLengthCap) + if (item >= Gamepad::kAxesLengthCap) continue; pad.axes[item] = event.value / kMaxLinuxAxisValue; @@ -255,7 +252,7 @@ void GamepadPlatformDataFetcherLinux::ReadDeviceData(size_t index) { if (item >= pad.axes_length) pad.axes_length = item + 1; } else if (event.type & JS_EVENT_BUTTON) { - if (item >= WebGamepad::kButtonsLengthCap) + if (item >= Gamepad::kButtonsLengthCap) continue; pad.buttons[item].pressed = event.value; diff --git a/chromium/device/gamepad/gamepad_platform_data_fetcher_linux.h b/chromium/device/gamepad/gamepad_platform_data_fetcher_linux.h index da22ba3c60c..0d51e279c0e 100644 --- a/chromium/device/gamepad/gamepad_platform_data_fetcher_linux.h +++ b/chromium/device/gamepad/gamepad_platform_data_fetcher_linux.h @@ -13,6 +13,7 @@ #include "base/compiler_specific.h" #include "base/macros.h" #include "device/gamepad/gamepad_data_fetcher.h" +#include "device/gamepad/public/cpp/gamepads.h" extern "C" { struct udev_device; @@ -47,7 +48,7 @@ class DEVICE_GAMEPAD_EXPORT GamepadPlatformDataFetcherLinux void ReadDeviceData(size_t index); // File descriptor for the /dev/input/js* devices. -1 if not in use. - int device_fd_[blink::WebGamepads::kItemsLengthCap]; + int device_fd_[Gamepads::kItemsLengthCap]; std::unique_ptr<device::UdevLinux> udev_; diff --git a/chromium/device/gamepad/gamepad_platform_data_fetcher_mac.h b/chromium/device/gamepad/gamepad_platform_data_fetcher_mac.h index 11808f30b6b..c65cde9e71a 100644 --- a/chromium/device/gamepad/gamepad_platform_data_fetcher_mac.h +++ b/chromium/device/gamepad/gamepad_platform_data_fetcher_mac.h @@ -16,6 +16,7 @@ #include "base/macros.h" #include "build/build_config.h" #include "device/gamepad/gamepad_data_fetcher.h" +#include "device/gamepad/public/cpp/gamepad.h" #if defined(__OBJC__) @class NSArray; @@ -77,13 +78,13 @@ class GamepadPlatformDataFetcherMac : public GamepadDataFetcher { struct AssociatedData { int location_id; IOHIDDeviceRef device_ref; - IOHIDElementRef button_elements[blink::WebGamepad::kButtonsLengthCap]; - IOHIDElementRef axis_elements[blink::WebGamepad::kAxesLengthCap]; - CFIndex axis_minimums[blink::WebGamepad::kAxesLengthCap]; - CFIndex axis_maximums[blink::WebGamepad::kAxesLengthCap]; - CFIndex axis_report_sizes[blink::WebGamepad::kAxesLengthCap]; + IOHIDElementRef button_elements[Gamepad::kButtonsLengthCap]; + IOHIDElementRef axis_elements[Gamepad::kAxesLengthCap]; + CFIndex axis_minimums[Gamepad::kAxesLengthCap]; + CFIndex axis_maximums[Gamepad::kAxesLengthCap]; + CFIndex axis_report_sizes[Gamepad::kAxesLengthCap]; }; - AssociatedData associated_[blink::WebGamepads::kItemsLengthCap]; + AssociatedData associated_[Gamepads::kItemsLengthCap]; DISALLOW_COPY_AND_ASSIGN(GamepadPlatformDataFetcherMac); }; diff --git a/chromium/device/gamepad/gamepad_platform_data_fetcher_mac.mm b/chromium/device/gamepad/gamepad_platform_data_fetcher_mac.mm index 3e7313e6267..b091d96c942 100644 --- a/chromium/device/gamepad/gamepad_platform_data_fetcher_mac.mm +++ b/chromium/device/gamepad/gamepad_platform_data_fetcher_mac.mm @@ -18,19 +18,16 @@ #import <Foundation/Foundation.h> #include <IOKit/hid/IOHIDKeys.h> -using blink::WebGamepad; -using blink::WebGamepads; - namespace device { namespace { void CopyNSStringAsUTF16LittleEndian(NSString* src, - blink::WebUChar* dest, + UChar* dest, size_t dest_len) { NSData* as16 = [src dataUsingEncoding:NSUTF16LittleEndianStringEncoding]; memset(dest, 0, dest_len); - [as16 getBytes:dest length:dest_len - sizeof(blink::WebUChar)]; + [as16 getBytes:dest length:dest_len - sizeof(UChar)]; } NSDictionary* DeviceMatching(uint32_t usage_page, uint32_t usage) { @@ -179,7 +176,7 @@ bool GamepadPlatformDataFetcherMac::CheckCollection(IOHIDElementRef element) { bool GamepadPlatformDataFetcherMac::AddButtonsAndAxes(NSArray* elements, PadState* state, size_t slot) { - WebGamepad& pad = state->data; + Gamepad& pad = state->data; AssociatedData& associated = associated_[slot]; pad.axes_length = 0; @@ -200,13 +197,13 @@ bool GamepadPlatformDataFetcherMac::AddButtonsAndAxes(NSArray* elements, if (IOHIDElementGetType(element) == kIOHIDElementTypeInput_Button && usage_page == kButtonUsagePage) { uint32_t button_index = usage - 1; - if (button_index < WebGamepad::kButtonsLengthCap) { + if (button_index < Gamepad::kButtonsLengthCap) { associated.button_elements[button_index] = element; pad.buttons_length = std::max(pad.buttons_length, button_index + 1); } } else if (IOHIDElementGetType(element) == kIOHIDElementTypeInput_Misc) { uint32_t axis_index = usage - kAxisMinimumUsageNumber; - if (axis_index < WebGamepad::kAxesLengthCap) { + if (axis_index < Gamepad::kAxesLengthCap) { associated.axis_elements[axis_index] = element; pad.axes_length = std::max(pad.axes_length, axis_index + 1); } else { @@ -226,19 +223,19 @@ bool GamepadPlatformDataFetcherMac::AddButtonsAndAxes(NSArray* elements, uint32_t usage_page = IOHIDElementGetUsagePage(element); uint32_t usage = IOHIDElementGetUsage(element); if (IOHIDElementGetType(element) == kIOHIDElementTypeInput_Misc && - usage - kAxisMinimumUsageNumber >= WebGamepad::kAxesLengthCap && + usage - kAxisMinimumUsageNumber >= Gamepad::kAxesLengthCap && usage_page <= kGameControlsUsagePage) { - for (; next_index < WebGamepad::kAxesLengthCap; ++next_index) { + for (; next_index < Gamepad::kAxesLengthCap; ++next_index) { if (associated.axis_elements[next_index] == NULL) break; } - if (next_index < WebGamepad::kAxesLengthCap) { + if (next_index < Gamepad::kAxesLengthCap) { associated.axis_elements[next_index] = element; pad.axes_length = std::max(pad.axes_length, next_index + 1); } } - if (next_index >= WebGamepad::kAxesLengthCap) + if (next_index >= Gamepad::kAxesLengthCap) break; } } @@ -268,19 +265,19 @@ bool GamepadPlatformDataFetcherMac::AddButtonsAndAxes(NSArray* elements, size_t GamepadPlatformDataFetcherMac::GetEmptySlot() { // Find a free slot for this device. - for (size_t slot = 0; slot < WebGamepads::kItemsLengthCap; ++slot) { + for (size_t slot = 0; slot < Gamepads::kItemsLengthCap; ++slot) { if (associated_[slot].device_ref == nullptr) return slot; } - return WebGamepads::kItemsLengthCap; + return Gamepads::kItemsLengthCap; } size_t GamepadPlatformDataFetcherMac::GetSlotForDevice(IOHIDDeviceRef device) { - for (size_t slot = 0; slot < WebGamepads::kItemsLengthCap; ++slot) { + for (size_t slot = 0; slot < Gamepads::kItemsLengthCap; ++slot) { // If we already have this device, and it's already connected, don't do // anything now. if (associated_[slot].device_ref == device) - return WebGamepads::kItemsLengthCap; + return Gamepads::kItemsLengthCap; } return GetEmptySlot(); } @@ -300,7 +297,7 @@ void GamepadPlatformDataFetcherMac::DeviceAdd(IOHIDDeviceRef device) { size_t slot = GetSlotForDevice(device); // We can't handle this many connected devices. - if (slot == WebGamepads::kItemsLengthCap) + if (slot == Gamepads::kItemsLengthCap) return; // Clear some state that may have been left behind by previous gamepads @@ -356,11 +353,11 @@ void GamepadPlatformDataFetcherMac::DeviceRemove(IOHIDDeviceRef device) { // Find the index for this device. size_t slot; - for (slot = 0; slot < WebGamepads::kItemsLengthCap; ++slot) { + for (slot = 0; slot < Gamepads::kItemsLengthCap; ++slot) { if (associated_[slot].device_ref == device) break; } - DCHECK(slot < WebGamepads::kItemsLengthCap); + DCHECK(slot < Gamepads::kItemsLengthCap); // Leave associated device_ref so that it will be reconnected in the same // location. Simply mark it as disconnected. associated_[slot].location_id = 0; @@ -376,18 +373,18 @@ void GamepadPlatformDataFetcherMac::ValueChanged(IOHIDValueRef value) { // Find device slot. size_t slot; - for (slot = 0; slot < WebGamepads::kItemsLengthCap; ++slot) { + for (slot = 0; slot < Gamepads::kItemsLengthCap; ++slot) { if (associated_[slot].device_ref == device) break; } - if (slot == WebGamepads::kItemsLengthCap) + if (slot == Gamepads::kItemsLengthCap) return; PadState* state = GetPadState(associated_[slot].location_id); if (!state) return; - WebGamepad& pad = state->data; + Gamepad& pad = state->data; AssociatedData& associated = associated_[slot]; uint32_t value_length = IOHIDValueGetLength(value); @@ -442,7 +439,7 @@ void GamepadPlatformDataFetcherMac::GetGamepadData(bool) { return; // Loop through and GetPadState to indicate the devices are still connected. - for (size_t slot = 0; slot < WebGamepads::kItemsLengthCap; ++slot) { + for (size_t slot = 0; slot < Gamepads::kItemsLengthCap; ++slot) { if (associated_[slot].device_ref != nullptr) { GetPadState(associated_[slot].location_id); } diff --git a/chromium/device/gamepad/gamepad_platform_data_fetcher_win.cc b/chromium/device/gamepad/gamepad_platform_data_fetcher_win.cc index 045460d460f..42404e006f4 100644 --- a/chromium/device/gamepad/gamepad_platform_data_fetcher_win.cc +++ b/chromium/device/gamepad/gamepad_platform_data_fetcher_win.cc @@ -16,8 +16,6 @@ namespace device { -using namespace blink; - namespace { // See http://goo.gl/5VSJR. These are not available in all versions of the @@ -38,7 +36,7 @@ float NormalizeXInputAxis(SHORT value) { return ((value + 32768.f) / 32767.5f) - 1.f; } -const WebUChar* GamepadSubTypeName(BYTE sub_type) { +const UChar* GamepadSubTypeName(BYTE sub_type) { switch (sub_type) { case kDeviceSubTypeGamepad: return L"GAMEPAD"; @@ -65,7 +63,7 @@ const WebUChar* GamepadSubTypeName(BYTE sub_type) { } } -const WebUChar* XInputDllFileName() { +const UChar* XInputDllFileName() { // Xinput.h defines filename (XINPUT_DLL) on different Windows versions, but // Xinput.h specifies it in build time. Approach here uses the same values // and it is resolving dll filename based on Windows version it is running on. @@ -114,16 +112,16 @@ void GamepadPlatformDataFetcherWin::EnumerateDevices() { if (!state) continue; // No slot available for this gamepad. - WebGamepad& pad = state->data; + Gamepad& pad = state->data; if (state->active_state == GAMEPAD_NEWLY_ACTIVE) { // This is the first time we've seen this device, so do some one-time // initialization pad.connected = true; - swprintf(pad.id, WebGamepad::kIdLengthCap, + swprintf(pad.id, Gamepad::kIdLengthCap, L"Xbox 360 Controller (XInput STANDARD %ls)", GamepadSubTypeName(caps.SubType)); - swprintf(pad.mapping, WebGamepad::kMappingLengthCap, L"standard"); + swprintf(pad.mapping, Gamepad::kMappingLengthCap, L"standard"); } } } @@ -156,7 +154,7 @@ void GamepadPlatformDataFetcherWin::GetXInputPadData(int i) { if (!pad_state) return; - WebGamepad& pad = pad_state->data; + Gamepad& pad = pad_state->data; XINPUT_STATE state; memset(&state, 0, sizeof(XINPUT_STATE)); diff --git a/chromium/device/gamepad/gamepad_platform_data_fetcher_win.h b/chromium/device/gamepad/gamepad_platform_data_fetcher_win.h index df5b5dcd198..cedfa195dea 100644 --- a/chromium/device/gamepad/gamepad_platform_data_fetcher_win.h +++ b/chromium/device/gamepad/gamepad_platform_data_fetcher_win.h @@ -25,7 +25,7 @@ #include "base/scoped_native_library.h" #include "device/gamepad/gamepad_data_fetcher.h" #include "device/gamepad/gamepad_standard_mappings.h" -#include "third_party/WebKit/public/platform/WebGamepads.h" +#include "device/gamepad/public/cpp/gamepads.h" namespace device { diff --git a/chromium/device/gamepad/gamepad_provider.cc b/chromium/device/gamepad/gamepad_provider.cc index 44d5e5a8aa3..d56910bd458 100644 --- a/chromium/device/gamepad/gamepad_provider.cc +++ b/chromium/device/gamepad/gamepad_provider.cc @@ -13,6 +13,7 @@ #include "base/bind.h" #include "base/location.h" #include "base/logging.h" +#include "base/message_loop/message_loop.h" #include "base/single_thread_task_runner.h" #include "base/third_party/dynamic_annotations/dynamic_annotations.h" #include "base/threading/thread.h" @@ -24,9 +25,6 @@ #include "device/gamepad/gamepad_user_gesture.h" #include "mojo/public/cpp/system/platform_handle.h" -using blink::WebGamepad; -using blink::WebGamepads; - namespace device { GamepadProvider::ClosureAndThread::ClosureAndThread( @@ -85,12 +83,8 @@ GamepadProvider::~GamepadProvider() { DCHECK(data_fetchers_.empty()); } -base::SharedMemoryHandle GamepadProvider::GetSharedMemoryHandleForProcess( - base::ProcessHandle process) { - base::SharedMemoryHandle renderer_handle; - gamepad_shared_buffer_->shared_memory()->ShareToProcess(process, - &renderer_handle); - return renderer_handle; +base::SharedMemoryHandle GamepadProvider::DuplicateSharedMemoryHandle() { + return gamepad_shared_buffer_->shared_memory()->handle().Duplicate(); } mojo::ScopedSharedBufferHandle GamepadProvider::GetSharedBufferHandle() { @@ -102,8 +96,8 @@ mojo::ScopedSharedBufferHandle GamepadProvider::GetSharedBufferHandle() { true /* read_only */); } -void GamepadProvider::GetCurrentGamepadData(WebGamepads* data) { - const WebGamepads* pads = gamepad_shared_buffer_->buffer(); +void GamepadProvider::GetCurrentGamepadData(Gamepads* data) { + const Gamepads* pads = gamepad_shared_buffer_->buffer(); base::AutoLock lock(shared_memory_lock_); *data = *pads; } @@ -227,8 +221,8 @@ void GamepadProvider::DoPoll() { bool changed; - ANNOTATE_BENIGN_RACE_SIZED(gamepad_shared_buffer_->buffer(), - sizeof(WebGamepads), "Racey reads are discarded"); + ANNOTATE_BENIGN_RACE_SIZED(gamepad_shared_buffer_->buffer(), sizeof(Gamepads), + "Racey reads are discarded"); { base::AutoLock lock(devices_changed_lock_); @@ -244,12 +238,12 @@ void GamepadProvider::DoPoll() { it->GetGamepadData(changed); } - blink::WebGamepads* buffer = gamepad_shared_buffer_->buffer(); + Gamepads* buffer = gamepad_shared_buffer_->buffer(); // Send out disconnect events using the last polled data before we wipe it out // in the mapping step. if (ever_had_user_gesture_) { - for (unsigned i = 0; i < WebGamepads::kItemsLengthCap; ++i) { + for (unsigned i = 0; i < Gamepads::kItemsLengthCap; ++i) { PadState& state = pad_states_.get()[i]; if (!state.active_state && state.source != GAMEPAD_SOURCE_NONE) { @@ -267,7 +261,7 @@ void GamepadProvider::DoPoll() { // Acquire the SeqLock. There is only ever one writer to this data. // See gamepad_shared_buffer.h. gamepad_shared_buffer_->WriteBegin(); - for (unsigned i = 0; i < WebGamepads::kItemsLengthCap; ++i) { + for (unsigned i = 0; i < Gamepads::kItemsLengthCap; ++i) { PadState& state = pad_states_.get()[i]; // Must run through the map+sanitize here or CheckForUserGesture may fail. MapAndSanitizeGamepadData(&state, &buffer->items[i], sanitize_); @@ -276,7 +270,7 @@ void GamepadProvider::DoPoll() { } if (ever_had_user_gesture_) { - for (unsigned i = 0; i < WebGamepads::kItemsLengthCap; ++i) { + for (unsigned i = 0; i < Gamepads::kItemsLengthCap; ++i) { PadState& state = pad_states_.get()[i]; if (state.active_state) { @@ -312,7 +306,7 @@ void GamepadProvider::ScheduleDoPoll() { void GamepadProvider::OnGamepadConnectionChange(bool connected, int index, - const WebGamepad& pad) { + const Gamepad& pad) { if (connection_change_client_) connection_change_client_->OnGamepadConnectionChange(connected, index, pad); } @@ -322,7 +316,7 @@ void GamepadProvider::CheckForUserGesture() { if (user_gesture_observers_.empty() && ever_had_user_gesture_) return; - const WebGamepads* pads = gamepad_shared_buffer_->buffer(); + const Gamepads* pads = gamepad_shared_buffer_->buffer(); if (GamepadsHaveUserGesture(*pads)) { ever_had_user_gesture_ = true; for (size_t i = 0; i < user_gesture_observers_.size(); i++) { diff --git a/chromium/device/gamepad/gamepad_provider.h b/chromium/device/gamepad/gamepad_provider.h index bc54d94e296..063e8a4bf43 100644 --- a/chromium/device/gamepad/gamepad_provider.h +++ b/chromium/device/gamepad/gamepad_provider.h @@ -18,10 +18,9 @@ #include "device/gamepad/gamepad_export.h" #include "device/gamepad/gamepad_pad_state_provider.h" #include "device/gamepad/gamepad_shared_buffer.h" +#include "device/gamepad/public/cpp/gamepads.h" #include "mojo/public/cpp/system/buffer.h" -#include "third_party/WebKit/public/platform/WebGamepads.h" - namespace base { class SingleThreadTaskRunner; class Thread; @@ -35,7 +34,7 @@ class DEVICE_GAMEPAD_EXPORT GamepadConnectionChangeClient { public: virtual void OnGamepadConnectionChange(bool connected, int index, - const blink::WebGamepad& pad) = 0; + const Gamepad& pad) = 0; }; class DEVICE_GAMEPAD_EXPORT GamepadProvider @@ -52,10 +51,8 @@ class DEVICE_GAMEPAD_EXPORT GamepadProvider ~GamepadProvider() override; - // Returns the shared memory handle of the gamepad data duplicated into the - // given process. - base::SharedMemoryHandle GetSharedMemoryHandleForProcess( - base::ProcessHandle renderer_process); + // Returns a duplicate of the shared memory handle of the gamepad data. + base::SharedMemoryHandle DuplicateSharedMemoryHandle(); // Returns a new mojo::ScopedSharedBufferHandle of the gamepad data. mojo::ScopedSharedBufferHandle GetSharedBufferHandle(); @@ -63,7 +60,7 @@ class DEVICE_GAMEPAD_EXPORT GamepadProvider void AddGamepadDataFetcher(GamepadDataFetcher* fetcher); void RemoveGamepadDataFetcher(GamepadDataFetcher* fetcher); - void GetCurrentGamepadData(blink::WebGamepads* data); + void GetCurrentGamepadData(Gamepads* data); // Pause and resume the background polling thread. Can be called from any // thread. @@ -101,9 +98,7 @@ class DEVICE_GAMEPAD_EXPORT GamepadProvider void DoPoll(); void ScheduleDoPoll(); - void OnGamepadConnectionChange(bool connected, - int index, - const blink::WebGamepad& pad); + void OnGamepadConnectionChange(bool connected, int index, const Gamepad& pad); // Checks the gamepad state to see if the user has interacted with it. void CheckForUserGesture(); diff --git a/chromium/device/gamepad/gamepad_provider_unittest.cc b/chromium/device/gamepad/gamepad_provider_unittest.cc index 2f1633e7c65..f2e1ae05e09 100644 --- a/chromium/device/gamepad/gamepad_provider_unittest.cc +++ b/chromium/device/gamepad/gamepad_provider_unittest.cc @@ -9,6 +9,7 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/run_loop.h" +#include "base/threading/platform_thread.h" #include "build/build_config.h" #include "device/gamepad/gamepad_data_fetcher.h" #include "device/gamepad/gamepad_test_helpers.h" @@ -18,8 +19,6 @@ namespace device { namespace { -using blink::WebGamepads; - // Helper class to generate and record user gesture callbacks. class UserGestureListener { public: @@ -42,20 +41,42 @@ class UserGestureListener { // Main test fixture class GamepadProviderTest : public testing::Test, public GamepadTestHelper { public: - GamepadProvider* CreateProvider(const WebGamepads& test_data) { + GamepadProvider* CreateProvider(const Gamepads& test_data) { mock_data_fetcher_ = new MockGamepadDataFetcher(test_data); provider_.reset(new GamepadProvider( nullptr, std::unique_ptr<GamepadDataFetcher>(mock_data_fetcher_))); return provider_.get(); } + // Sleep until the shared memory buffer's seqlock advances the buffer version, + // indicating that the gamepad provider has written to it after polling the + // gamepad fetchers. The buffer will report an odd value for the version if + // the buffer is not in a consistent state, so we also require that the value + // is even before continuing. + void WaitForData(GamepadHardwareBuffer* buffer) { + const base::subtle::Atomic32 initial_version = buffer->seqlock.ReadBegin(); + base::subtle::Atomic32 current_version; + do { + base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(10)); + current_version = buffer->seqlock.ReadBegin(); + } while (current_version % 2 || current_version == initial_version); + } + + // The provider polls the data on the background thread and then issues + // the callback on the client thread. Waiting for it to poll twice ensures + // that it was able to issue callbacks for the first poll. + void WaitForDataAndCallbacksIssued(GamepadHardwareBuffer* buffer) { + WaitForData(buffer); + WaitForData(buffer); + } + void ReadGamepadHardwareBuffer(GamepadHardwareBuffer* buffer, - WebGamepads* output) { - memset(output, 0, sizeof(WebGamepads)); + Gamepads* output) { + memset(output, 0, sizeof(Gamepads)); base::subtle::Atomic32 version; do { version = buffer->seqlock.ReadBegin(); - memcpy(output, &buffer->data, sizeof(WebGamepads)); + memcpy(output, &buffer->data, sizeof(Gamepads)); } while (buffer->seqlock.ReadRetry(version)); } @@ -70,10 +91,9 @@ class GamepadProviderTest : public testing::Test, public GamepadTestHelper { DISALLOW_COPY_AND_ASSIGN(GamepadProviderTest); }; -// Test is flaky. crbug.com/705367 -TEST_F(GamepadProviderTest, DISABLED_PollingAccess) { - WebGamepads test_data; - memset(&test_data, 0, sizeof(WebGamepads)); +TEST_F(GamepadProviderTest, PollingAccess) { + Gamepads test_data; + memset(&test_data, 0, sizeof(Gamepads)); test_data.items[0].connected = true; test_data.items[0].timestamp = 0; test_data.items[0].buttons_length = 1; @@ -89,18 +109,19 @@ TEST_F(GamepadProviderTest, DISABLED_PollingAccess) { base::RunLoop().RunUntilIdle(); - mock_data_fetcher_->WaitForDataRead(); - // Renderer-side, pull data out of poll buffer. - base::SharedMemoryHandle handle = provider->GetSharedMemoryHandleForProcess( - base::GetCurrentProcessHandle()); + base::SharedMemoryHandle handle = provider->DuplicateSharedMemoryHandle(); std::unique_ptr<base::SharedMemory> shared_memory( new base::SharedMemory(handle, true)); EXPECT_TRUE(shared_memory->Map(sizeof(GamepadHardwareBuffer))); GamepadHardwareBuffer* buffer = static_cast<GamepadHardwareBuffer*>(shared_memory->memory()); - WebGamepads output; + + // Wait until the shared memory buffer has been written at least once. + WaitForData(buffer); + + Gamepads output; ReadGamepadHardwareBuffer(buffer, &output); EXPECT_EQ(1u, output.items[0].buttons_length); @@ -111,9 +132,8 @@ TEST_F(GamepadProviderTest, DISABLED_PollingAccess) { EXPECT_EQ(0.5f, output.items[0].axes[1]); } -// Flaky on all platforms: http://crbug.com/692219 -TEST_F(GamepadProviderTest, DISABLED_ConnectDisconnectMultiple) { - WebGamepads test_data; +TEST_F(GamepadProviderTest, ConnectDisconnectMultiple) { + Gamepads test_data; test_data.items[0].connected = true; test_data.items[0].timestamp = 0; test_data.items[0].axes_length = 2; @@ -126,7 +146,7 @@ TEST_F(GamepadProviderTest, DISABLED_ConnectDisconnectMultiple) { test_data.items[1].axes[0] = 1.f; test_data.items[1].axes[1] = -.5f; - WebGamepads test_data_onedisconnected; + Gamepads test_data_onedisconnected; test_data_onedisconnected.items[1].connected = true; test_data_onedisconnected.items[1].timestamp = 0; test_data_onedisconnected.items[1].axes_length = 2; @@ -139,18 +159,19 @@ TEST_F(GamepadProviderTest, DISABLED_ConnectDisconnectMultiple) { base::RunLoop().RunUntilIdle(); - mock_data_fetcher_->WaitForDataRead(); - // Renderer-side, pull data out of poll buffer. - base::SharedMemoryHandle handle = provider->GetSharedMemoryHandleForProcess( - base::GetCurrentProcessHandle()); + base::SharedMemoryHandle handle = provider->DuplicateSharedMemoryHandle(); std::unique_ptr<base::SharedMemory> shared_memory( new base::SharedMemory(handle, true)); EXPECT_TRUE(shared_memory->Map(sizeof(GamepadHardwareBuffer))); GamepadHardwareBuffer* buffer = static_cast<GamepadHardwareBuffer*>(shared_memory->memory()); - WebGamepads output; + + // Wait until the shared memory buffer has been written at least once. + WaitForData(buffer); + + Gamepads output; ReadGamepadHardwareBuffer(buffer, &output); EXPECT_EQ(2u, output.items[0].axes_length); @@ -161,7 +182,9 @@ TEST_F(GamepadProviderTest, DISABLED_ConnectDisconnectMultiple) { EXPECT_EQ(-0.5f, output.items[1].axes[1]); mock_data_fetcher_->SetTestData(test_data_onedisconnected); - mock_data_fetcher_->WaitForDataReadAndCallbacksIssued(); + + WaitForDataAndCallbacksIssued(buffer); + ReadGamepadHardwareBuffer(buffer, &output); EXPECT_EQ(0u, output.items[0].axes_length); @@ -172,7 +195,7 @@ TEST_F(GamepadProviderTest, DISABLED_ConnectDisconnectMultiple) { // Tests that waiting for a user gesture works properly. TEST_F(GamepadProviderTest, UserGesture) { - WebGamepads no_button_data; + Gamepads no_button_data; no_button_data.items[0].connected = true; no_button_data.items[0].timestamp = 0; no_button_data.items[0].buttons_length = 1; @@ -182,7 +205,7 @@ TEST_F(GamepadProviderTest, UserGesture) { no_button_data.items[0].axes[0] = 0.f; no_button_data.items[0].axes[1] = .4f; - WebGamepads button_down_data = no_button_data; + Gamepads button_down_data = no_button_data; button_down_data.items[0].buttons[0].value = 1.f; button_down_data.items[0].buttons[0].pressed = true; @@ -192,30 +215,39 @@ TEST_F(GamepadProviderTest, UserGesture) { provider->Resume(); provider->RegisterForUserGesture(listener.GetClosure()); - mock_data_fetcher_->WaitForDataReadAndCallbacksIssued(); - // It should not have issued our callback. base::RunLoop().RunUntilIdle(); + + // Renderer-side, pull data out of poll buffer. + base::SharedMemoryHandle handle = provider->DuplicateSharedMemoryHandle(); + std::unique_ptr<base::SharedMemory> shared_memory( + new base::SharedMemory(handle, true)); + EXPECT_TRUE(shared_memory->Map(sizeof(GamepadHardwareBuffer))); + + GamepadHardwareBuffer* buffer = + static_cast<GamepadHardwareBuffer*>(shared_memory->memory()); + + // Wait until the shared memory buffer has been written at least once. + WaitForData(buffer); + + // It should not have issued our callback. EXPECT_FALSE(listener.has_user_gesture()); - // Set a button down and wait for it to be read twice. + // Set a button down. mock_data_fetcher_->SetTestData(button_down_data); - mock_data_fetcher_->WaitForDataReadAndCallbacksIssued(); + + // The user gesture listener callback is not called until after the buffer has + // been updated. Wait for the second update to ensure callbacks have fired. + WaitForDataAndCallbacksIssued(buffer); // It should have issued our callback. base::RunLoop().RunUntilIdle(); EXPECT_TRUE(listener.has_user_gesture()); } -// Flaky on CrOS and Linux: http://crbug.com/640086, https://crbug.com/702712 -#if defined(OS_LINUX) || defined(OS_CHROMEOS) -#define MAYBE_Sanitization DISABLED_Sanitization -#else -#define MAYBE_Sanitization Sanitization -#endif // Tests that waiting for a user gesture works properly. -TEST_F(GamepadProviderTest, MAYBE_Sanitization) { - WebGamepads active_data; +TEST_F(GamepadProviderTest, Sanitization) { + Gamepads active_data; active_data.items[0].connected = true; active_data.items[0].timestamp = 0; active_data.items[0].buttons_length = 1; @@ -224,7 +256,7 @@ TEST_F(GamepadProviderTest, MAYBE_Sanitization) { active_data.items[0].buttons[0].pressed = true; active_data.items[0].axes[0] = -1.f; - WebGamepads zero_data; + Gamepads zero_data; zero_data.items[0].connected = true; zero_data.items[0].timestamp = 0; zero_data.items[0].buttons_length = 1; @@ -240,18 +272,19 @@ TEST_F(GamepadProviderTest, MAYBE_Sanitization) { base::RunLoop().RunUntilIdle(); - mock_data_fetcher_->WaitForDataRead(); - // Renderer-side, pull data out of poll buffer. - base::SharedMemoryHandle handle = provider->GetSharedMemoryHandleForProcess( - base::GetCurrentProcessHandle()); + base::SharedMemoryHandle handle = provider->DuplicateSharedMemoryHandle(); std::unique_ptr<base::SharedMemory> shared_memory( new base::SharedMemory(handle, true)); EXPECT_TRUE(shared_memory->Map(sizeof(GamepadHardwareBuffer))); GamepadHardwareBuffer* buffer = static_cast<GamepadHardwareBuffer*>(shared_memory->memory()); - WebGamepads output; + + // Wait until the shared memory buffer has been written at least once. + WaitForData(buffer); + + Gamepads output; ReadGamepadHardwareBuffer(buffer, &output); // Initial data should all be zeroed out due to sanitization, even though the @@ -264,7 +297,8 @@ TEST_F(GamepadProviderTest, MAYBE_Sanitization) { // Zero out the inputs mock_data_fetcher_->SetTestData(zero_data); - mock_data_fetcher_->WaitForDataReadAndCallbacksIssued(); + + WaitForDataAndCallbacksIssued(buffer); // Read updated data from shared memory ReadGamepadHardwareBuffer(buffer, &output); @@ -278,7 +312,8 @@ TEST_F(GamepadProviderTest, MAYBE_Sanitization) { // Re-set the active inputs mock_data_fetcher_->SetTestData(active_data); - mock_data_fetcher_->WaitForDataReadAndCallbacksIssued(); + + WaitForDataAndCallbacksIssued(buffer); // Read updated data from shared memory ReadGamepadHardwareBuffer(buffer, &output); diff --git a/chromium/device/gamepad/gamepad_service.cc b/chromium/device/gamepad/gamepad_service.cc index 2fd5354dc24..3a86e40623f 100644 --- a/chromium/device/gamepad/gamepad_service.cc +++ b/chromium/device/gamepad/gamepad_service.cc @@ -108,7 +108,7 @@ void GamepadService::Terminate() { void GamepadService::OnGamepadConnectionChange(bool connected, int index, - const blink::WebGamepad& pad) { + const Gamepad& pad) { if (connected) { main_thread_task_runner_->PostTask( FROM_HERE, base::Bind(&GamepadService::OnGamepadConnected, @@ -120,8 +120,7 @@ void GamepadService::OnGamepadConnectionChange(bool connected, } } -void GamepadService::OnGamepadConnected(int index, - const blink::WebGamepad& pad) { +void GamepadService::OnGamepadConnected(int index, const Gamepad& pad) { DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); for (ConsumerSet::iterator it = consumers_.begin(); it != consumers_.end(); @@ -131,8 +130,7 @@ void GamepadService::OnGamepadConnected(int index, } } -void GamepadService::OnGamepadDisconnected(int index, - const blink::WebGamepad& pad) { +void GamepadService::OnGamepadDisconnected(int index, const Gamepad& pad) { DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); for (ConsumerSet::iterator it = consumers_.begin(); it != consumers_.end(); @@ -142,10 +140,9 @@ void GamepadService::OnGamepadDisconnected(int index, } } -base::SharedMemoryHandle GamepadService::GetSharedMemoryHandleForProcess( - base::ProcessHandle handle) { +base::SharedMemoryHandle GamepadService::DuplicateSharedMemoryHandle() { DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); - return provider_->GetSharedMemoryHandleForProcess(handle); + return provider_->DuplicateSharedMemoryHandle(); } mojo::ScopedSharedBufferHandle GamepadService::GetSharedBufferHandle() { @@ -166,10 +163,10 @@ void GamepadService::OnUserGesture() { if (!it->did_observe_user_gesture && it->is_active) { const ConsumerInfo& info = *it; info.did_observe_user_gesture = true; - blink::WebGamepads gamepads; + Gamepads gamepads; provider_->GetCurrentGamepadData(&gamepads); - for (unsigned i = 0; i < blink::WebGamepads::kItemsLengthCap; ++i) { - const blink::WebGamepad& pad = gamepads.items[i]; + for (unsigned i = 0; i < Gamepads::kItemsLengthCap; ++i) { + const Gamepad& pad = gamepads.items[i]; if (pad.connected) info.consumer->OnGamepadConnected(i, pad); } diff --git a/chromium/device/gamepad/gamepad_service.h b/chromium/device/gamepad/gamepad_service.h index e9ffbe86c5d..53017841492 100644 --- a/chromium/device/gamepad/gamepad_service.h +++ b/chromium/device/gamepad/gamepad_service.h @@ -19,10 +19,6 @@ namespace { class SingleThreadTaskRunner; } -namespace blink { -class WebGamepad; -} - namespace content { class GamepadServiceTestConstructor; } @@ -71,10 +67,8 @@ class DEVICE_GAMEPAD_EXPORT GamepadService // while a consumer is active. void RegisterForUserGesture(const base::Closure& closure); - // Returns the shared memory handle of the gamepad data duplicated into the - // given process. - base::SharedMemoryHandle GetSharedMemoryHandleForProcess( - base::ProcessHandle handle); + // Returns a duplicate of the shared memory handle of the gamepad data. + base::SharedMemoryHandle DuplicateSharedMemoryHandle(); // Returns a new mojo::ScopedSharedBuffer handle of the gamepad data. mojo::ScopedSharedBufferHandle GetSharedBufferHandle(); @@ -83,10 +77,10 @@ class DEVICE_GAMEPAD_EXPORT GamepadService void Terminate(); // Called on IO thread when a gamepad is connected. - void OnGamepadConnected(int index, const blink::WebGamepad& pad); + void OnGamepadConnected(int index, const Gamepad& pad); // Called on IO thread when a gamepad is disconnected. - void OnGamepadDisconnected(int index, const blink::WebGamepad& pad); + void OnGamepadDisconnected(int index, const Gamepad& pad); private: friend struct base::DefaultSingletonTraits<GamepadService>; @@ -107,7 +101,7 @@ class DEVICE_GAMEPAD_EXPORT GamepadService void OnGamepadConnectionChange(bool connected, int index, - const blink::WebGamepad& pad) override; + const Gamepad& pad) override; void SetSanitizationEnabled(bool sanitize); diff --git a/chromium/device/gamepad/gamepad_service_unittest.cc b/chromium/device/gamepad/gamepad_service_unittest.cc index 97ce78139c5..86aad624cd5 100644 --- a/chromium/device/gamepad/gamepad_service_unittest.cc +++ b/chromium/device/gamepad/gamepad_service_unittest.cc @@ -18,21 +18,17 @@ namespace device { namespace { -static const int kNumberOfGamepads = blink::WebGamepads::kItemsLengthCap; +static const int kNumberOfGamepads = Gamepads::kItemsLengthCap; } -using blink::WebGamepads; - class ConnectionListener : public device::GamepadConsumer { public: ConnectionListener() { ClearCounters(); } - void OnGamepadConnected(unsigned index, - const blink::WebGamepad& gamepad) override { + void OnGamepadConnected(unsigned index, const Gamepad& gamepad) override { connected_counter_++; } - void OnGamepadDisconnected(unsigned index, - const blink::WebGamepad& gamepad) override { + void OnGamepadDisconnected(unsigned index, const Gamepad& gamepad) override { disconnected_counter_++; } @@ -71,7 +67,7 @@ class GamepadServiceTest : public testing::Test { device::MockGamepadDataFetcher* fetcher_; GamepadService* service_; std::unique_ptr<ConnectionListener> connection_listener_; - WebGamepads test_data_; + Gamepads test_data_; DISALLOW_COPY_AND_ASSIGN(GamepadServiceTest); }; diff --git a/chromium/device/gamepad/gamepad_shared_buffer.cc b/chromium/device/gamepad/gamepad_shared_buffer.cc index 66ada779f1e..a8c2216110c 100644 --- a/chromium/device/gamepad/gamepad_shared_buffer.cc +++ b/chromium/device/gamepad/gamepad_shared_buffer.cc @@ -14,7 +14,7 @@ GamepadSharedBuffer::GamepadSharedBuffer() { void* mem = shared_memory_.memory(); DCHECK(mem); hardware_buffer_ = new (mem) GamepadHardwareBuffer(); - memset(&(hardware_buffer_->data), 0, sizeof(blink::WebGamepads)); + memset(&(hardware_buffer_->data), 0, sizeof(Gamepads)); } GamepadSharedBuffer::~GamepadSharedBuffer() {} @@ -23,7 +23,7 @@ base::SharedMemory* GamepadSharedBuffer::shared_memory() { return &shared_memory_; } -blink::WebGamepads* GamepadSharedBuffer::buffer() { +Gamepads* GamepadSharedBuffer::buffer() { return &(hardware_buffer()->data); } diff --git a/chromium/device/gamepad/gamepad_shared_buffer.h b/chromium/device/gamepad/gamepad_shared_buffer.h index b98e9616b92..1eb7b933795 100644 --- a/chromium/device/gamepad/gamepad_shared_buffer.h +++ b/chromium/device/gamepad/gamepad_shared_buffer.h @@ -8,7 +8,7 @@ #include "base/memory/shared_memory.h" #include "device/base/synchronization/shared_memory_seqlock_buffer.h" #include "device/gamepad/gamepad_export.h" -#include "third_party/WebKit/public/platform/WebGamepads.h" +#include "device/gamepad/public/cpp/gamepads.h" namespace device { @@ -25,7 +25,7 @@ namespace device { */ -typedef SharedMemorySeqLockBuffer<blink::WebGamepads> GamepadHardwareBuffer; +typedef SharedMemorySeqLockBuffer<Gamepads> GamepadHardwareBuffer; class DEVICE_GAMEPAD_EXPORT GamepadSharedBuffer { public: @@ -33,7 +33,7 @@ class DEVICE_GAMEPAD_EXPORT GamepadSharedBuffer { ~GamepadSharedBuffer(); base::SharedMemory* shared_memory(); - blink::WebGamepads* buffer(); + Gamepads* buffer(); GamepadHardwareBuffer* hardware_buffer(); void WriteBegin(); diff --git a/chromium/device/gamepad/gamepad_standard_mappings.cc b/chromium/device/gamepad/gamepad_standard_mappings.cc index e4aaf696716..d467574d886 100644 --- a/chromium/device/gamepad/gamepad_standard_mappings.cc +++ b/chromium/device/gamepad/gamepad_standard_mappings.cc @@ -6,38 +6,37 @@ namespace device { -blink::WebGamepadButton AxisToButton(float input) { +GamepadButton AxisToButton(float input) { float value = (input + 1.f) / 2.f; bool pressed = value > kDefaultButtonPressedThreshold; bool touched = value > 0.0f; - return blink::WebGamepadButton(pressed, touched, value); + return GamepadButton(pressed, touched, value); } -blink::WebGamepadButton AxisNegativeAsButton(float input) { +GamepadButton AxisNegativeAsButton(float input) { float value = (input < -0.5f) ? 1.f : 0.f; bool pressed = value > kDefaultButtonPressedThreshold; bool touched = value > 0.0f; - return blink::WebGamepadButton(pressed, touched, value); + return GamepadButton(pressed, touched, value); } -blink::WebGamepadButton AxisPositiveAsButton(float input) { +GamepadButton AxisPositiveAsButton(float input) { float value = (input > 0.5f) ? 1.f : 0.f; bool pressed = value > kDefaultButtonPressedThreshold; bool touched = value > 0.0f; - return blink::WebGamepadButton(pressed, touched, value); + return GamepadButton(pressed, touched, value); } -blink::WebGamepadButton ButtonFromButtonAndAxis(blink::WebGamepadButton button, - float axis) { +GamepadButton ButtonFromButtonAndAxis(GamepadButton button, float axis) { float value = (axis + 1.f) / 2.f; - return blink::WebGamepadButton(button.pressed, button.touched, value); + return GamepadButton(button.pressed, button.touched, value); } -blink::WebGamepadButton NullButton() { - return blink::WebGamepadButton(false, false, 0.0); +GamepadButton NullButton() { + return GamepadButton(false, false, 0.0); } -void DpadFromAxis(blink::WebGamepad* mapped, float dir) { +void DpadFromAxis(Gamepad* mapped, float dir) { bool up = false; bool right = false; bool down = false; diff --git a/chromium/device/gamepad/gamepad_standard_mappings.h b/chromium/device/gamepad/gamepad_standard_mappings.h index b924533cdaa..bb31cff25d5 100644 --- a/chromium/device/gamepad/gamepad_standard_mappings.h +++ b/chromium/device/gamepad/gamepad_standard_mappings.h @@ -6,13 +6,12 @@ #define DEVICE_GAMEPAD_GAMEPAD_STANDARD_MAPPINGS_H_ #include "base/strings/string_piece.h" -#include "third_party/WebKit/public/platform/WebGamepad.h" +#include "device/gamepad/public/cpp/gamepad.h" namespace device { -typedef void (*GamepadStandardMappingFunction)( - const blink::WebGamepad& original, - blink::WebGamepad* mapped); +typedef void (*GamepadStandardMappingFunction)(const Gamepad& original, + Gamepad* mapped); GamepadStandardMappingFunction GetGamepadStandardMappingFunction( const base::StringPiece& vendor_id, @@ -63,13 +62,12 @@ enum CanonicalAxisIndex { const float kDefaultButtonPressedThreshold = 30.f / 255.f; // Common mapping functions -blink::WebGamepadButton AxisToButton(float input); -blink::WebGamepadButton AxisNegativeAsButton(float input); -blink::WebGamepadButton AxisPositiveAsButton(float input); -blink::WebGamepadButton ButtonFromButtonAndAxis(blink::WebGamepadButton button, - float axis); -blink::WebGamepadButton NullButton(); -void DpadFromAxis(blink::WebGamepad* mapped, float dir); +GamepadButton AxisToButton(float input); +GamepadButton AxisNegativeAsButton(float input); +GamepadButton AxisPositiveAsButton(float input); +GamepadButton ButtonFromButtonAndAxis(GamepadButton button, float axis); +GamepadButton NullButton(); +void DpadFromAxis(Gamepad* mapped, float dir); } // namespace device diff --git a/chromium/device/gamepad/gamepad_standard_mappings_linux.cc b/chromium/device/gamepad/gamepad_standard_mappings_linux.cc index 9de99435325..17b8afc2430 100644 --- a/chromium/device/gamepad/gamepad_standard_mappings_linux.cc +++ b/chromium/device/gamepad/gamepad_standard_mappings_linux.cc @@ -11,8 +11,7 @@ namespace device { namespace { -void MapperXInputStyleGamepad(const blink::WebGamepad& input, - blink::WebGamepad* mapped) { +void MapperXInputStyleGamepad(const Gamepad& input, Gamepad* mapped) { *mapped = input; mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = AxisToButton(input.axes[2]); mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = AxisToButton(input.axes[5]); @@ -32,8 +31,7 @@ void MapperXInputStyleGamepad(const blink::WebGamepad& input, mapped->axes_length = AXIS_INDEX_COUNT; } -void MapperXboxOneHidGamepad(const blink::WebGamepad& input, - blink::WebGamepad* mapped) { +void MapperXboxOneHidGamepad(const Gamepad& input, Gamepad* mapped) { *mapped = input; mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[0]; @@ -59,8 +57,7 @@ void MapperXboxOneHidGamepad(const blink::WebGamepad& input, mapped->axes_length = AXIS_INDEX_COUNT; } -void MapperLakeviewResearch(const blink::WebGamepad& input, - blink::WebGamepad* mapped) { +void MapperLakeviewResearch(const Gamepad& input, Gamepad* mapped) { *mapped = input; mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[2]; mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[3]; @@ -80,8 +77,7 @@ void MapperLakeviewResearch(const blink::WebGamepad& input, mapped->axes_length = AXIS_INDEX_COUNT; } -void MapperPlaystationSixAxis(const blink::WebGamepad& input, - blink::WebGamepad* mapped) { +void MapperPlaystationSixAxis(const Gamepad& input, Gamepad* mapped) { *mapped = input; mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[14]; mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[13]; @@ -105,8 +101,7 @@ void MapperPlaystationSixAxis(const blink::WebGamepad& input, mapped->axes_length = AXIS_INDEX_COUNT; } -void MapperDualshock4(const blink::WebGamepad& input, - blink::WebGamepad* mapped) { +void MapperDualshock4(const Gamepad& input, Gamepad* mapped) { enum Dualshock4Buttons { DUALSHOCK_BUTTON_TOUCHPAD = BUTTON_INDEX_COUNT, DUALSHOCK_BUTTON_COUNT @@ -138,7 +133,7 @@ void MapperDualshock4(const blink::WebGamepad& input, mapped->axes_length = AXIS_INDEX_COUNT; } -void MapperIBuffalo(const blink::WebGamepad& input, blink::WebGamepad* mapped) { +void MapperIBuffalo(const Gamepad& input, Gamepad* mapped) { *mapped = input; mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[1]; mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[0]; @@ -157,7 +152,7 @@ void MapperIBuffalo(const blink::WebGamepad& input, blink::WebGamepad* mapped) { mapped->axes_length = 2; } -void MapperXGEAR(const blink::WebGamepad& input, blink::WebGamepad* mapped) { +void MapperXGEAR(const Gamepad& input, Gamepad* mapped) { *mapped = input; mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[2]; mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[1]; @@ -178,8 +173,7 @@ void MapperXGEAR(const blink::WebGamepad& input, blink::WebGamepad* mapped) { mapped->axes_length = AXIS_INDEX_COUNT; } -void MapperDragonRiseGeneric(const blink::WebGamepad& input, - blink::WebGamepad* mapped) { +void MapperDragonRiseGeneric(const Gamepad& input, Gamepad* mapped) { *mapped = input; mapped->buttons[BUTTON_INDEX_DPAD_UP] = AxisNegativeAsButton(input.axes[6]); mapped->buttons[BUTTON_INDEX_DPAD_DOWN] = AxisPositiveAsButton(input.axes[6]); @@ -194,8 +188,7 @@ void MapperDragonRiseGeneric(const blink::WebGamepad& input, mapped->axes_length = AXIS_INDEX_COUNT; } -void MapperOnLiveWireless(const blink::WebGamepad& input, - blink::WebGamepad* mapped) { +void MapperOnLiveWireless(const Gamepad& input, Gamepad* mapped) { *mapped = input; mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = AxisToButton(input.axes[2]); mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = AxisToButton(input.axes[5]); @@ -216,7 +209,7 @@ void MapperOnLiveWireless(const blink::WebGamepad& input, mapped->axes_length = AXIS_INDEX_COUNT; } -void MapperADT1(const blink::WebGamepad& input, blink::WebGamepad* mapped) { +void MapperADT1(const Gamepad& input, Gamepad* mapped) { *mapped = input; mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = AxisToButton(input.axes[5]); mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = AxisToButton(input.axes[4]); @@ -235,7 +228,7 @@ void MapperADT1(const blink::WebGamepad& input, blink::WebGamepad* mapped) { mapped->axes_length = AXIS_INDEX_COUNT; } -void MapperNvShield(const blink::WebGamepad& input, blink::WebGamepad* mapped) { +void MapperNvShield(const Gamepad& input, Gamepad* mapped) { *mapped = input; mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = AxisToButton(input.axes[5]); mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = AxisToButton(input.axes[4]); @@ -254,7 +247,7 @@ void MapperNvShield(const blink::WebGamepad& input, blink::WebGamepad* mapped) { mapped->axes_length = AXIS_INDEX_COUNT; } -void MapperOUYA(const blink::WebGamepad& input, blink::WebGamepad* mapped) { +void MapperOUYA(const Gamepad& input, Gamepad* mapped) { *mapped = input; mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[0]; mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[3]; @@ -280,8 +273,7 @@ void MapperOUYA(const blink::WebGamepad& input, blink::WebGamepad* mapped) { mapped->axes_length = AXIS_INDEX_COUNT; } -void MapperRazerServal(const blink::WebGamepad& input, - blink::WebGamepad* mapped) { +void MapperRazerServal(const Gamepad& input, Gamepad* mapped) { *mapped = input; mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = AxisToButton(input.axes[5]); mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = AxisToButton(input.axes[4]); @@ -299,7 +291,7 @@ void MapperRazerServal(const blink::WebGamepad& input, mapped->axes_length = AXIS_INDEX_COUNT; } -void MapperMogaPro(const blink::WebGamepad& input, blink::WebGamepad* mapped) { +void MapperMogaPro(const Gamepad& input, Gamepad* mapped) { *mapped = input; mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = AxisToButton(input.axes[5]); mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = AxisToButton(input.axes[4]); @@ -317,8 +309,7 @@ void MapperMogaPro(const blink::WebGamepad& input, blink::WebGamepad* mapped) { mapped->axes_length = AXIS_INDEX_COUNT; } -void MapperSamsung_EI_GP20(const blink::WebGamepad& input, - blink::WebGamepad* mapped) { +void MapperSamsung_EI_GP20(const Gamepad& input, Gamepad* mapped) { *mapped = input; mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[0]; mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[1]; diff --git a/chromium/device/gamepad/gamepad_standard_mappings_mac.mm b/chromium/device/gamepad/gamepad_standard_mappings_mac.mm index 5fb8f090307..27e12ce6898 100644 --- a/chromium/device/gamepad/gamepad_standard_mappings_mac.mm +++ b/chromium/device/gamepad/gamepad_standard_mappings_mac.mm @@ -11,8 +11,7 @@ namespace device { namespace { -void MapperXbox360Gamepad(const blink::WebGamepad& input, - blink::WebGamepad* mapped) { +void MapperXbox360Gamepad(const Gamepad& input, Gamepad* mapped) { *mapped = input; mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = AxisToButton(input.axes[2]); mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = AxisToButton(input.axes[5]); @@ -31,8 +30,7 @@ void MapperXbox360Gamepad(const blink::WebGamepad& input, mapped->axes_length = AXIS_INDEX_COUNT; } -void MapperXboxOneHidGamepad(const blink::WebGamepad& input, - blink::WebGamepad* mapped) { +void MapperXboxOneHidGamepad(const Gamepad& input, Gamepad* mapped) { *mapped = input; mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[0]; @@ -54,8 +52,7 @@ void MapperXboxOneHidGamepad(const blink::WebGamepad& input, mapped->axes_length = AXIS_INDEX_COUNT; } -void MapperPlaystationSixAxis(const blink::WebGamepad& input, - blink::WebGamepad* mapped) { +void MapperPlaystationSixAxis(const Gamepad& input, Gamepad* mapped) { *mapped = input; mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[14]; mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[13]; @@ -91,8 +88,7 @@ void MapperPlaystationSixAxis(const blink::WebGamepad& input, mapped->axes_length = AXIS_INDEX_COUNT; } -void MapperDualshock4(const blink::WebGamepad& input, - blink::WebGamepad* mapped) { +void MapperDualshock4(const Gamepad& input, Gamepad* mapped) { enum Dualshock4Buttons { DUALSHOCK_BUTTON_TOUCHPAD = BUTTON_INDEX_COUNT, DUALSHOCK_BUTTON_COUNT @@ -120,7 +116,7 @@ void MapperDualshock4(const blink::WebGamepad& input, mapped->axes_length = AXIS_INDEX_COUNT; } -void MapperIBuffalo(const blink::WebGamepad& input, blink::WebGamepad* mapped) { +void MapperIBuffalo(const Gamepad& input, Gamepad* mapped) { *mapped = input; mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[1]; mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[0]; @@ -139,8 +135,7 @@ void MapperIBuffalo(const blink::WebGamepad& input, blink::WebGamepad* mapped) { mapped->axes_length = 2; } -void MapperDirectInputStyle(const blink::WebGamepad& input, - blink::WebGamepad* mapped) { +void MapperDirectInputStyle(const Gamepad& input, Gamepad* mapped) { *mapped = input; mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[1]; mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[2]; @@ -151,8 +146,7 @@ void MapperDirectInputStyle(const blink::WebGamepad& input, mapped->axes_length = AXIS_INDEX_COUNT; } -void MapperMacallyIShock(const blink::WebGamepad& input, - blink::WebGamepad* mapped) { +void MapperMacallyIShock(const Gamepad& input, Gamepad* mapped) { enum IShockButtons { ISHOCK_BUTTON_C = BUTTON_INDEX_COUNT, ISHOCK_BUTTON_D, @@ -190,7 +184,7 @@ void MapperMacallyIShock(const blink::WebGamepad& input, mapped->axes_length = AXIS_INDEX_COUNT; } -void MapperXGEAR(const blink::WebGamepad& input, blink::WebGamepad* mapped) { +void MapperXGEAR(const Gamepad& input, Gamepad* mapped) { *mapped = input; mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[2]; mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[3]; @@ -206,8 +200,7 @@ void MapperXGEAR(const blink::WebGamepad& input, blink::WebGamepad* mapped) { mapped->axes_length = AXIS_INDEX_COUNT; } -void MapperSmartJoyPLUS(const blink::WebGamepad& input, - blink::WebGamepad* mapped) { +void MapperSmartJoyPLUS(const Gamepad& input, Gamepad* mapped) { *mapped = input; mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[2]; mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[3]; @@ -224,8 +217,7 @@ void MapperSmartJoyPLUS(const blink::WebGamepad& input, mapped->axes_length = AXIS_INDEX_COUNT; } -void MapperDragonRiseGeneric(const blink::WebGamepad& input, - blink::WebGamepad* mapped) { +void MapperDragonRiseGeneric(const Gamepad& input, Gamepad* mapped) { *mapped = input; DpadFromAxis(mapped, input.axes[9]); mapped->axes[AXIS_INDEX_LEFT_STICK_X] = input.axes[0]; @@ -236,8 +228,7 @@ void MapperDragonRiseGeneric(const blink::WebGamepad& input, mapped->axes_length = AXIS_INDEX_COUNT; } -void MapperOnLiveWireless(const blink::WebGamepad& input, - blink::WebGamepad* mapped) { +void MapperOnLiveWireless(const Gamepad& input, Gamepad* mapped) { *mapped = input; mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[0]; mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[1]; @@ -260,7 +251,7 @@ void MapperOnLiveWireless(const blink::WebGamepad& input, mapped->axes_length = AXIS_INDEX_COUNT; } -void MapperADT1(const blink::WebGamepad& input, blink::WebGamepad* mapped) { +void MapperADT1(const Gamepad& input, Gamepad* mapped) { *mapped = input; mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[0]; mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[1]; @@ -282,7 +273,7 @@ void MapperADT1(const blink::WebGamepad& input, blink::WebGamepad* mapped) { mapped->axes_length = AXIS_INDEX_COUNT; } -void MapperNvShield(const blink::WebGamepad& input, blink::WebGamepad* mapped) { +void MapperNvShield(const Gamepad& input, Gamepad* mapped) { *mapped = input; mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[0]; mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[1]; @@ -304,7 +295,7 @@ void MapperNvShield(const blink::WebGamepad& input, blink::WebGamepad* mapped) { mapped->axes_length = AXIS_INDEX_COUNT; } -void MapperOUYA(const blink::WebGamepad& input, blink::WebGamepad* mapped) { +void MapperOUYA(const Gamepad& input, Gamepad* mapped) { *mapped = input; mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[0]; mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[3]; @@ -330,8 +321,7 @@ void MapperOUYA(const blink::WebGamepad& input, blink::WebGamepad* mapped) { mapped->axes_length = AXIS_INDEX_COUNT; } -void MapperRazerServal(const blink::WebGamepad& input, - blink::WebGamepad* mapped) { +void MapperRazerServal(const Gamepad& input, Gamepad* mapped) { *mapped = input; mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[0]; mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[1]; @@ -352,7 +342,7 @@ void MapperRazerServal(const blink::WebGamepad& input, mapped->axes_length = AXIS_INDEX_COUNT; } -void MapperMogaPro(const blink::WebGamepad& input, blink::WebGamepad* mapped) { +void MapperMogaPro(const Gamepad& input, Gamepad* mapped) { *mapped = input; mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[0]; mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[1]; diff --git a/chromium/device/gamepad/gamepad_standard_mappings_win.cc b/chromium/device/gamepad/gamepad_standard_mappings_win.cc index 1a11227237c..b73f1194eca 100644 --- a/chromium/device/gamepad/gamepad_standard_mappings_win.cc +++ b/chromium/device/gamepad/gamepad_standard_mappings_win.cc @@ -11,8 +11,7 @@ namespace device { namespace { -void MapperLogitechDualAction(const blink::WebGamepad& input, - blink::WebGamepad* mapped) { +void MapperLogitechDualAction(const Gamepad& input, Gamepad* mapped) { *mapped = input; mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[1]; mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[2]; @@ -24,8 +23,7 @@ void MapperLogitechDualAction(const blink::WebGamepad& input, mapped->axes_length = AXIS_INDEX_COUNT; } -void Mapper2Axes8Keys(const blink::WebGamepad& input, - blink::WebGamepad* mapped) { +void Mapper2Axes8Keys(const Gamepad& input, Gamepad* mapped) { *mapped = input; mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[2]; mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[1]; @@ -38,18 +36,17 @@ void Mapper2Axes8Keys(const blink::WebGamepad& input, AxisPositiveAsButton(input.axes[0]); // Missing buttons - mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = blink::WebGamepadButton(); - mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = blink::WebGamepadButton(); - mapped->buttons[BUTTON_INDEX_LEFT_THUMBSTICK] = blink::WebGamepadButton(); - mapped->buttons[BUTTON_INDEX_RIGHT_THUMBSTICK] = blink::WebGamepadButton(); - mapped->buttons[BUTTON_INDEX_META] = blink::WebGamepadButton(); + mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = GamepadButton(); + mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = GamepadButton(); + mapped->buttons[BUTTON_INDEX_LEFT_THUMBSTICK] = GamepadButton(); + mapped->buttons[BUTTON_INDEX_RIGHT_THUMBSTICK] = GamepadButton(); + mapped->buttons[BUTTON_INDEX_META] = GamepadButton(); mapped->buttons_length = BUTTON_INDEX_COUNT - 1; mapped->axes_length = 0; } -void MapperDualshock4(const blink::WebGamepad& input, - blink::WebGamepad* mapped) { +void MapperDualshock4(const Gamepad& input, Gamepad* mapped) { enum Dualshock4Buttons { DUALSHOCK_BUTTON_TOUCHPAD = BUTTON_INDEX_COUNT, DUALSHOCK_BUTTON_COUNT @@ -77,7 +74,7 @@ void MapperDualshock4(const blink::WebGamepad& input, mapped->axes_length = AXIS_INDEX_COUNT; } -void MapperIBuffalo(const blink::WebGamepad& input, blink::WebGamepad* mapped) { +void MapperIBuffalo(const Gamepad& input, Gamepad* mapped) { *mapped = input; mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[1]; mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[0]; @@ -96,8 +93,7 @@ void MapperIBuffalo(const blink::WebGamepad& input, blink::WebGamepad* mapped) { mapped->axes_length = 2; } -void MapperOnLiveWireless(const blink::WebGamepad& input, - blink::WebGamepad* mapped) { +void MapperOnLiveWireless(const Gamepad& input, Gamepad* mapped) { *mapped = input; mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[0]; mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[1]; @@ -120,7 +116,7 @@ void MapperOnLiveWireless(const blink::WebGamepad& input, mapped->axes_length = AXIS_INDEX_COUNT; } -void MapperADT1(const blink::WebGamepad& input, blink::WebGamepad* mapped) { +void MapperADT1(const Gamepad& input, Gamepad* mapped) { *mapped = input; mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[0]; mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[1]; @@ -142,7 +138,7 @@ void MapperADT1(const blink::WebGamepad& input, blink::WebGamepad* mapped) { mapped->axes_length = AXIS_INDEX_COUNT; } -void MapperNvShield(const blink::WebGamepad& input, blink::WebGamepad* mapped) { +void MapperNvShield(const Gamepad& input, Gamepad* mapped) { *mapped = input; mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[0]; mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[1]; @@ -164,7 +160,7 @@ void MapperNvShield(const blink::WebGamepad& input, blink::WebGamepad* mapped) { mapped->axes_length = AXIS_INDEX_COUNT; } -void MapperOUYA(const blink::WebGamepad& input, blink::WebGamepad* mapped) { +void MapperOUYA(const Gamepad& input, Gamepad* mapped) { *mapped = input; mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[0]; mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[3]; @@ -190,8 +186,7 @@ void MapperOUYA(const blink::WebGamepad& input, blink::WebGamepad* mapped) { mapped->axes_length = AXIS_INDEX_COUNT; } -void MapperRazerServal(const blink::WebGamepad& input, - blink::WebGamepad* mapped) { +void MapperRazerServal(const Gamepad& input, Gamepad* mapped) { *mapped = input; mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[0]; mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[1]; @@ -212,7 +207,7 @@ void MapperRazerServal(const blink::WebGamepad& input, mapped->axes_length = AXIS_INDEX_COUNT; } -void MapperMogaPro(const blink::WebGamepad& input, blink::WebGamepad* mapped) { +void MapperMogaPro(const Gamepad& input, Gamepad* mapped) { *mapped = input; mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[0]; mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[1]; diff --git a/chromium/device/gamepad/gamepad_test_helpers.cc b/chromium/device/gamepad/gamepad_test_helpers.cc index cd1f5cdae4e..d6e27d47e9b 100644 --- a/chromium/device/gamepad/gamepad_test_helpers.cc +++ b/chromium/device/gamepad/gamepad_test_helpers.cc @@ -6,8 +6,7 @@ namespace device { -MockGamepadDataFetcher::MockGamepadDataFetcher( - const blink::WebGamepads& test_data) +MockGamepadDataFetcher::MockGamepadDataFetcher(const Gamepads& test_data) : test_data_(test_data), read_data_(base::WaitableEvent::ResetPolicy::AUTOMATIC, base::WaitableEvent::InitialState::NOT_SIGNALED) {} @@ -22,11 +21,11 @@ void MockGamepadDataFetcher::GetGamepadData(bool devices_changed_hint) { { base::AutoLock lock(lock_); - for (unsigned int i = 0; i < blink::WebGamepads::kItemsLengthCap; ++i) { + for (unsigned int i = 0; i < Gamepads::kItemsLengthCap; ++i) { if (test_data_.items[i].connected) { PadState* pad = GetPadState(i); if (pad) - memcpy(&pad->data, &test_data_.items[i], sizeof(blink::WebGamepad)); + memcpy(&pad->data, &test_data_.items[i], sizeof(Gamepad)); } } } @@ -46,7 +45,7 @@ void MockGamepadDataFetcher::WaitForDataReadAndCallbacksIssued() { WaitForDataRead(); } -void MockGamepadDataFetcher::SetTestData(const blink::WebGamepads& new_data) { +void MockGamepadDataFetcher::SetTestData(const Gamepads& new_data) { base::AutoLock lock(lock_); test_data_ = new_data; } @@ -56,7 +55,7 @@ GamepadTestHelper::GamepadTestHelper() {} GamepadTestHelper::~GamepadTestHelper() {} GamepadServiceTestConstructor::GamepadServiceTestConstructor( - const blink::WebGamepads& test_data) { + const Gamepads& test_data) { data_fetcher_ = new MockGamepadDataFetcher(test_data); gamepad_service_ = new GamepadService(std::unique_ptr<GamepadDataFetcher>(data_fetcher_)); diff --git a/chromium/device/gamepad/gamepad_test_helpers.h b/chromium/device/gamepad/gamepad_test_helpers.h index b4f8c934780..87857c20edf 100644 --- a/chromium/device/gamepad/gamepad_test_helpers.h +++ b/chromium/device/gamepad/gamepad_test_helpers.h @@ -14,7 +14,7 @@ #include "device/gamepad/gamepad_data_fetcher.h" #include "device/gamepad/gamepad_service.h" #include "device/gamepad/gamepad_shared_buffer.h" -#include "third_party/WebKit/public/platform/WebGamepads.h" +#include "device/gamepad/public/cpp/gamepads.h" namespace device { @@ -23,7 +23,7 @@ class MockGamepadDataFetcher : public GamepadDataFetcher { public: // Initializes the fetcher with the given gamepad data, which will be // returned when the provider queries us. - explicit MockGamepadDataFetcher(const blink::WebGamepads& test_data); + explicit MockGamepadDataFetcher(const Gamepads& test_data); ~MockGamepadDataFetcher() override; @@ -42,11 +42,11 @@ class MockGamepadDataFetcher : public GamepadDataFetcher { void WaitForDataReadAndCallbacksIssued(); // Updates the test data. - void SetTestData(const blink::WebGamepads& new_data); + void SetTestData(const Gamepads& new_data); private: base::Lock lock_; - blink::WebGamepads test_data_; + Gamepads test_data_; base::WaitableEvent read_data_; DISALLOW_COPY_AND_ASSIGN(MockGamepadDataFetcher); @@ -71,7 +71,7 @@ class GamepadTestHelper { // global singleton for the gamepad service. class GamepadServiceTestConstructor : public GamepadTestHelper { public: - explicit GamepadServiceTestConstructor(const blink::WebGamepads& test_data); + explicit GamepadServiceTestConstructor(const Gamepads& test_data); ~GamepadServiceTestConstructor() override; GamepadService* gamepad_service() { return gamepad_service_; } diff --git a/chromium/device/gamepad/gamepad_user_gesture.cc b/chromium/device/gamepad/gamepad_user_gesture.cc index 3307bbdb2bb..b4da5e099c4 100644 --- a/chromium/device/gamepad/gamepad_user_gesture.cc +++ b/chromium/device/gamepad/gamepad_user_gesture.cc @@ -8,7 +8,7 @@ #include <algorithm> -#include "third_party/WebKit/public/platform/WebGamepads.h" +#include "device/gamepad/public/cpp/gamepads.h" namespace { // A big enough deadzone to detect accidental presses. @@ -17,9 +17,9 @@ const float kAxisMoveAmountThreshold = 0.5; namespace device { -bool GamepadsHaveUserGesture(const blink::WebGamepads& gamepads) { - for (unsigned int i = 0; i < blink::WebGamepads::kItemsLengthCap; i++) { - const blink::WebGamepad& pad = gamepads.items[i]; +bool GamepadsHaveUserGesture(const Gamepads& gamepads) { + for (unsigned int i = 0; i < Gamepads::kItemsLengthCap; i++) { + const Gamepad& pad = gamepads.items[i]; // If the device is physically connected, then check the buttons and axes // to see if there is currently an intentional user action. diff --git a/chromium/device/gamepad/gamepad_user_gesture.h b/chromium/device/gamepad/gamepad_user_gesture.h index d88601ff552..fa7e73c9d67 100644 --- a/chromium/device/gamepad/gamepad_user_gesture.h +++ b/chromium/device/gamepad/gamepad_user_gesture.h @@ -5,15 +5,13 @@ #ifndef DEVICE_GAMEPAD_USER_GESTURE_H_ #define DEVICE_GAMEPAD_USER_GESTURE_H_ -namespace blink { -class WebGamepads; -} - namespace device { +class Gamepads; + // Returns true if any of the gamepads have a button pressed or axis moved // that would be considered a user gesture for interaction. -bool GamepadsHaveUserGesture(const blink::WebGamepads& gamepads); +bool GamepadsHaveUserGesture(const Gamepads& gamepads); } // namespace device diff --git a/chromium/device/gamepad/public/cpp/BUILD.gn b/chromium/device/gamepad/public/cpp/BUILD.gn new file mode 100644 index 00000000000..fdec85b8d42 --- /dev/null +++ b/chromium/device/gamepad/public/cpp/BUILD.gn @@ -0,0 +1,23 @@ +# Copyright 2017 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. + +# This target contains only those files that are shared by the Device Gamepad +# implementation and all Device Gamepad clients, including Blink. Add a file +# here only if it meets the following constraints: +# (1) It is *necessary* to use the file to consume Device Gamepad (the +# current files define structs that are used as a consistent interpretation of +# shared memory by the Device Gamepad and its clients). +# (2) The file has no dependencies on the STL or Chromium code and will not +# grow them over time (the current files are POD structs and will necessarily +# stay that way due to their above-described purpose). +# Consult {platform-architecture-dev, services-dev}@chromium.org in the case +# of any uncertainty. +source_set("shared_with_blink") { + sources = [ + "gamepad.cc", + "gamepad.h", + "gamepads.h", + ] + # Do not add deps here per the above comment. +} diff --git a/chromium/device/gamepad/public/cpp/gamepad.cc b/chromium/device/gamepad/public/cpp/gamepad.cc new file mode 100644 index 00000000000..bd5bf4ed77c --- /dev/null +++ b/chromium/device/gamepad/public/cpp/gamepad.cc @@ -0,0 +1,21 @@ +// Copyright 2017 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 "device/gamepad/public/cpp/gamepad.h" + +namespace device { + +Gamepad::Gamepad() + : connected(false), + timestamp(0), + axes_length(0), + buttons_length(0), + display_id(0) { + id[0] = 0; + mapping[0] = 0; +} + +Gamepad::Gamepad(const Gamepad& other) = default; + +} // namespace device diff --git a/chromium/device/gamepad/public/cpp/gamepad.h b/chromium/device/gamepad/public/cpp/gamepad.h new file mode 100644 index 00000000000..c8a7e8bd27b --- /dev/null +++ b/chromium/device/gamepad/public/cpp/gamepad.h @@ -0,0 +1,115 @@ +// Copyright 2017 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 DEVICE_GAMEPAD_PUBLIC_CPP_GAMEPAD_H_ +#define DEVICE_GAMEPAD_PUBLIC_CPP_GAMEPAD_H_ + +#include <stddef.h> + +namespace device { + +#pragma pack(push, 4) + +class GamepadButton { + public: + GamepadButton() : pressed(false), touched(false), value(0.) {} + GamepadButton(bool pressed, bool touched, double value) + : pressed(pressed), touched(touched), value(value) {} + bool pressed; + bool touched; + double value; +}; + +class GamepadVector { + public: + GamepadVector() : not_null(false) {} + + bool not_null; + float x, y, z; +}; + +class GamepadQuaternion { + public: + GamepadQuaternion() : not_null(false) {} + + bool not_null; + float x, y, z, w; +}; + +class GamepadPose { + public: + GamepadPose() : not_null(false) {} + + bool not_null; + + bool has_orientation; + bool has_position; + + GamepadQuaternion orientation; + GamepadVector position; + GamepadVector angular_velocity; + GamepadVector linear_velocity; + GamepadVector angular_acceleration; + GamepadVector linear_acceleration; +}; + +enum class GamepadHand { kNone = 0, kLeft = 1, kRight = 2 }; + +// UTF-16 character type +#if defined(WIN32) +using UChar = wchar_t; +#else +using UChar = unsigned short; +#endif + +// This structure is intentionally POD and fixed size so that it can be shared +// memory between hardware polling threads and the rest of the browser. See +// also gamepads.h. +class Gamepad { + public: + static constexpr size_t kIdLengthCap = 128; + static constexpr size_t kMappingLengthCap = 16; + static constexpr size_t kAxesLengthCap = 16; + static constexpr size_t kButtonsLengthCap = 32; + + Gamepad(); + Gamepad(const Gamepad& other); + + // Is there a gamepad connected at this index? + bool connected; + + // Device identifier (based on manufacturer, model, etc.). + UChar id[kIdLengthCap]; + + // Monotonically increasing value referring to when the data were last + // updated. + unsigned long long timestamp; + + // Number of valid entries in the axes array. + unsigned axes_length; + + // Normalized values representing axes, in the range [-1..1]. + double axes[kAxesLengthCap]; + + // Number of valid entries in the buttons array. + unsigned buttons_length; + + // Button states + GamepadButton buttons[kButtonsLengthCap]; + + // Mapping type (for example "standard") + UChar mapping[kMappingLengthCap]; + + GamepadPose pose; + + GamepadHand hand; + + unsigned display_id; +}; + +#pragma pack(pop) + +} // namespace device + +#endif // DEVICE_GAMEPAD_PUBLIC_CPP_GAMEPAD_H_ diff --git a/chromium/device/gamepad/public/cpp/gamepads.h b/chromium/device/gamepad/public/cpp/gamepads.h new file mode 100644 index 00000000000..e5ebebfb251 --- /dev/null +++ b/chromium/device/gamepad/public/cpp/gamepads.h @@ -0,0 +1,29 @@ +// Copyright 2017 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 DEVICE_GAMEPAD_PUBLIC_CPP_GAMEPADS_H_ +#define DEVICE_GAMEPAD_PUBLIC_CPP_GAMEPADS_H_ + +#include "device/gamepad/public/cpp/gamepad.h" + +namespace device { + +#pragma pack(push, 4) + +// This structure is intentionally POD and fixed size so that it can be stored +// in shared memory between hardware polling threads and the rest of the +// browser. +class Gamepads { + public: + static constexpr size_t kItemsLengthCap = 4; + + // Gamepad data for N separate gamepad devices. + Gamepad items[kItemsLengthCap]; +}; + +#pragma pack(pop) + +} // namespace device + +#endif // DEVICE_GAMEPAD_PUBLIC_CPP_GAMEPADS_H_ diff --git a/chromium/device/gamepad/public/interfaces/OWNERS b/chromium/device/gamepad/public/interfaces/OWNERS index a4ead6e62e2..51ec2e6f1da 100644 --- a/chromium/device/gamepad/public/interfaces/OWNERS +++ b/chromium/device/gamepad/public/interfaces/OWNERS @@ -4,3 +4,5 @@ per-file *.mojom=set noparent per-file *.mojom=file://ipc/SECURITY_OWNERS per-file *_struct_traits*.*=set noparent per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS +per-file *.typemap=set noparent +per-file *.typemap=file://ipc/SECURITY_OWNERS diff --git a/chromium/device/gamepad/public/interfaces/gamepad.typemap b/chromium/device/gamepad/public/interfaces/gamepad.typemap index 531b5d0027f..81850d6086e 100644 --- a/chromium/device/gamepad/public/interfaces/gamepad.typemap +++ b/chromium/device/gamepad/public/interfaces/gamepad.typemap @@ -3,7 +3,7 @@ # found in the LICENSE file. mojom = "//device/gamepad/public/interfaces/gamepad.mojom" -public_headers = [ "//third_party/WebKit/public/platform/WebGamepad.h" ] +public_headers = [ "//device/gamepad/public/cpp/gamepad.h" ] traits_headers = [ "//device/gamepad/public/interfaces/gamepad_struct_traits.h" ] sources = [ @@ -15,10 +15,10 @@ deps = [ ] type_mappings = [ - "device.mojom.Gamepad=blink::WebGamepad", - "device.mojom.GamepadButton=blink::WebGamepadButton", - "device.mojom.GamepadHand=blink::WebGamepadHand", - "device.mojom.GamepadPose=blink::WebGamepadPose[nullable_is_same_type]", - "device.mojom.GamepadQuaternion=blink::WebGamepadQuaternion[nullable_is_same_type]", - "device.mojom.GamepadVector=blink::WebGamepadVector[nullable_is_same_type]", + "device.mojom.Gamepad=device::Gamepad", + "device.mojom.GamepadButton=device::GamepadButton", + "device.mojom.GamepadHand=device::GamepadHand", + "device.mojom.GamepadPose=device::GamepadPose[nullable_is_same_type]", + "device.mojom.GamepadQuaternion=device::GamepadQuaternion[nullable_is_same_type]", + "device.mojom.GamepadVector=device::GamepadVector[nullable_is_same_type]", ] diff --git a/chromium/device/gamepad/public/interfaces/gamepad_struct_traits.cc b/chromium/device/gamepad/public/interfaces/gamepad_struct_traits.cc index 3d02a272199..2a97cea2d95 100644 --- a/chromium/device/gamepad/public/interfaces/gamepad_struct_traits.cc +++ b/chromium/device/gamepad/public/interfaces/gamepad_struct_traits.cc @@ -9,16 +9,16 @@ namespace mojo { // static void StructTraits< device::mojom::GamepadQuaternionDataView, - blink::WebGamepadQuaternion>::SetToNull(blink::WebGamepadQuaternion* out) { - memset(out, 0, sizeof(blink::WebGamepadQuaternion)); + device::GamepadQuaternion>::SetToNull(device::GamepadQuaternion* out) { + memset(out, 0, sizeof(device::GamepadQuaternion)); out->not_null = false; } // static bool StructTraits<device::mojom::GamepadQuaternionDataView, - blink::WebGamepadQuaternion>:: + device::GamepadQuaternion>:: Read(device::mojom::GamepadQuaternionDataView data, - blink::WebGamepadQuaternion* out) { + device::GamepadQuaternion* out) { out->not_null = true; out->x = data.x(); out->y = data.y(); @@ -29,17 +29,16 @@ bool StructTraits<device::mojom::GamepadQuaternionDataView, // static void StructTraits<device::mojom::GamepadVectorDataView, - blink::WebGamepadVector>::SetToNull(blink::WebGamepadVector* - out) { - memset(out, 0, sizeof(blink::WebGamepadVector)); + device::GamepadVector>::SetToNull(device::GamepadVector* + out) { + memset(out, 0, sizeof(device::GamepadVector)); out->not_null = false; } // static -bool StructTraits< - device::mojom::GamepadVectorDataView, - blink::WebGamepadVector>::Read(device::mojom::GamepadVectorDataView data, - blink::WebGamepadVector* out) { +bool StructTraits<device::mojom::GamepadVectorDataView, device::GamepadVector>:: + Read(device::mojom::GamepadVectorDataView data, + device::GamepadVector* out) { out->not_null = true; out->x = data.x(); out->y = data.y(); @@ -48,10 +47,9 @@ bool StructTraits< } // static -bool StructTraits< - device::mojom::GamepadButtonDataView, - blink::WebGamepadButton>::Read(device::mojom::GamepadButtonDataView data, - blink::WebGamepadButton* out) { +bool StructTraits<device::mojom::GamepadButtonDataView, device::GamepadButton>:: + Read(device::mojom::GamepadButtonDataView data, + device::GamepadButton* out) { out->pressed = data.pressed(); out->touched = data.touched(); out->value = data.value(); @@ -60,15 +58,14 @@ bool StructTraits< // static void StructTraits<device::mojom::GamepadPoseDataView, - blink::WebGamepadPose>::SetToNull(blink::WebGamepadPose* - out) { - memset(out, 0, sizeof(blink::WebGamepadPose)); + device::GamepadPose>::SetToNull(device::GamepadPose* out) { + memset(out, 0, sizeof(device::GamepadPose)); out->not_null = false; } // static -bool StructTraits<device::mojom::GamepadPoseDataView, blink::WebGamepadPose>:: - Read(device::mojom::GamepadPoseDataView data, blink::WebGamepadPose* out) { +bool StructTraits<device::mojom::GamepadPoseDataView, device::GamepadPose>:: + Read(device::mojom::GamepadPoseDataView data, device::GamepadPose* out) { out->not_null = true; if (!data.ReadOrientation(&out->orientation)) { return false; @@ -97,14 +94,14 @@ bool StructTraits<device::mojom::GamepadPoseDataView, blink::WebGamepadPose>:: // static device::mojom::GamepadHand -EnumTraits<device::mojom::GamepadHand, blink::WebGamepadHand>::ToMojom( - blink::WebGamepadHand input) { +EnumTraits<device::mojom::GamepadHand, device::GamepadHand>::ToMojom( + device::GamepadHand input) { switch (input) { - case blink::WebGamepadHand::kGamepadHandNone: + case device::GamepadHand::kNone: return device::mojom::GamepadHand::GamepadHandNone; - case blink::WebGamepadHand::kGamepadHandLeft: + case device::GamepadHand::kLeft: return device::mojom::GamepadHand::GamepadHandLeft; - case blink::WebGamepadHand::kGamepadHandRight: + case device::GamepadHand::kRight: return device::mojom::GamepadHand::GamepadHandRight; } @@ -113,18 +110,18 @@ EnumTraits<device::mojom::GamepadHand, blink::WebGamepadHand>::ToMojom( } // static -bool EnumTraits<device::mojom::GamepadHand, blink::WebGamepadHand>::FromMojom( +bool EnumTraits<device::mojom::GamepadHand, device::GamepadHand>::FromMojom( device::mojom::GamepadHand input, - blink::WebGamepadHand* output) { + device::GamepadHand* output) { switch (input) { case device::mojom::GamepadHand::GamepadHandNone: - *output = blink::WebGamepadHand::kGamepadHandNone; + *output = device::GamepadHand::kNone; return true; case device::mojom::GamepadHand::GamepadHandLeft: - *output = blink::WebGamepadHand::kGamepadHandLeft; + *output = device::GamepadHand::kLeft; return true; case device::mojom::GamepadHand::GamepadHandRight: - *output = blink::WebGamepadHand::kGamepadHandRight; + *output = device::GamepadHand::kRight; return true; } @@ -134,10 +131,10 @@ bool EnumTraits<device::mojom::GamepadHand, blink::WebGamepadHand>::FromMojom( // static ConstCArray<uint16_t> -StructTraits<device::mojom::GamepadDataView, blink::WebGamepad>::id( - const blink::WebGamepad& r) { +StructTraits<device::mojom::GamepadDataView, device::Gamepad>::id( + const device::Gamepad& r) { size_t id_length = 0; - while (id_length < blink::WebGamepad::kIdLengthCap && r.id[id_length] != 0) { + while (id_length < device::Gamepad::kIdLengthCap && r.id[id_length] != 0) { id_length++; } return {id_length, reinterpret_cast<const uint16_t*>(&r.id[0])}; @@ -145,10 +142,10 @@ StructTraits<device::mojom::GamepadDataView, blink::WebGamepad>::id( // static ConstCArray<uint16_t> -StructTraits<device::mojom::GamepadDataView, blink::WebGamepad>::mapping( - const blink::WebGamepad& r) { +StructTraits<device::mojom::GamepadDataView, device::Gamepad>::mapping( + const device::Gamepad& r) { size_t mapping_length = 0; - while (mapping_length < blink::WebGamepad::kMappingLengthCap && + while (mapping_length < device::Gamepad::kMappingLengthCap && r.mapping[mapping_length] != 0) { mapping_length++; } @@ -156,14 +153,13 @@ StructTraits<device::mojom::GamepadDataView, blink::WebGamepad>::mapping( } // static -bool StructTraits<device::mojom::GamepadDataView, blink::WebGamepad>::Read( +bool StructTraits<device::mojom::GamepadDataView, device::Gamepad>::Read( device::mojom::GamepadDataView data, - blink::WebGamepad* out) { + device::Gamepad* out) { out->connected = data.connected(); - memset(&out->id[0], 0, - blink::WebGamepad::kIdLengthCap * sizeof(blink::WebUChar)); - CArray<uint16_t> id = {0, blink::WebGamepad::kIdLengthCap, + memset(&out->id[0], 0, device::Gamepad::kIdLengthCap * sizeof(device::UChar)); + CArray<uint16_t> id = {0, device::Gamepad::kIdLengthCap, reinterpret_cast<uint16_t*>(&out->id[0])}; if (!data.ReadId(&id)) { return false; @@ -171,15 +167,15 @@ bool StructTraits<device::mojom::GamepadDataView, blink::WebGamepad>::Read( out->timestamp = data.timestamp(); - CArray<double> axes = {0, blink::WebGamepad::kAxesLengthCap, &out->axes[0]}; + CArray<double> axes = {0, device::Gamepad::kAxesLengthCap, &out->axes[0]}; if (!data.ReadAxes(&axes)) { return false; } // static_cast is safe when "data.ReadAxes(&axes)" above returns true. out->axes_length = static_cast<unsigned>(axes.size); - CArray<blink::WebGamepadButton> buttons = { - 0, blink::WebGamepad::kButtonsLengthCap, &out->buttons[0]}; + CArray<device::GamepadButton> buttons = { + 0, device::Gamepad::kButtonsLengthCap, &out->buttons[0]}; if (!data.ReadButtons(&buttons)) { return false; } @@ -187,8 +183,8 @@ bool StructTraits<device::mojom::GamepadDataView, blink::WebGamepad>::Read( out->buttons_length = static_cast<unsigned>(buttons.size); memset(&out->mapping[0], 0, - blink::WebGamepad::kMappingLengthCap * sizeof(blink::WebUChar)); - CArray<uint16_t> mapping = {0, blink::WebGamepad::kMappingLengthCap, + device::Gamepad::kMappingLengthCap * sizeof(device::UChar)); + CArray<uint16_t> mapping = {0, device::Gamepad::kMappingLengthCap, reinterpret_cast<uint16_t*>(&out->mapping[0])}; if (!data.ReadMapping(&mapping)) { return false; @@ -198,7 +194,7 @@ bool StructTraits<device::mojom::GamepadDataView, blink::WebGamepad>::Read( return false; } - blink::WebGamepadHand hand; + device::GamepadHand hand; if (!data.ReadHand(&hand)) { return false; } diff --git a/chromium/device/gamepad/public/interfaces/gamepad_struct_traits.h b/chromium/device/gamepad/public/interfaces/gamepad_struct_traits.h index b0a334eddf8..9d02f52f197 100644 --- a/chromium/device/gamepad/public/interfaces/gamepad_struct_traits.h +++ b/chromium/device/gamepad/public/interfaces/gamepad_struct_traits.h @@ -7,113 +7,107 @@ #include <stddef.h> +#include "device/gamepad/public/cpp/gamepad.h" #include "device/gamepad/public/interfaces/gamepad.mojom.h" #include "mojo/public/cpp/bindings/array_traits_carray.h" #include "mojo/public/cpp/bindings/struct_traits.h" -#include "third_party/WebKit/public/platform/WebGamepad.h" namespace mojo { template <> struct StructTraits<device::mojom::GamepadQuaternionDataView, - blink::WebGamepadQuaternion> { - static bool IsNull(const blink::WebGamepadQuaternion& r) { - return !r.not_null; - } - static void SetToNull(blink::WebGamepadQuaternion* out); - static float x(const blink::WebGamepadQuaternion& r) { return r.x; } - static float y(const blink::WebGamepadQuaternion& r) { return r.y; } - static float z(const blink::WebGamepadQuaternion& r) { return r.z; } - static float w(const blink::WebGamepadQuaternion& r) { return r.w; } + device::GamepadQuaternion> { + static bool IsNull(const device::GamepadQuaternion& r) { return !r.not_null; } + static void SetToNull(device::GamepadQuaternion* out); + static float x(const device::GamepadQuaternion& r) { return r.x; } + static float y(const device::GamepadQuaternion& r) { return r.y; } + static float z(const device::GamepadQuaternion& r) { return r.z; } + static float w(const device::GamepadQuaternion& r) { return r.w; } static bool Read(device::mojom::GamepadQuaternionDataView data, - blink::WebGamepadQuaternion* out); + device::GamepadQuaternion* out); }; template <> struct StructTraits<device::mojom::GamepadVectorDataView, - blink::WebGamepadVector> { - static bool IsNull(const blink::WebGamepadVector& r) { return !r.not_null; } - static void SetToNull(blink::WebGamepadVector* out); - static float x(const blink::WebGamepadVector& r) { return r.x; } - static float y(const blink::WebGamepadVector& r) { return r.y; } - static float z(const blink::WebGamepadVector& r) { return r.z; } + device::GamepadVector> { + static bool IsNull(const device::GamepadVector& r) { return !r.not_null; } + static void SetToNull(device::GamepadVector* out); + static float x(const device::GamepadVector& r) { return r.x; } + static float y(const device::GamepadVector& r) { return r.y; } + static float z(const device::GamepadVector& r) { return r.z; } static bool Read(device::mojom::GamepadVectorDataView data, - blink::WebGamepadVector* out); + device::GamepadVector* out); }; template <> struct StructTraits<device::mojom::GamepadButtonDataView, - blink::WebGamepadButton> { - static bool pressed(const blink::WebGamepadButton& r) { return r.pressed; } - static bool touched(const blink::WebGamepadButton& r) { return r.touched; } - static double value(const blink::WebGamepadButton& r) { return r.value; } + device::GamepadButton> { + static bool pressed(const device::GamepadButton& r) { return r.pressed; } + static bool touched(const device::GamepadButton& r) { return r.touched; } + static double value(const device::GamepadButton& r) { return r.value; } static bool Read(device::mojom::GamepadButtonDataView data, - blink::WebGamepadButton* out); + device::GamepadButton* out); }; template <> -struct StructTraits<device::mojom::GamepadPoseDataView, blink::WebGamepadPose> { - static bool IsNull(const blink::WebGamepadPose& r) { return !r.not_null; } - static void SetToNull(blink::WebGamepadPose* out); - static const blink::WebGamepadQuaternion& orientation( - const blink::WebGamepadPose& r) { +struct StructTraits<device::mojom::GamepadPoseDataView, device::GamepadPose> { + static bool IsNull(const device::GamepadPose& r) { return !r.not_null; } + static void SetToNull(device::GamepadPose* out); + static const device::GamepadQuaternion& orientation( + const device::GamepadPose& r) { return r.orientation; } - static const blink::WebGamepadVector& position( - const blink::WebGamepadPose& r) { + static const device::GamepadVector& position(const device::GamepadPose& r) { return r.position; } - static const blink::WebGamepadVector& angular_velocity( - const blink::WebGamepadPose& r) { + static const device::GamepadVector& angular_velocity( + const device::GamepadPose& r) { return r.angular_velocity; } - static const blink::WebGamepadVector& linear_velocity( - const blink::WebGamepadPose& r) { + static const device::GamepadVector& linear_velocity( + const device::GamepadPose& r) { return r.linear_velocity; } - static const blink::WebGamepadVector& angular_acceleration( - const blink::WebGamepadPose& r) { + static const device::GamepadVector& angular_acceleration( + const device::GamepadPose& r) { return r.angular_acceleration; } - static const blink::WebGamepadVector& linear_acceleration( - const blink::WebGamepadPose& r) { + static const device::GamepadVector& linear_acceleration( + const device::GamepadPose& r) { return r.linear_acceleration; } static bool Read(device::mojom::GamepadPoseDataView data, - blink::WebGamepadPose* out); + device::GamepadPose* out); }; template <> -struct EnumTraits<device::mojom::GamepadHand, blink::WebGamepadHand> { - static device::mojom::GamepadHand ToMojom(blink::WebGamepadHand input); +struct EnumTraits<device::mojom::GamepadHand, device::GamepadHand> { + static device::mojom::GamepadHand ToMojom(device::GamepadHand input); static bool FromMojom(device::mojom::GamepadHand input, - blink::WebGamepadHand* output); + device::GamepadHand* output); }; template <> -struct StructTraits<device::mojom::GamepadDataView, blink::WebGamepad> { - static bool connected(const blink::WebGamepad& r) { return r.connected; } - static uint64_t timestamp(const blink::WebGamepad& r) { return r.timestamp; } - static ConstCArray<double> axes(const blink::WebGamepad& r) { +struct StructTraits<device::mojom::GamepadDataView, device::Gamepad> { + static bool connected(const device::Gamepad& r) { return r.connected; } + static uint64_t timestamp(const device::Gamepad& r) { return r.timestamp; } + static ConstCArray<double> axes(const device::Gamepad& r) { return {r.axes_length, &r.axes[0]}; } - static ConstCArray<blink::WebGamepadButton> buttons( - const blink::WebGamepad& r) { + static ConstCArray<device::GamepadButton> buttons(const device::Gamepad& r) { return {r.buttons_length, &r.buttons[0]}; } - static const blink::WebGamepadPose& pose(const blink::WebGamepad& r) { + static const device::GamepadPose& pose(const device::Gamepad& r) { return r.pose; } - static const blink::WebGamepadHand& hand(const blink::WebGamepad& r) { + static const device::GamepadHand& hand(const device::Gamepad& r) { return r.hand; } - static uint32_t display_id(const blink::WebGamepad& r) { - return r.display_id; - } + static uint32_t display_id(const device::Gamepad& r) { return r.display_id; } - static ConstCArray<uint16_t> id(const blink::WebGamepad& r); - static ConstCArray<uint16_t> mapping(const blink::WebGamepad& r); - static bool Read(device::mojom::GamepadDataView data, blink::WebGamepad* out); + static ConstCArray<uint16_t> id(const device::Gamepad& r); + static ConstCArray<uint16_t> mapping(const device::Gamepad& r); + static bool Read(device::mojom::GamepadDataView data, device::Gamepad* out); }; } // namespace mojo diff --git a/chromium/device/gamepad/public/interfaces/gamepad_struct_traits_unittest.cc b/chromium/device/gamepad/public/interfaces/gamepad_struct_traits_unittest.cc index e3b59f10f78..5a731fe88b0 100644 --- a/chromium/device/gamepad/public/interfaces/gamepad_struct_traits_unittest.cc +++ b/chromium/device/gamepad/public/interfaces/gamepad_struct_traits_unittest.cc @@ -2,13 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <utility> + #include "base/message_loop/message_loop.h" #include "base/run_loop.h" +#include "device/gamepad/public/cpp/gamepad.h" #include "device/gamepad/public/interfaces/gamepad_struct_traits_test.mojom.h" #include "mojo/public/cpp/bindings/binding.h" #include "mojo/public/cpp/bindings/interface_request.h" #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/WebKit/public/platform/WebGamepad.h" namespace device { @@ -21,21 +23,21 @@ enum GamepadTestDataType { GamepadPose_Null = 3, }; -blink::WebGamepad GetWebGamepadInstance(GamepadTestDataType type) { - blink::WebGamepadButton wgb(true, false, 1.0f); +Gamepad GetWebGamepadInstance(GamepadTestDataType type) { + GamepadButton wgb(true, false, 1.0f); - blink::WebGamepadVector wgv; - memset(&wgv, 0, sizeof(blink::WebGamepadVector)); + GamepadVector wgv; + memset(&wgv, 0, sizeof(GamepadVector)); wgv.not_null = true; wgv.x = wgv.y = wgv.z = 1.0f; - blink::WebGamepadQuaternion wgq; - memset(&wgq, 0, sizeof(blink::WebGamepadQuaternion)); + GamepadQuaternion wgq; + memset(&wgq, 0, sizeof(GamepadQuaternion)); wgq.not_null = true; wgq.x = wgq.y = wgq.z = wgq.w = 2.0f; - blink::WebGamepadPose wgp; - memset(&wgp, 0, sizeof(blink::WebGamepadPose)); + GamepadPose wgp; + memset(&wgp, 0, sizeof(GamepadPose)); if (type == GamepadPose_Null) { wgp.not_null = false; } else if (type == GamepadCommon) { @@ -55,57 +57,56 @@ blink::WebGamepad GetWebGamepadInstance(GamepadTestDataType type) { wgp.angular_acceleration = wgv; } - blink::WebUChar wch[blink::WebGamepad::kMappingLengthCap] = { + UChar wch[Gamepad::kMappingLengthCap] = { 1, 8, 9, 127, 128, 1024, 1025, 1949, 2047, 2048, 16383, 16384, 20000, 32767, 32768, 65535}; - blink::WebGamepad send; - memset(&send, 0, sizeof(blink::WebGamepad)); + Gamepad send; + memset(&send, 0, sizeof(Gamepad)); send.connected = true; - for (size_t i = 0; i < blink::WebGamepad::kMappingLengthCap; i++) { + for (size_t i = 0; i < Gamepad::kMappingLengthCap; i++) { send.id[i] = send.mapping[i] = wch[i]; } send.timestamp = 1234567890123456789ULL; send.axes_length = 0U; - for (size_t i = 0; i < blink::WebGamepad::kAxesLengthCap; i++) { + for (size_t i = 0; i < Gamepad::kAxesLengthCap; i++) { send.axes_length++; send.axes[i] = 1.0; } send.buttons_length = 0U; - for (size_t i = 0; i < blink::WebGamepad::kButtonsLengthCap; i++) { + for (size_t i = 0; i < Gamepad::kButtonsLengthCap; i++) { send.buttons_length++; send.buttons[i] = wgb; } send.pose = wgp; - send.hand = blink::WebGamepadHand::kGamepadHandRight; + send.hand = GamepadHand::kRight; send.display_id = static_cast<unsigned short>(16); return send; } -bool isWebGamepadButtonEqual(const blink::WebGamepadButton& lhs, - const blink::WebGamepadButton& rhs) { +bool isWebGamepadButtonEqual(const GamepadButton& lhs, + const GamepadButton& rhs) { return (lhs.pressed == rhs.pressed && lhs.touched == rhs.touched && lhs.value == rhs.value); } -bool isWebGamepadVectorEqual(const blink::WebGamepadVector& lhs, - const blink::WebGamepadVector& rhs) { +bool isWebGamepadVectorEqual(const GamepadVector& lhs, + const GamepadVector& rhs) { return ((lhs.not_null == false && rhs.not_null == false) || (lhs.not_null == rhs.not_null && lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z)); } -bool isWebGamepadQuaternionEqual(const blink::WebGamepadQuaternion& lhs, - const blink::WebGamepadQuaternion& rhs) { +bool isWebGamepadQuaternionEqual(const GamepadQuaternion& lhs, + const GamepadQuaternion& rhs) { return ((lhs.not_null == false && rhs.not_null == false) || (lhs.not_null == rhs.not_null && lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z && lhs.w == rhs.w)); } -bool isWebGamepadPoseEqual(const blink::WebGamepadPose& lhs, - const blink::WebGamepadPose& rhs) { +bool isWebGamepadPoseEqual(const GamepadPose& lhs, const GamepadPose& rhs) { if (lhs.not_null == false && rhs.not_null == false) { return true; } @@ -131,8 +132,7 @@ bool isWebGamepadPoseEqual(const blink::WebGamepadPose& lhs, return true; } -bool isWebGamepadEqual(const blink::WebGamepad& send, - const blink::WebGamepad& echo) { +bool isWebGamepadEqual(const Gamepad& send, const Gamepad& echo) { if (send.connected != echo.connected || send.timestamp != echo.timestamp || send.axes_length != echo.axes_length || send.buttons_length != echo.buttons_length || @@ -140,22 +140,22 @@ bool isWebGamepadEqual(const blink::WebGamepad& send, send.display_id != echo.display_id) { return false; } - for (size_t i = 0; i < blink::WebGamepad::kIdLengthCap; i++) { + for (size_t i = 0; i < Gamepad::kIdLengthCap; i++) { if (send.id[i] != echo.id[i]) { return false; } } - for (size_t i = 0; i < blink::WebGamepad::kAxesLengthCap; i++) { + for (size_t i = 0; i < Gamepad::kAxesLengthCap; i++) { if (send.axes[i] != echo.axes[i]) { return false; } } - for (size_t i = 0; i < blink::WebGamepad::kButtonsLengthCap; i++) { + for (size_t i = 0; i < Gamepad::kButtonsLengthCap; i++) { if (!isWebGamepadButtonEqual(send.buttons[i], echo.buttons[i])) { return false; } } - for (size_t i = 0; i < blink::WebGamepad::kMappingLengthCap; i++) { + for (size_t i = 0; i < Gamepad::kMappingLengthCap; i++) { if (send.mapping[i] != echo.mapping[i]) { return false; } @@ -163,9 +163,9 @@ bool isWebGamepadEqual(const blink::WebGamepad& send, return true; } -void ExpectWebGamepad(const blink::WebGamepad& send, +void ExpectWebGamepad(const Gamepad& send, const base::Closure& closure, - const blink::WebGamepad& echo) { + const Gamepad& echo) { EXPECT_EQ(true, isWebGamepadEqual(send, echo)); closure.Run(); } @@ -173,61 +173,56 @@ void ExpectWebGamepad(const blink::WebGamepad& send, } // namespace class GamepadStructTraitsTest : public testing::Test, - public device::mojom::GamepadStructTraitsTest { + public mojom::GamepadStructTraitsTest { protected: GamepadStructTraitsTest() : binding_(this) {} - void PassGamepad(const blink::WebGamepad& send, - const PassGamepadCallback& callback) override { - callback.Run(send); + void PassGamepad(const Gamepad& send, PassGamepadCallback callback) override { + std::move(callback).Run(send); } - device::mojom::GamepadStructTraitsTestPtr GetGamepadStructTraitsTestProxy() { + mojom::GamepadStructTraitsTestPtr GetGamepadStructTraitsTestProxy() { return binding_.CreateInterfacePtrAndBind(); } private: base::MessageLoop message_loop_; - mojo::Binding<device::mojom::GamepadStructTraitsTest> binding_; + mojo::Binding<mojom::GamepadStructTraitsTest> binding_; DISALLOW_COPY_AND_ASSIGN(GamepadStructTraitsTest); }; TEST_F(GamepadStructTraitsTest, GamepadCommon) { - blink::WebGamepad send = GetWebGamepadInstance(GamepadCommon); + Gamepad send = GetWebGamepadInstance(GamepadCommon); base::RunLoop loop; - device::mojom::GamepadStructTraitsTestPtr proxy = - GetGamepadStructTraitsTestProxy(); + mojom::GamepadStructTraitsTestPtr proxy = GetGamepadStructTraitsTestProxy(); proxy->PassGamepad(send, base::Bind(&ExpectWebGamepad, send, loop.QuitClosure())); loop.Run(); } TEST_F(GamepadStructTraitsTest, GamepadPose_HasOrientation) { - blink::WebGamepad send = GetWebGamepadInstance(GamepadPose_HasOrientation); + Gamepad send = GetWebGamepadInstance(GamepadPose_HasOrientation); base::RunLoop loop; - device::mojom::GamepadStructTraitsTestPtr proxy = - GetGamepadStructTraitsTestProxy(); + mojom::GamepadStructTraitsTestPtr proxy = GetGamepadStructTraitsTestProxy(); proxy->PassGamepad(send, base::Bind(&ExpectWebGamepad, send, loop.QuitClosure())); loop.Run(); } TEST_F(GamepadStructTraitsTest, GamepadPose_HasPosition) { - blink::WebGamepad send = GetWebGamepadInstance(GamepadPose_HasPosition); + Gamepad send = GetWebGamepadInstance(GamepadPose_HasPosition); base::RunLoop loop; - device::mojom::GamepadStructTraitsTestPtr proxy = - GetGamepadStructTraitsTestProxy(); + mojom::GamepadStructTraitsTestPtr proxy = GetGamepadStructTraitsTestProxy(); proxy->PassGamepad(send, base::Bind(&ExpectWebGamepad, send, loop.QuitClosure())); loop.Run(); } TEST_F(GamepadStructTraitsTest, GamepadPose_Null) { - blink::WebGamepad send = GetWebGamepadInstance(GamepadPose_Null); + Gamepad send = GetWebGamepadInstance(GamepadPose_Null); base::RunLoop loop; - device::mojom::GamepadStructTraitsTestPtr proxy = - GetGamepadStructTraitsTestProxy(); + mojom::GamepadStructTraitsTestPtr proxy = GetGamepadStructTraitsTestProxy(); proxy->PassGamepad(send, base::Bind(&ExpectWebGamepad, send, loop.QuitClosure())); loop.Run(); diff --git a/chromium/device/gamepad/raw_input_data_fetcher_win.cc b/chromium/device/gamepad/raw_input_data_fetcher_win.cc index 5684986a2ef..57fe372e0c3 100644 --- a/chromium/device/gamepad/raw_input_data_fetcher_win.cc +++ b/chromium/device/gamepad/raw_input_data_fetcher_win.cc @@ -12,8 +12,6 @@ namespace device { -using namespace blink; - namespace { float NormalizeAxis(long value, long min, long max) { @@ -149,7 +147,7 @@ void RawInputDataFetcher::GetGamepadData(bool devices_changed_hint) { if (!state) continue; - WebGamepad& pad = state->data; + Gamepad& pad = state->data; pad.timestamp = gamepad->report_id; pad.buttons_length = gamepad->buttons_length; @@ -205,7 +203,7 @@ void RawInputDataFetcher::EnumerateDevices() { controllers_[device_handle] = gamepad; - WebGamepad& pad = state->data; + Gamepad& pad = state->data; pad.connected = true; std::string vendor = base::StringPrintf("%04x", gamepad->vendor_id); @@ -214,13 +212,13 @@ void RawInputDataFetcher::EnumerateDevices() { state->axis_mask = 0; state->button_mask = 0; - swprintf(pad.id, WebGamepad::kIdLengthCap, + swprintf(pad.id, Gamepad::kIdLengthCap, L"%ls (%lsVendor: %04x Product: %04x)", gamepad->id, state->mapper ? L"STANDARD GAMEPAD " : L"", gamepad->vendor_id, gamepad->product_id); if (state->mapper) - swprintf(pad.mapping, WebGamepad::kMappingLengthCap, L"standard"); + swprintf(pad.mapping, Gamepad::kMappingLengthCap, L"standard"); else pad.mapping[0] = 0; } @@ -230,11 +228,14 @@ void RawInputDataFetcher::EnumerateDevices() { } // Clear out old controllers that weren't part of this enumeration pass. - for (const auto& controller : controllers_) { - RawGamepadInfo* gamepad = controller.second; + auto controller_it = controllers_.begin(); + while (controller_it != controllers_.end()) { + RawGamepadInfo* gamepad = controller_it->second; if (gamepad->enumeration_id != last_enumeration_id_) { - controllers_.erase(gamepad->handle); + controller_it = controllers_.erase(controller_it); delete gamepad; + } else { + ++controller_it; } } } @@ -325,7 +326,7 @@ RawGamepadInfo* RawInputDataFetcher::ParseGamepadInfo(HANDLE hDevice) { } if (!got_product_string) - swprintf(gamepad_info->id, WebGamepad::kIdLengthCap, L"Unknown Gamepad"); + swprintf(gamepad_info->id, Gamepad::kIdLengthCap, L"Unknown Gamepad"); // Query device capabilities. result = GetRawInputDeviceInfo(hDevice, RIDI_PREPARSEDDATA, NULL, &size); @@ -360,10 +361,10 @@ RawGamepadInfo* RawInputDataFetcher::ParseGamepadInfo(HANDLE hDevice) { DCHECK_EQ(HIDP_STATUS_SUCCESS, status); for (uint32_t i = 0; i < count; ++i) { - if (button_caps[i].Range.UsageMin <= WebGamepad::kButtonsLengthCap && + if (button_caps[i].Range.UsageMin <= Gamepad::kButtonsLengthCap && button_caps[i].UsagePage == kButtonUsagePage) { uint32_t max_index = - std::min(WebGamepad::kButtonsLengthCap, + std::min(Gamepad::kButtonsLengthCap, static_cast<size_t>(button_caps[i].Range.UsageMax)); gamepad_info->buttons_length = std::max(gamepad_info->buttons_length, max_index); @@ -381,7 +382,7 @@ RawGamepadInfo* RawInputDataFetcher::ParseGamepadInfo(HANDLE hDevice) { for (UINT i = 0; i < count; i++) { uint32_t axis_index = axes_caps[i].Range.UsageMin - kAxisMinimumUsageNumber; - if (axis_index < WebGamepad::kAxesLengthCap) { + if (axis_index < Gamepad::kAxesLengthCap) { gamepad_info->axes[axis_index].caps = axes_caps[i]; gamepad_info->axes[axis_index].value = 0; gamepad_info->axes[axis_index].active = true; @@ -398,13 +399,13 @@ RawGamepadInfo* RawInputDataFetcher::ParseGamepadInfo(HANDLE hDevice) { uint32_t next_index = 0; for (UINT i = 0; i < count; i++) { uint32_t usage = axes_caps[i].Range.UsageMin - kAxisMinimumUsageNumber; - if (usage >= WebGamepad::kAxesLengthCap && + if (usage >= Gamepad::kAxesLengthCap && axes_caps[i].UsagePage <= kGameControlsUsagePage) { - for (; next_index < WebGamepad::kAxesLengthCap; ++next_index) { + for (; next_index < Gamepad::kAxesLengthCap; ++next_index) { if (!gamepad_info->axes[next_index].active) break; } - if (next_index < WebGamepad::kAxesLengthCap) { + if (next_index < Gamepad::kAxesLengthCap) { gamepad_info->axes[next_index].caps = axes_caps[i]; gamepad_info->axes[next_index].value = 0; gamepad_info->axes[next_index].active = true; @@ -415,7 +416,7 @@ RawGamepadInfo* RawInputDataFetcher::ParseGamepadInfo(HANDLE hDevice) { } } - if (next_index >= WebGamepad::kAxesLengthCap) + if (next_index >= Gamepad::kAxesLengthCap) break; } } @@ -457,8 +458,7 @@ void RawInputDataFetcher::UpdateGamepad(RAWINPUT* input, for (uint32_t j = 0; j < buttons_length; j++) { int32_t button_index = usages[j].Usage - 1; if (usages[j].UsagePage == kButtonUsagePage && button_index >= 0 && - button_index < - static_cast<int>(blink::WebGamepad::kButtonsLengthCap)) { + button_index < static_cast<int>(Gamepad::kButtonsLengthCap)) { gamepad_info->buttons[button_index] = true; } } diff --git a/chromium/device/gamepad/raw_input_data_fetcher_win.h b/chromium/device/gamepad/raw_input_data_fetcher_win.h index 7e443dc3dc4..7943dfc7272 100644 --- a/chromium/device/gamepad/raw_input_data_fetcher_win.h +++ b/chromium/device/gamepad/raw_input_data_fetcher_win.h @@ -23,7 +23,7 @@ #include "build/build_config.h" #include "device/gamepad/gamepad_data_fetcher.h" #include "device/gamepad/gamepad_standard_mappings.h" -#include "third_party/WebKit/public/platform/WebGamepads.h" +#include "device/gamepad/public/cpp/gamepad.h" namespace device { @@ -48,13 +48,13 @@ struct RawGamepadInfo { uint32_t vendor_id; uint32_t product_id; - wchar_t id[blink::WebGamepad::kIdLengthCap]; + wchar_t id[Gamepad::kIdLengthCap]; uint32_t buttons_length; - bool buttons[blink::WebGamepad::kButtonsLengthCap]; + bool buttons[Gamepad::kButtonsLengthCap]; uint32_t axes_length; - RawGamepadAxis axes[blink::WebGamepad::kAxesLengthCap]; + RawGamepadAxis axes[Gamepad::kAxesLengthCap]; }; class RawInputDataFetcher : public GamepadDataFetcher, diff --git a/chromium/device/gamepad/xbox_data_fetcher_mac.mm b/chromium/device/gamepad/xbox_data_fetcher_mac.mm index f4a235a71ba..f0057c376c9 100644 --- a/chromium/device/gamepad/xbox_data_fetcher_mac.mm +++ b/chromium/device/gamepad/xbox_data_fetcher_mac.mm @@ -17,8 +17,6 @@ #include "base/logging.h" #include "base/mac/foundation_util.h" -using blink::WebGamepad; - namespace device { namespace { @@ -228,11 +226,11 @@ void NormalizeXboxOneButtonData(const XboxOneButtonData& data, } void CopyNSStringAsUTF16LittleEndian(NSString* src, - blink::WebUChar* dest, + UChar* dest, size_t dest_len) { NSData* as16 = [src dataUsingEncoding:NSUTF16LittleEndianStringEncoding]; memset(dest, 0, dest_len); - [as16 getBytes:dest length:dest_len - sizeof(blink::WebUChar)]; + [as16 getBytes:dest length:dest_len - sizeof(UChar)]; } } // namespace @@ -811,7 +809,7 @@ void XboxDataFetcher::XboxControllerGotData(XboxController* controller, if (!state) return; // No available slot for this device - WebGamepad& pad = state->data; + Gamepad& pad = state->data; for (size_t i = 0; i < 6; i++) { pad.buttons[i].pressed = data.buttons[i]; diff --git a/chromium/device/generic_sensor/BUILD.gn b/chromium/device/generic_sensor/BUILD.gn index de71e31dd6d..f95b0a1b20c 100644 --- a/chromium/device/generic_sensor/BUILD.gn +++ b/chromium/device/generic_sensor/BUILD.gn @@ -17,6 +17,8 @@ component("generic_sensor") { "linux/sensor_data_linux.h", "platform_sensor.cc", "platform_sensor.h", + "platform_sensor_accelerometer_mac.cc", + "platform_sensor_accelerometer_mac.h", "platform_sensor_ambient_light_mac.cc", "platform_sensor_ambient_light_mac.h", "platform_sensor_android.cc", @@ -66,8 +68,14 @@ component("generic_sensor") { } if (is_mac) { - deps += [ "//device/sensors/public/cpp:full" ] - libs = [ "IOKit.framework" ] + deps += [ + "//device/sensors/public/cpp:full", + "//third_party/sudden_motion_sensor", + ] + libs = [ + "CoreFoundation.framework", + "IOKit.framework", + ] } if (use_udev) { diff --git a/chromium/device/generic_sensor/DEPS b/chromium/device/generic_sensor/DEPS index d69661a3166..162bc1c65b3 100644 --- a/chromium/device/generic_sensor/DEPS +++ b/chromium/device/generic_sensor/DEPS @@ -1,4 +1,5 @@ include_rules = [ "+device/base/synchronization", "+jni", + "+third_party/sudden_motion_sensor", ] diff --git a/chromium/device/generic_sensor/OWNERS b/chromium/device/generic_sensor/OWNERS index bc4aa627721..fa52be797d1 100644 --- a/chromium/device/generic_sensor/OWNERS +++ b/chromium/device/generic_sensor/OWNERS @@ -1,3 +1,6 @@ alexander.shalamov@intel.com mikhail.pozdnyakov@intel.com timvolodine@chromium.org + +# COMPONENT: Blink>Sensor +# TEAM: device-dev@chromium.org diff --git a/chromium/device/generic_sensor/README.md b/chromium/device/generic_sensor/README.md new file mode 100644 index 00000000000..e1842f971ab --- /dev/null +++ b/chromium/device/generic_sensor/README.md @@ -0,0 +1,71 @@ +# Sensors + +`device/generic_sensor` contains the platform-specific parts of the Sensor APIs +implementation. + +Sensors Mojo interfaces are defined in the `public/interfaces` subdirectory. + +The JS bindings are implemented in `third_party/WebKit/Source/modules/sensor`. + + +## Platform Support + +Support for the SensorTypes defined by the Mojo interface is summarized in this +table. An empty cell indicates that the sensor type is not supported on that +platform. + +| SensorType | Android | Linux | macOS | Windows | +| -------------------- | ------------------------- | -------------- | ------------------ | ----------------------------------------- | +| AMBIENT_LIGHT | TYPE_LIGHT | in_illuminance | AppleLMUController | SENSOR_TYPE_AMBIENT_LIGHT | +| PROXIMITY | | | | | +| ACCELEROMETER | TYPE_ACCELEROMETER | in_accel | SMCMotionSensor | SENSOR_TYPE_ACCELEROMETER_3D | +| LINEAR_ACCELEROMETER | TYPE_LINEAR_ACCELEROMETER | | | | +| GYROSCOPE | TYPE_GYROSCOPE | in_anglvel | | SENSOR_TYPE_GYROMETER_3D | +| MAGNETOMETER | TYPE_MAGNETIC_FIELD | in_magn | | SENSOR_TYPE_COMPASS_3D | +| PRESSURE | | | | | +| ABSOLUTE_ORIENTATION | TYPE_ROTATION_VECTOR | | | SENSOR_TYPE_AGGREGATED_DEVICE_ORIENTATION | +| RELATIVE_ORIENTATION | TYPE_GAME_ROTATION_VECTOR | | | | + +### Android + +Sensors are implemented by passing through values provided by the +[Sensor](https://developer.android.com/reference/android/hardware/Sensor.html) +class. The values in the "Android" column of the table above correspond to the +integer constants from the android.hardware.Sensor used to provide data for a +SensorType. + +### Linux (and Chrome OS) + +Sensors are implemented by reading values from the IIO subsystem. The values in +the "Linux" column of the table above are the prefix of the sysfs files Chrome +searches for to provide data for a SensorType. + +### macOS + +On this platform there is limited support for sensors. The AMBIENT_LIGHT sensor +type is provided by interpreting the value that can be read from the LMU. The +ACCELEROMETER sensor type is provided by interpreting the value that can be read +from the SMCMotionSensor. + +### Windows + +Sensors are implemented by passing through values provided by the +[Sensor API](https://msdn.microsoft.com/en-us/library/windows/desktop/dd318953(v=vs.85).aspx). +The values in the "Windows" column of the table above correspond to the names of +the sensor type GUIDs used to provide data for a SensorType. + +## Testing + +Sensors platform unit tests are located in the current directory and its +subdirectories. + +The sensors unit tests file for Android is +`android/junit/src/org/chromium/device/sensors/PlatformSensorAndProviderTest.java`. + +Sensors browser tests are located in `content/test/data/generic_sensor`. + + +## Design Documents + +Please refer to the [design documentation](https://docs.google.com/document/d/1Ml65ZdW5AgIsZTszk4mD_ohr40pcrdVFOIf0ZtWxDv0) +for more details. diff --git a/chromium/device/generic_sensor/linux/sensor_device_manager.cc b/chromium/device/generic_sensor/linux/sensor_device_manager.cc index 4fc04340f8c..fb4ca88df15 100644 --- a/chromium/device/generic_sensor/linux/sensor_device_manager.cc +++ b/chromium/device/generic_sensor/linux/sensor_device_manager.cc @@ -23,15 +23,15 @@ SensorDeviceManager::SensorDeviceManager() : observer_(this), delegate_(nullptr), task_runner_(base::ThreadTaskRunnerHandle::Get()) { - thread_checker_.DetachFromThread(); + DETACH_FROM_THREAD(thread_checker_); } SensorDeviceManager::~SensorDeviceManager() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); } void SensorDeviceManager::Start(Delegate* delegate) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); base::ThreadRestrictions::AssertIOAllowed(); DCHECK(!delegate_); diff --git a/chromium/device/generic_sensor/linux/sensor_device_manager.h b/chromium/device/generic_sensor/linux/sensor_device_manager.h index 3715a7912a0..937e8e54e35 100644 --- a/chromium/device/generic_sensor/linux/sensor_device_manager.h +++ b/chromium/device/generic_sensor/linux/sensor_device_manager.h @@ -7,6 +7,7 @@ #include "base/scoped_observer.h" +#include "base/single_thread_task_runner.h" #include "device/base/device_monitor_linux.h" #include "device/generic_sensor/generic_sensor_export.h" #include "device/generic_sensor/public/interfaces/sensor.mojom.h" @@ -68,7 +69,8 @@ class DEVICE_GENERIC_SENSOR_EXPORT SensorDeviceManager // initial enumeration. SensorDeviceMap sensors_by_node_; - base::ThreadChecker thread_checker_; + THREAD_CHECKER(thread_checker_); + ScopedObserver<DeviceMonitorLinux, DeviceMonitorLinux::Observer> observer_; Delegate* delegate_; diff --git a/chromium/device/generic_sensor/platform_sensor.h b/chromium/device/generic_sensor/platform_sensor.h index 2df4ade2b05..94629a552b9 100644 --- a/chromium/device/generic_sensor/platform_sensor.h +++ b/chromium/device/generic_sensor/platform_sensor.h @@ -12,6 +12,7 @@ #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/observer_list.h" +#include "base/single_thread_task_runner.h" #include "device/generic_sensor/generic_sensor_export.h" #include "device/generic_sensor/public/cpp/sensor_reading.h" #include "device/generic_sensor/public/interfaces/sensor.mojom.h" diff --git a/chromium/device/generic_sensor/platform_sensor_accelerometer_mac.cc b/chromium/device/generic_sensor/platform_sensor_accelerometer_mac.cc new file mode 100644 index 00000000000..19a7f2969ef --- /dev/null +++ b/chromium/device/generic_sensor/platform_sensor_accelerometer_mac.cc @@ -0,0 +1,103 @@ +// Copyright 2017 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 "device/generic_sensor/platform_sensor_accelerometer_mac.h" + +#include <stdint.h> + +#include <cmath> + +#include "base/bind.h" +#include "device/base/synchronization/shared_memory_seqlock_buffer.h" +#include "device/generic_sensor/generic_sensor_consts.h" +#include "device/generic_sensor/platform_sensor_provider_mac.h" +#include "third_party/sudden_motion_sensor/sudden_motion_sensor_mac.h" + +namespace { + +constexpr double kMeanGravity = 9.80665; + +constexpr double kGravityThreshold = kMeanGravity * 0.01; + +bool IsSignificantlyDifferent(const device::SensorReading& reading1, + const device::SensorReading& reading2) { + return (std::fabs(reading1.values[0] - reading2.values[0]) >= + kGravityThreshold) || + (std::fabs(reading1.values[1] - reading2.values[1]) >= + kGravityThreshold) || + (std::fabs(reading1.values[2] - reading2.values[2]) >= + kGravityThreshold); +} + +} // namespace + +namespace device { + +PlatformSensorAccelerometerMac::PlatformSensorAccelerometerMac( + mojo::ScopedSharedBufferMapping mapping, + PlatformSensorProvider* provider) + : PlatformSensor(mojom::SensorType::ACCELEROMETER, + std::move(mapping), + provider), + sudden_motion_sensor_(SuddenMotionSensor::Create()) {} + +PlatformSensorAccelerometerMac::~PlatformSensorAccelerometerMac() = default; + +mojom::ReportingMode PlatformSensorAccelerometerMac::GetReportingMode() { + return mojom::ReportingMode::ON_CHANGE; +} + +bool PlatformSensorAccelerometerMac::CheckSensorConfiguration( + const PlatformSensorConfiguration& configuration) { + return configuration.frequency() > 0 && + configuration.frequency() <= + mojom::SensorConfiguration::kMaxAllowedFrequency; +} + +PlatformSensorConfiguration +PlatformSensorAccelerometerMac::GetDefaultConfiguration() { + return PlatformSensorConfiguration(kDefaultAccelerometerFrequencyHz); +} + +bool PlatformSensorAccelerometerMac::StartSensor( + const PlatformSensorConfiguration& configuration) { + if (!sudden_motion_sensor_) + return false; + + float axis_value[3]; + if (!sudden_motion_sensor_->ReadSensorValues(axis_value)) + return false; + + timer_.Start( + FROM_HERE, + base::TimeDelta::FromMicroseconds(base::Time::kMicrosecondsPerSecond / + configuration.frequency()), + this, &PlatformSensorAccelerometerMac::PollForData); + + return true; +} + +void PlatformSensorAccelerometerMac::StopSensor() { + timer_.Stop(); +} + +void PlatformSensorAccelerometerMac::PollForData() { + // Retrieve per-axis calibrated values. + float axis_value[3]; + if (!sudden_motion_sensor_->ReadSensorValues(axis_value)) + return; + + SensorReading reading; + reading.timestamp = (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF(); + reading.values[0] = axis_value[0] * kMeanGravity; + reading.values[1] = axis_value[1] * kMeanGravity; + reading.values[2] = axis_value[2] * kMeanGravity; + + if (IsSignificantlyDifferent(reading_, reading)) { + reading_ = reading; + UpdateSensorReading(reading, true); + } +} + +} // namespace device diff --git a/chromium/device/generic_sensor/platform_sensor_accelerometer_mac.h b/chromium/device/generic_sensor/platform_sensor_accelerometer_mac.h new file mode 100644 index 00000000000..02e08b5d1a8 --- /dev/null +++ b/chromium/device/generic_sensor/platform_sensor_accelerometer_mac.h @@ -0,0 +1,55 @@ +// Copyright 2017 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 DEVICE_GENERIC_SENSOR_PLATFORM_SENSOR_ACCELEROMETER_MAC_H_ +#define DEVICE_GENERIC_SENSOR_PLATFORM_SENSOR_ACCELEROMETER_MAC_H_ + +#include <memory> + +#include "base/timer/timer.h" +#include "device/generic_sensor/platform_sensor.h" + +class SuddenMotionSensor; + +namespace device { + +// Implementation of PlatformSensor for macOS to query the accelerometer +// sensor. +// This is a single instance object per browser process which is created by +// The singleton PlatformSensorProviderMac. If there are no clients, this +// instance is not created. +class PlatformSensorAccelerometerMac : public PlatformSensor { + public: + // Construct a platform sensor of type ACCELEROMETER, given a buffer |mapping| + // where readings will be written. + PlatformSensorAccelerometerMac(mojo::ScopedSharedBufferMapping mapping, + PlatformSensorProvider* provider); + + mojom::ReportingMode GetReportingMode() override; + // Can only be called once, the first time or after a StopSensor call. + bool StartSensor(const PlatformSensorConfiguration& configuration) override; + void StopSensor() override; + + protected: + ~PlatformSensorAccelerometerMac() override; + bool CheckSensorConfiguration( + const PlatformSensorConfiguration& configuration) override; + PlatformSensorConfiguration GetDefaultConfiguration() override; + + private: + void PollForData(); + + std::unique_ptr<SuddenMotionSensor> sudden_motion_sensor_; + + SensorReading reading_; + + // Repeating timer for data polling. + base::RepeatingTimer timer_; + + DISALLOW_COPY_AND_ASSIGN(PlatformSensorAccelerometerMac); +}; + +} // namespace device + +#endif // DEVICE_GENERIC_SENSOR_PLATFORM_SENSOR_ACCELEROMETER_MAC_H_ diff --git a/chromium/device/generic_sensor/platform_sensor_ambient_light_mac.cc b/chromium/device/generic_sensor/platform_sensor_ambient_light_mac.cc index e96299e4db0..8a72acf7d6d 100644 --- a/chromium/device/generic_sensor/platform_sensor_ambient_light_mac.cc +++ b/chromium/device/generic_sensor/platform_sensor_ambient_light_mac.cc @@ -4,13 +4,41 @@ #include "device/generic_sensor/platform_sensor_ambient_light_mac.h" +#include <stdint.h> + #include <IOKit/IOMessage.h> #include "base/bind.h" #include "device/base/synchronization/shared_memory_seqlock_buffer.h" +#include "device/generic_sensor/generic_sensor_consts.h" #include "device/generic_sensor/platform_sensor_provider_mac.h" -#include "device/sensors/public/cpp/device_sensors_consts.h" -#include "device/sensors/public/cpp/device_util_mac.h" + +namespace { + +// Convert the value returned by the ambient light LMU sensor on Mac +// hardware to a lux value. +double LMUvalueToLux(uint64_t raw_value) { + // Conversion formula from regression. + // https://bugzilla.mozilla.org/show_bug.cgi?id=793728 + // Let x = raw_value, then + // lux = -2.978303814*(10^-27)*x^4 + 2.635687683*(10^-19)*x^3 - + // 3.459747434*(10^-12)*x^2 + 3.905829689*(10^-5)*x - 0.1932594532 + + static const long double k4 = pow(10.L, -7); + static const long double k3 = pow(10.L, -4); + static const long double k2 = pow(10.L, -2); + static const long double k1 = pow(10.L, 5); + long double scaled_value = raw_value / k1; + + long double lux_value = + (-3 * k4 * pow(scaled_value, 4)) + (2.6 * k3 * pow(scaled_value, 3)) + + (-3.4 * k2 * pow(scaled_value, 2)) + (3.9 * scaled_value) - 0.19; + + double lux = ceil(static_cast<double>(lux_value)); + return lux > 0 ? lux : 0; +} + +} // namespace namespace device { @@ -19,14 +47,13 @@ enum LmuFunctionIndex { }; PlatformSensorAmbientLightMac::PlatformSensorAmbientLightMac( - mojom::SensorType type, mojo::ScopedSharedBufferMapping mapping, PlatformSensorProvider* provider) - : PlatformSensor(type, std::move(mapping), provider), + : PlatformSensor(mojom::SensorType::AMBIENT_LIGHT, + std::move(mapping), + provider), light_sensor_port_(nullptr), - current_lux_(0.0) { - DCHECK_EQ(type, mojom::SensorType::AMBIENT_LIGHT); -} + current_lux_(0.0) {} PlatformSensorAmbientLightMac::~PlatformSensorAmbientLightMac() = default; diff --git a/chromium/device/generic_sensor/platform_sensor_ambient_light_mac.h b/chromium/device/generic_sensor/platform_sensor_ambient_light_mac.h index a056b8b29d9..649b32ec3ea 100644 --- a/chromium/device/generic_sensor/platform_sensor_ambient_light_mac.h +++ b/chromium/device/generic_sensor/platform_sensor_ambient_light_mac.h @@ -19,11 +19,9 @@ namespace device { // instance is not created. class PlatformSensorAmbientLightMac : public PlatformSensor { public: - // Construct a platform sensor of |type| AMBIENT_LIGHT, given - // a buffer |mapping| to write the result back. |task_runner| is - // used to post the notification that the sensor reading has changed. - PlatformSensorAmbientLightMac(mojom::SensorType type, - mojo::ScopedSharedBufferMapping mapping, + // Construct a platform sensor of AMBIENT_LIGHT, given a buffer |mapping| + // to write the result back. + PlatformSensorAmbientLightMac(mojo::ScopedSharedBufferMapping mapping, PlatformSensorProvider* provider); mojom::ReportingMode GetReportingMode() override; diff --git a/chromium/device/generic_sensor/platform_sensor_and_provider_unittest_win.cc b/chromium/device/generic_sensor/platform_sensor_and_provider_unittest_win.cc index 2913d65b83e..fbe917fe68b 100644 --- a/chromium/device/generic_sensor/platform_sensor_and_provider_unittest_win.cc +++ b/chromium/device/generic_sensor/platform_sensor_and_provider_unittest_win.cc @@ -3,8 +3,9 @@ // found in the LICENSE file. #include <SensorsApi.h> -#include <Sensors.h> // NOLINT -#include <Propvarutil.h> // NOLINT +#include <objbase.h> +#include <propvarutil.h> +#include <sensors.h> #include "base/bind.h" #include "base/memory/ptr_util.h" @@ -193,8 +194,7 @@ class PlatformSensorAndProviderTestWin : public ::testing::Test { sensor_collection_ = new NiceMock<MockISensorCollection>(); sensor_manager_ = new NiceMock<MockISensorManager>(); base::win::ScopedComPtr<ISensorManager> manager; - sensor_manager_->QueryInterface(__uuidof(ISensorManager), - manager.ReceiveVoid()); + sensor_manager_->QueryInterface(IID_PPV_ARGS(&manager)); // Overrides default ISensorManager with mocked interface. PlatformSensorProviderWin::GetInstance()->SetSensorManagerForTesting( @@ -351,8 +351,7 @@ class PlatformSensorAndProviderTestWin : public ::testing::Test { // it when there are not more references. auto* mock_report = new NiceMock<MockISensorDataReport>(); base::win::ScopedComPtr<ISensorDataReport> data_report; - mock_report->QueryInterface(__uuidof(ISensorDataReport), - data_report.ReceiveVoid()); + mock_report->QueryInterface(IID_PPV_ARGS(&data_report)); EXPECT_CALL(*mock_report, GetTimestamp(_)) .WillOnce(Invoke([](SYSTEMTIME* timestamp) { @@ -371,7 +370,7 @@ class PlatformSensorAndProviderTestWin : public ::testing::Test { return S_OK; }))); - sensor_events_->OnDataUpdated(sensor_.get(), data_report.get()); + sensor_events_->OnDataUpdated(sensor_.get(), data_report.Get()); } scoped_refptr<MockISensorManager> sensor_manager_; diff --git a/chromium/device/generic_sensor/platform_sensor_android.cc b/chromium/device/generic_sensor/platform_sensor_android.cc index c2e0c87f2bd..10e3f6c1383 100644 --- a/chromium/device/generic_sensor/platform_sensor_android.cc +++ b/chromium/device/generic_sensor/platform_sensor_android.cc @@ -4,7 +4,6 @@ #include "device/generic_sensor/platform_sensor_android.h" -#include "base/android/context_utils.h" #include "base/bind.h" #include "jni/PlatformSensor_jni.h" diff --git a/chromium/device/generic_sensor/platform_sensor_linux.cc b/chromium/device/generic_sensor/platform_sensor_linux.cc index 3a6bcab600d..5d3e07bdeaf 100644 --- a/chromium/device/generic_sensor/platform_sensor_linux.cc +++ b/chromium/device/generic_sensor/platform_sensor_linux.cc @@ -4,6 +4,7 @@ #include "device/generic_sensor/platform_sensor_linux.h" +#include "base/single_thread_task_runner.h" #include "device/generic_sensor/linux/sensor_data_linux.h" #include "device/generic_sensor/platform_sensor_reader_linux.h" diff --git a/chromium/device/generic_sensor/platform_sensor_provider_android.cc b/chromium/device/generic_sensor/platform_sensor_provider_android.cc index df361c835db..05a008a2cfb 100644 --- a/chromium/device/generic_sensor/platform_sensor_provider_android.cc +++ b/chromium/device/generic_sensor/platform_sensor_provider_android.cc @@ -4,7 +4,6 @@ #include "device/generic_sensor/platform_sensor_provider_android.h" -#include "base/android/context_utils.h" #include "base/android/scoped_java_ref.h" #include "base/memory/singleton.h" #include "device/generic_sensor/platform_sensor_android.h" @@ -24,8 +23,7 @@ PlatformSensorProviderAndroid* PlatformSensorProviderAndroid::GetInstance() { PlatformSensorProviderAndroid::PlatformSensorProviderAndroid() { JNIEnv* env = AttachCurrentThread(); - j_object_.Reset(Java_PlatformSensorProvider_create( - env, base::android::GetApplicationContext())); + j_object_.Reset(Java_PlatformSensorProvider_create(env)); } PlatformSensorProviderAndroid::~PlatformSensorProviderAndroid() = default; diff --git a/chromium/device/generic_sensor/platform_sensor_provider_base.cc b/chromium/device/generic_sensor/platform_sensor_provider_base.cc index f8bb907f0f2..8af22ed5891 100644 --- a/chromium/device/generic_sensor/platform_sensor_provider_base.cc +++ b/chromium/device/generic_sensor/platform_sensor_provider_base.cc @@ -20,12 +20,15 @@ const uint64_t kSharedBufferSizeInBytes = } // namespace PlatformSensorProviderBase::PlatformSensorProviderBase() = default; -PlatformSensorProviderBase::~PlatformSensorProviderBase() = default; + +PlatformSensorProviderBase::~PlatformSensorProviderBase() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); +} void PlatformSensorProviderBase::CreateSensor( mojom::SensorType type, const CreateSensorCallback& callback) { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); if (!CreateSharedBufferIfNeeded()) { callback.Run(nullptr); @@ -53,7 +56,7 @@ void PlatformSensorProviderBase::CreateSensor( scoped_refptr<PlatformSensor> PlatformSensorProviderBase::GetSensor( mojom::SensorType type) { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); auto it = sensor_map_.find(type); if (it != sensor_map_.end()) @@ -62,7 +65,7 @@ scoped_refptr<PlatformSensor> PlatformSensorProviderBase::GetSensor( } bool PlatformSensorProviderBase::CreateSharedBufferIfNeeded() { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); if (shared_buffer_handle_.is_valid()) return true; @@ -72,7 +75,7 @@ bool PlatformSensorProviderBase::CreateSharedBufferIfNeeded() { } void PlatformSensorProviderBase::RemoveSensor(mojom::SensorType type) { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(ContainsKey(sensor_map_, type)); sensor_map_.erase(type); @@ -84,21 +87,21 @@ void PlatformSensorProviderBase::RemoveSensor(mojom::SensorType type) { mojo::ScopedSharedBufferHandle PlatformSensorProviderBase::CloneSharedBufferHandle() { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); CreateSharedBufferIfNeeded(); return shared_buffer_handle_->Clone( mojo::SharedBufferHandle::AccessMode::READ_ONLY); } bool PlatformSensorProviderBase::HasSensors() const { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); return !sensor_map_.empty(); } void PlatformSensorProviderBase::NotifySensorCreated( mojom::SensorType type, scoped_refptr<PlatformSensor> sensor) { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(!ContainsKey(sensor_map_, type)); DCHECK(ContainsKey(requests_map_, type)); diff --git a/chromium/device/generic_sensor/platform_sensor_provider_base.h b/chromium/device/generic_sensor/platform_sensor_provider_base.h index ee2d233c49b..c38443bee89 100644 --- a/chromium/device/generic_sensor/platform_sensor_provider_base.h +++ b/chromium/device/generic_sensor/platform_sensor_provider_base.h @@ -7,7 +7,8 @@ #include "base/macros.h" -#include "base/threading/non_thread_safe.h" +#include "base/single_thread_task_runner.h" +#include "base/threading/thread_checker.h" #include "device/generic_sensor/generic_sensor_export.h" #include "device/generic_sensor/platform_sensor.h" @@ -15,8 +16,7 @@ namespace device { // Base class that defines factory methods for PlatformSensor creation. // Its implementations must be accessed via GetInstance() method. -class DEVICE_GENERIC_SENSOR_EXPORT PlatformSensorProviderBase - : public base::NonThreadSafe { +class DEVICE_GENERIC_SENSOR_EXPORT PlatformSensorProviderBase { public: using CreateSensorCallback = base::Callback<void(scoped_refptr<PlatformSensor>)>; @@ -61,6 +61,8 @@ class DEVICE_GENERIC_SENSOR_EXPORT PlatformSensorProviderBase mojo::ScopedSharedBufferMapping MapSharedBufferForType( mojom::SensorType type); + THREAD_CHECKER(thread_checker_); + private: friend class PlatformSensor; // To call RemoveSensor(); diff --git a/chromium/device/generic_sensor/platform_sensor_provider_linux.cc b/chromium/device/generic_sensor/platform_sensor_provider_linux.cc index 7049b615538..4db2a4c97e4 100644 --- a/chromium/device/generic_sensor/platform_sensor_provider_linux.cc +++ b/chromium/device/generic_sensor/platform_sensor_provider_linux.cc @@ -5,6 +5,7 @@ #include "device/generic_sensor/platform_sensor_provider_linux.h" #include "base/memory/singleton.h" +#include "base/message_loop/message_loop.h" #include "base/task_runner_util.h" #include "base/threading/thread.h" #include "device/generic_sensor/linux/sensor_data_linux.h" @@ -62,7 +63,7 @@ void PlatformSensorProviderLinux::SensorDeviceFound( mojo::ScopedSharedBufferMapping mapping, const PlatformSensorProviderBase::CreateSensorCallback& callback, const SensorInfoLinux* sensor_device) { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(sensor_device); if (!StartPollingThread()) { @@ -78,13 +79,13 @@ void PlatformSensorProviderLinux::SensorDeviceFound( void PlatformSensorProviderLinux::SetFileTaskRunner( scoped_refptr<base::SingleThreadTaskRunner> file_task_runner) { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); if (!file_task_runner_) file_task_runner_ = file_task_runner; } void PlatformSensorProviderLinux::AllSensorsRemoved() { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(file_task_runner_); Shutdown(); // When there are no sensors left, the polling thread must be stopped. @@ -114,7 +115,7 @@ void PlatformSensorProviderLinux::StopPollingThread() { } void PlatformSensorProviderLinux::Shutdown() { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); const bool did_post_task = file_task_runner_->DeleteSoon( FROM_HERE, sensor_device_manager_.release()); DCHECK(did_post_task); @@ -125,7 +126,7 @@ void PlatformSensorProviderLinux::Shutdown() { SensorInfoLinux* PlatformSensorProviderLinux::GetSensorDevice( mojom::SensorType type) { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); auto sensor = sensor_devices_by_type_.find(type); if (sensor == sensor_devices_by_type_.end()) return nullptr; @@ -133,26 +134,26 @@ SensorInfoLinux* PlatformSensorProviderLinux::GetSensorDevice( } void PlatformSensorProviderLinux::GetAllSensorDevices() { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); // TODO(maksims): implement this method once we have discovery API. NOTIMPLEMENTED(); } void PlatformSensorProviderLinux::SetSensorDeviceManagerForTesting( std::unique_ptr<SensorDeviceManager> sensor_device_manager) { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); Shutdown(); sensor_device_manager_ = std::move(sensor_device_manager); } void PlatformSensorProviderLinux::SetFileTaskRunnerForTesting( scoped_refptr<base::SingleThreadTaskRunner> task_runner) { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); file_task_runner_ = std::move(task_runner); } void PlatformSensorProviderLinux::ProcessStoredRequests() { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); std::vector<mojom::SensorType> request_types = GetPendingRequestTypes(); if (request_types.empty()) return; @@ -169,7 +170,7 @@ void PlatformSensorProviderLinux::ProcessStoredRequests() { void PlatformSensorProviderLinux::CreateSensorAndNotify( mojom::SensorType type, SensorInfoLinux* sensor_device) { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); scoped_refptr<PlatformSensorLinux> sensor; mojo::ScopedSharedBufferMapping mapping = MapSharedBufferForType(type); if (sensor_device && mapping && StartPollingThread()) { @@ -181,7 +182,7 @@ void PlatformSensorProviderLinux::CreateSensorAndNotify( } void PlatformSensorProviderLinux::OnSensorNodesEnumerated() { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(!sensor_nodes_enumerated_); sensor_nodes_enumerated_ = true; ProcessStoredRequests(); @@ -190,7 +191,7 @@ void PlatformSensorProviderLinux::OnSensorNodesEnumerated() { void PlatformSensorProviderLinux::OnDeviceAdded( mojom::SensorType type, std::unique_ptr<SensorInfoLinux> sensor_device) { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); // At the moment, we support only one device per type. if (base::ContainsKey(sensor_devices_by_type_, type)) { DVLOG(1) << "Sensor ignored. Type " << type @@ -203,7 +204,7 @@ void PlatformSensorProviderLinux::OnDeviceAdded( void PlatformSensorProviderLinux::OnDeviceRemoved( mojom::SensorType type, const std::string& device_node) { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); auto it = sensor_devices_by_type_.find(type); if (it != sensor_devices_by_type_.end() && it->second->device_node == device_node) diff --git a/chromium/device/generic_sensor/platform_sensor_provider_linux.h b/chromium/device/generic_sensor/platform_sensor_provider_linux.h index 3d36de4fab1..5bde10fbb38 100644 --- a/chromium/device/generic_sensor/platform_sensor_provider_linux.h +++ b/chromium/device/generic_sensor/platform_sensor_provider_linux.h @@ -7,6 +7,7 @@ #include "device/generic_sensor/platform_sensor_provider.h" +#include "base/single_thread_task_runner.h" #include "device/generic_sensor/generic_sensor_export.h" #include "device/generic_sensor/linux/sensor_device_manager.h" diff --git a/chromium/device/generic_sensor/platform_sensor_provider_mac.cc b/chromium/device/generic_sensor/platform_sensor_provider_mac.cc index 777cda0bab7..f88a34d4717 100644 --- a/chromium/device/generic_sensor/platform_sensor_provider_mac.cc +++ b/chromium/device/generic_sensor/platform_sensor_provider_mac.cc @@ -5,6 +5,7 @@ #include "device/generic_sensor/platform_sensor_provider_mac.h" #include "base/memory/singleton.h" +#include "device/generic_sensor/platform_sensor_accelerometer_mac.h" #include "device/generic_sensor/platform_sensor_ambient_light_mac.h" namespace device { @@ -28,10 +29,15 @@ void PlatformSensorProviderMac::CreateSensorInternal( switch (type) { case mojom::SensorType::AMBIENT_LIGHT: { scoped_refptr<PlatformSensor> sensor = - new PlatformSensorAmbientLightMac(type, std::move(mapping), this); + new PlatformSensorAmbientLightMac(std::move(mapping), this); callback.Run(std::move(sensor)); break; } + case mojom::SensorType::ACCELEROMETER: { + callback.Run(base::MakeRefCounted<PlatformSensorAccelerometerMac>( + std::move(mapping), this)); + break; + } default: NOTIMPLEMENTED(); callback.Run(nullptr); diff --git a/chromium/device/generic_sensor/platform_sensor_provider_unittest.cc b/chromium/device/generic_sensor/platform_sensor_provider_unittest.cc index 35e5019977f..4b20c2eadff 100644 --- a/chromium/device/generic_sensor/platform_sensor_provider_unittest.cc +++ b/chromium/device/generic_sensor/platform_sensor_provider_unittest.cc @@ -105,35 +105,77 @@ class PlatformSensorProviderTest : public ::testing::Test { }; TEST_F(PlatformSensorProviderTest, CreateSensorsAndCheckType) { - TestSensorCreateCallback callback1; - scoped_refptr<PlatformSensor> sensor1 = - CreateSensor(SensorType::AMBIENT_LIGHT, &callback1); - EXPECT_TRUE(sensor1); - EXPECT_EQ(SensorType::AMBIENT_LIGHT, sensor1->GetType()); + { + TestSensorCreateCallback callback; + scoped_refptr<PlatformSensor> sensor = + CreateSensor(SensorType::AMBIENT_LIGHT, &callback); + EXPECT_TRUE(sensor); + EXPECT_EQ(SensorType::AMBIENT_LIGHT, sensor->GetType()); + } - TestSensorCreateCallback callback2; - scoped_refptr<PlatformSensor> sensor2 = - CreateSensor(SensorType::PROXIMITY, &callback2); - EXPECT_TRUE(sensor2); - EXPECT_EQ(SensorType::PROXIMITY, sensor2->GetType()); + { + TestSensorCreateCallback callback; + scoped_refptr<PlatformSensor> sensor = + CreateSensor(SensorType::PROXIMITY, &callback); + EXPECT_TRUE(sensor); + EXPECT_EQ(SensorType::PROXIMITY, sensor->GetType()); + } - TestSensorCreateCallback callback3; - scoped_refptr<PlatformSensor> sensor3 = - CreateSensor(SensorType::ACCELEROMETER, &callback3); - EXPECT_TRUE(sensor3); - EXPECT_EQ(SensorType::ACCELEROMETER, sensor3->GetType()); - - TestSensorCreateCallback callback4; - scoped_refptr<PlatformSensor> sensor4 = - CreateSensor(SensorType::GYROSCOPE, &callback4); - EXPECT_TRUE(sensor4); - EXPECT_EQ(SensorType::GYROSCOPE, sensor4->GetType()); - - TestSensorCreateCallback callback5; - scoped_refptr<PlatformSensor> sensor5 = - CreateSensor(SensorType::PRESSURE, &callback5); - EXPECT_TRUE(sensor5); - EXPECT_EQ(SensorType::PRESSURE, sensor5->GetType()); + { + TestSensorCreateCallback callback; + scoped_refptr<PlatformSensor> sensor = + CreateSensor(SensorType::ACCELEROMETER, &callback); + EXPECT_TRUE(sensor); + EXPECT_EQ(SensorType::ACCELEROMETER, sensor->GetType()); + } + + { + TestSensorCreateCallback callback; + scoped_refptr<PlatformSensor> sensor = + CreateSensor(SensorType::LINEAR_ACCELERATION, &callback); + EXPECT_TRUE(sensor); + EXPECT_EQ(SensorType::LINEAR_ACCELERATION, sensor->GetType()); + } + + { + TestSensorCreateCallback callback; + scoped_refptr<PlatformSensor> sensor = + CreateSensor(SensorType::GYROSCOPE, &callback); + EXPECT_TRUE(sensor); + EXPECT_EQ(SensorType::GYROSCOPE, sensor->GetType()); + } + + { + TestSensorCreateCallback callback; + scoped_refptr<PlatformSensor> sensor = + CreateSensor(SensorType::MAGNETOMETER, &callback); + EXPECT_TRUE(sensor); + EXPECT_EQ(SensorType::MAGNETOMETER, sensor->GetType()); + } + + { + TestSensorCreateCallback callback; + scoped_refptr<PlatformSensor> sensor = + CreateSensor(SensorType::PRESSURE, &callback); + EXPECT_TRUE(sensor); + EXPECT_EQ(SensorType::PRESSURE, sensor->GetType()); + } + + { + TestSensorCreateCallback callback; + scoped_refptr<PlatformSensor> sensor = + CreateSensor(SensorType::ABSOLUTE_ORIENTATION, &callback); + EXPECT_TRUE(sensor); + EXPECT_EQ(SensorType::ABSOLUTE_ORIENTATION, sensor->GetType()); + } + + { + TestSensorCreateCallback callback; + scoped_refptr<PlatformSensor> sensor = + CreateSensor(SensorType::RELATIVE_ORIENTATION, &callback); + EXPECT_TRUE(sensor); + EXPECT_EQ(SensorType::RELATIVE_ORIENTATION, sensor->GetType()); + } } TEST_F(PlatformSensorProviderTest, CreateAndGetSensor) { diff --git a/chromium/device/generic_sensor/platform_sensor_provider_win.cc b/chromium/device/generic_sensor/platform_sensor_provider_win.cc index 12b4efdd1d8..e8948375a5e 100644 --- a/chromium/device/generic_sensor/platform_sensor_provider_win.cc +++ b/chromium/device/generic_sensor/platform_sensor_provider_win.cc @@ -4,6 +4,8 @@ #include "device/generic_sensor/platform_sensor_provider_win.h" +#include <objbase.h> + #include "base/memory/ptr_util.h" #include "base/memory/singleton.h" #include "base/task_runner_util.h" @@ -31,7 +33,7 @@ void PlatformSensorProviderWin::CreateSensorInternal( mojom::SensorType type, mojo::ScopedSharedBufferMapping mapping, const CreateSensorCallback& callback) { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); if (!StartSensorThread()) { callback.Run(nullptr); return; @@ -50,7 +52,8 @@ bool PlatformSensorProviderWin::InitializeSensorManager() { if (sensor_manager_) return true; - HRESULT hr = sensor_manager_.CreateInstance(CLSID_SensorManager); + HRESULT hr = ::CoCreateInstance(CLSID_SensorManager, nullptr, CLSCTX_ALL, + IID_PPV_ARGS(&sensor_manager_)); return SUCCEEDED(hr); } @@ -81,7 +84,7 @@ void PlatformSensorProviderWin::SensorReaderCreated( mojo::ScopedSharedBufferMapping mapping, const CreateSensorCallback& callback, std::unique_ptr<PlatformSensorReaderWin> sensor_reader) { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); if (!sensor_reader) { callback.Run(nullptr); if (!HasSensors()) diff --git a/chromium/device/generic_sensor/platform_sensor_reader_linux.cc b/chromium/device/generic_sensor/platform_sensor_reader_linux.cc index bd750f38462..a814e878e27 100644 --- a/chromium/device/generic_sensor/platform_sensor_reader_linux.cc +++ b/chromium/device/generic_sensor/platform_sensor_reader_linux.cc @@ -6,6 +6,7 @@ #include "base/files/file_util.h" #include "base/memory/ptr_util.h" +#include "base/single_thread_task_runner.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/threading/thread_restrictions.h" @@ -64,26 +65,26 @@ PollingSensorReader::PollingSensorReader( apply_scaling_func_(sensor_device->apply_scaling_func) {} PollingSensorReader::~PollingSensorReader() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); } void PollingSensorReader::StartFetchingData( const PlatformSensorConfiguration& configuration) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); if (is_reading_active_) StopFetchingData(); InitializeTimer(configuration); } void PollingSensorReader::StopFetchingData() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); is_reading_active_ = false; timer_.Stop(); } void PollingSensorReader::InitializeTimer( const PlatformSensorConfiguration& configuration) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(!is_reading_active_); timer_.Start(FROM_HERE, base::TimeDelta::FromMicroseconds( base::Time::kMicrosecondsPerSecond / @@ -93,7 +94,7 @@ void PollingSensorReader::InitializeTimer( } void PollingSensorReader::PollForData() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); SensorReading readings; DCHECK_LE(sensor_file_paths_.size(), arraysize(readings.values)); @@ -143,15 +144,15 @@ SensorReader::SensorReader( : sensor_(sensor), task_runner_(std::move(task_runner)), is_reading_active_(false) { - thread_checker_.DetachFromThread(); + DETACH_FROM_THREAD(thread_checker_); } SensorReader::~SensorReader() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); } void SensorReader::NotifyReadError() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); if (is_reading_active_) { task_runner_->PostTask( FROM_HERE, diff --git a/chromium/device/generic_sensor/platform_sensor_reader_linux.h b/chromium/device/generic_sensor/platform_sensor_reader_linux.h index ab757200076..c5c1630d14f 100644 --- a/chromium/device/generic_sensor/platform_sensor_reader_linux.h +++ b/chromium/device/generic_sensor/platform_sensor_reader_linux.h @@ -52,7 +52,7 @@ class SensorReader { // In builds with DCHECK enabled checks that methods of this // and derived classes are called on a right thread. - base::ThreadChecker thread_checker_; + THREAD_CHECKER(thread_checker_); // A sensor that this reader is owned by and notifies about errors and // readings to. diff --git a/chromium/device/generic_sensor/platform_sensor_reader_win.cc b/chromium/device/generic_sensor/platform_sensor_reader_win.cc index 814afd7a65b..d158b99f33c 100644 --- a/chromium/device/generic_sensor/platform_sensor_reader_win.cc +++ b/chromium/device/generic_sensor/platform_sensor_reader_win.cc @@ -5,6 +5,7 @@ #include "device/generic_sensor/platform_sensor_reader_win.h" #include <Sensors.h> +#include <objbase.h> #include "base/callback.h" #include "base/memory/ptr_util.h" @@ -22,11 +23,11 @@ namespace device { struct ReaderInitParams { // ISensorDataReport::GetSensorValue is not const, therefore, report // cannot be passed as const ref. - // ISensorDataReport& report - report that contains new sensor data. - // SensorReading& reading - out parameter that must be populated. + // ISensorDataReport* report - report that contains new sensor data. + // SensorReading* reading - out parameter that must be populated. // Returns HRESULT - S_OK on success, otherwise error code. - using ReaderFunctor = base::Callback<HRESULT(ISensorDataReport& report, - SensorReading& reading)>; + using ReaderFunctor = base::Callback<HRESULT(ISensorDataReport* report, + SensorReading* reading)>; SENSOR_TYPE_ID sensor_type_id; ReaderFunctor reader_func; unsigned long min_reporting_interval_ms = 0; @@ -36,11 +37,11 @@ namespace { // Gets value from the report for provided key. bool GetReadingValueForProperty(REFPROPERTYKEY key, - ISensorDataReport& report, + ISensorDataReport* report, double* value) { DCHECK(value); base::win::ScopedPropVariant variant_value; - if (SUCCEEDED(report.GetSensorValue(key, variant_value.Receive()))) { + if (SUCCEEDED(report->GetSensorValue(key, variant_value.Receive()))) { if (variant_value.get().vt == VT_R8) *value = variant_value.get().dblVal; else if (variant_value.get().vt == VT_R4) @@ -59,13 +60,13 @@ std::unique_ptr<ReaderInitParams> CreateAmbientLightReaderInitParams() { auto params = base::MakeUnique<ReaderInitParams>(); params->sensor_type_id = SENSOR_TYPE_AMBIENT_LIGHT; params->reader_func = - base::Bind([](ISensorDataReport& report, SensorReading& reading) { + base::Bind([](ISensorDataReport* report, SensorReading* reading) { double lux = 0.0; if (!GetReadingValueForProperty(SENSOR_DATA_TYPE_LIGHT_LEVEL_LUX, report, &lux)) { return E_FAIL; } - reading.values[0] = lux; + reading->values[0] = lux; return S_OK; }); return params; @@ -76,7 +77,7 @@ std::unique_ptr<ReaderInitParams> CreateAccelerometerReaderInitParams() { auto params = base::MakeUnique<ReaderInitParams>(); params->sensor_type_id = SENSOR_TYPE_ACCELEROMETER_3D; params->reader_func = - base::Bind([](ISensorDataReport& report, SensorReading& reading) { + base::Bind([](ISensorDataReport* report, SensorReading* reading) { double x = 0.0; double y = 0.0; double z = 0.0; @@ -92,9 +93,9 @@ std::unique_ptr<ReaderInitParams> CreateAccelerometerReaderInitParams() { // Windows uses coordinate system where Z axis points down from device // screen, therefore, using right hand notation, we have to reverse // sign for each axis. Values are converted from G/s^2 to m/s^2. - reading.values[0] = -x * kMeanGravity; - reading.values[1] = -y * kMeanGravity; - reading.values[2] = -z * kMeanGravity; + reading->values[0] = -x * kMeanGravity; + reading->values[1] = -y * kMeanGravity; + reading->values[2] = -z * kMeanGravity; return S_OK; }); return params; @@ -104,8 +105,8 @@ std::unique_ptr<ReaderInitParams> CreateAccelerometerReaderInitParams() { std::unique_ptr<ReaderInitParams> CreateGyroscopeReaderInitParams() { auto params = base::MakeUnique<ReaderInitParams>(); params->sensor_type_id = SENSOR_TYPE_GYROMETER_3D; - params->reader_func = base::Bind([](ISensorDataReport& report, - SensorReading& reading) { + params->reader_func = base::Bind([](ISensorDataReport* report, + SensorReading* reading) { double x = 0.0; double y = 0.0; double z = 0.0; @@ -124,9 +125,9 @@ std::unique_ptr<ReaderInitParams> CreateGyroscopeReaderInitParams() { // Windows uses coordinate system where Z axis points down from device // screen, therefore, using right hand notation, we have to reverse // sign for each axis. Values are converted from deg to rad. - reading.values[0] = -x * kRadiansInDegrees; - reading.values[1] = -y * kRadiansInDegrees; - reading.values[2] = -z * kRadiansInDegrees; + reading->values[0] = -x * kRadiansInDegrees; + reading->values[1] = -y * kRadiansInDegrees; + reading->values[2] = -z * kRadiansInDegrees; return S_OK; }); return params; @@ -137,7 +138,7 @@ std::unique_ptr<ReaderInitParams> CreateMagnetometerReaderInitParams() { auto params = base::MakeUnique<ReaderInitParams>(); params->sensor_type_id = SENSOR_TYPE_COMPASS_3D; params->reader_func = - base::Bind([](ISensorDataReport& report, SensorReading& reading) { + base::Bind([](ISensorDataReport* report, SensorReading* reading) { double x = 0.0; double y = 0.0; double z = 0.0; @@ -157,9 +158,9 @@ std::unique_ptr<ReaderInitParams> CreateMagnetometerReaderInitParams() { // screen, therefore, using right hand notation, we have to reverse // sign for each axis. Values are converted from Milligaus to // Microtesla. - reading.values[0] = -x * kMicroteslaInMilligauss; - reading.values[1] = -y * kMicroteslaInMilligauss; - reading.values[2] = -z * kMicroteslaInMilligauss; + reading->values[0] = -x * kMicroteslaInMilligauss; + reading->values[1] = -y * kMicroteslaInMilligauss; + reading->values[2] = -z * kMicroteslaInMilligauss; return S_OK; }); return params; @@ -170,10 +171,10 @@ std::unique_ptr<ReaderInitParams> CreateAbsoluteOrientationReaderInitParams() { auto params = base::MakeUnique<ReaderInitParams>(); params->sensor_type_id = SENSOR_TYPE_AGGREGATED_DEVICE_ORIENTATION; params->reader_func = - base::Bind([](ISensorDataReport& report, SensorReading& reading) { + base::Bind([](ISensorDataReport* report, SensorReading* reading) { base::win::ScopedPropVariant quat_variant; - HRESULT hr = report.GetSensorValue(SENSOR_DATA_TYPE_QUATERNION, - quat_variant.Receive()); + HRESULT hr = report->GetSensorValue(SENSOR_DATA_TYPE_QUATERNION, + quat_variant.Receive()); if (FAILED(hr) || quat_variant.get().vt != (VT_VECTOR | VT_UI1) || quat_variant.get().caub.cElems < 16) { return E_FAIL; @@ -184,10 +185,10 @@ std::unique_ptr<ReaderInitParams> CreateAbsoluteOrientationReaderInitParams() { // Windows uses coordinate system where Z axis points down from device // screen, therefore, using right hand notation, we have to reverse // sign for each quaternion component. - reading.values[0] = -quat[0]; // x*sin(Theta/2) - reading.values[1] = -quat[1]; // y*sin(Theta/2) - reading.values[2] = -quat[2]; // z*sin(Theta/2) - reading.values[3] = quat[3]; // cos(Theta/2) + reading->values[0] = -quat[0]; // x*sin(Theta/2) + reading->values[1] = -quat[1]; // y*sin(Theta/2) + reading->values[2] = -quat[2]; // z*sin(Theta/2) + reading->values[3] = quat[3]; // cos(Theta/2) return S_OK; }); return params; @@ -309,7 +310,7 @@ class EventListener : public ISensorEvents, public base::win::IUnknownImpl { if (last_sensor_reading_.timestamp > reading.timestamp) return E_FAIL; - hr = platform_sensor_reader_->SensorReadingChanged(*report, reading); + hr = platform_sensor_reader_->SensorReadingChanged(report, &reading); if (SUCCEEDED(hr)) last_sensor_reading_ = reading; return hr; @@ -357,15 +358,15 @@ base::win::ScopedComPtr<ISensor> PlatformSensorReaderWin::GetSensorForType( base::win::ScopedComPtr<ISensorManager> sensor_manager) { base::win::ScopedComPtr<ISensor> sensor; base::win::ScopedComPtr<ISensorCollection> sensor_collection; - HRESULT hr = sensor_manager->GetSensorsByType(sensor_type, - sensor_collection.Receive()); + HRESULT hr = sensor_manager->GetSensorsByType( + sensor_type, sensor_collection.GetAddressOf()); if (FAILED(hr) || !sensor_collection) return sensor; ULONG count = 0; hr = sensor_collection->GetCount(&count); if (SUCCEEDED(hr) && count > 0) - sensor_collection->GetAt(0, sensor.Receive()); + sensor_collection->GetAt(0, sensor.GetAddressOf()); return sensor; } @@ -430,7 +431,8 @@ void PlatformSensorReaderWin::ListenSensorEvent() { bool PlatformSensorReaderWin::SetReportingInterval( const PlatformSensorConfiguration& configuration) { base::win::ScopedComPtr<IPortableDeviceValues> props; - if (SUCCEEDED(props.CreateInstance(CLSID_PortableDeviceValues))) { + if (SUCCEEDED(::CoCreateInstance(CLSID_PortableDeviceValues, nullptr, + CLSCTX_ALL, IID_PPV_ARGS(&props)))) { unsigned interval = (1 / configuration.frequency()) * base::Time::kMillisecondsPerSecond; @@ -439,7 +441,7 @@ bool PlatformSensorReaderWin::SetReportingInterval( if (SUCCEEDED(hr)) { base::win::ScopedComPtr<IPortableDeviceValues> return_props; - hr = sensor_->SetProperties(props.get(), return_props.Receive()); + hr = sensor_->SetProperties(props.Get(), return_props.GetAddressOf()); return SUCCEEDED(hr); } } @@ -447,14 +449,14 @@ bool PlatformSensorReaderWin::SetReportingInterval( } HRESULT PlatformSensorReaderWin::SensorReadingChanged( - ISensorDataReport& report, - SensorReading& reading) const { + ISensorDataReport* report, + SensorReading* reading) const { if (!client_) return E_FAIL; HRESULT hr = init_params_->reader_func.Run(report, reading); if (SUCCEEDED(hr)) - client_->OnReadingUpdated(reading); + client_->OnReadingUpdated(*reading); return hr; } diff --git a/chromium/device/generic_sensor/platform_sensor_reader_win.h b/chromium/device/generic_sensor/platform_sensor_reader_win.h index 67018a4adf5..64fb3c8422a 100644 --- a/chromium/device/generic_sensor/platform_sensor_reader_win.h +++ b/chromium/device/generic_sensor/platform_sensor_reader_win.h @@ -55,8 +55,8 @@ class PlatformSensorReaderWin { bool SetReportingInterval(const PlatformSensorConfiguration& configuration); void ListenSensorEvent(); - HRESULT SensorReadingChanged(ISensorDataReport& report, - SensorReading& reading) const; + HRESULT SensorReadingChanged(ISensorDataReport* report, + SensorReading* reading) const; void SensorError(); private: diff --git a/chromium/device/generic_sensor/platform_sensor_win.cc b/chromium/device/generic_sensor/platform_sensor_win.cc index a3e82cbddb8..65cf562eeac 100644 --- a/chromium/device/generic_sensor/platform_sensor_win.cc +++ b/chromium/device/generic_sensor/platform_sensor_win.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "device/generic_sensor/platform_sensor_win.h" +#include "base/single_thread_task_runner.h" namespace device { diff --git a/chromium/device/generic_sensor/public/cpp/sensor_reading.h b/chromium/device/generic_sensor/public/cpp/sensor_reading.h index 81e2f76822c..a7048f7a9a3 100644 --- a/chromium/device/generic_sensor/public/cpp/sensor_reading.h +++ b/chromium/device/generic_sensor/public/cpp/sensor_reading.h @@ -46,6 +46,56 @@ struct DEVICE_GENERIC_SENSOR_PUBLIC_EXPORT SensorReading { SensorReading(const SensorReading& other); SensorReadingField<double> timestamp; constexpr static int kValuesCount = 4; + // AMBIENT_LIGHT: + // values[0]: ambient light level in SI lux units. + // + // PROXIMITY: + // values[0]: proximity sensor distance measured in centimeters. + // + // ACCELEROMETER: + // values[0]: acceleration minus Gx on the x-axis. + // values[1]: acceleration minus Gy on the y-axis. + // values[2]: acceleration minus Gz on the z-axis. + // + // LINEAR_ACCELERATION: + // values[0]: acceleration on the x-axis. + // values[1]: acceleration on the y-axis. + // values[2]: acceleration on the z-axis. + // + // GYROSCOPE: + // values[0]: angular speed around the x-axis. + // values[1]: angular speed around the y-axis. + // values[2]: angular speed around the z-axis. + // + // MAGNETOMETER: + // values[0]: ambient magnetic field in the x-axis in micro-Tesla (uT). + // values[1]: ambient magnetic field in the y-axis in micro-Tesla (uT). + // values[2]: ambient magnetic field in the z-axis in micro-Tesla (uT). + // + // PRESSURE: + // values[0]: atmospheric pressure in hPa (millibar). + // + // ABSOLUTE_ORIENTATION: + // values[0]: x value of a quaternion representing the orientation of the + // device in 3D space. + // values[1]: y value of a quaternion representing the orientation of the + // device in 3D space. + // values[2]: z value of a quaternion representing the orientation of the + // device in 3D space. + // values[3]: w value of a quaternion representing the orientation of the + // device in 3D space. + // + // RELATIVE_ORIENTATION: + // (Identical to ABSOLUTE_ORIENTATION except that it doesn't use the + // geomagnetic field.) + // values[0]: x value of a quaternion representing the orientation of the + // device in 3D space. + // values[1]: y value of a quaternion representing the orientation of the + // device in 3D space. + // values[2]: z value of a quaternion representing the orientation of the + // device in 3D space. + // values[3]: w value of a quaternion representing the orientation of the + // device in 3D space. SensorReadingField<double> values[kValuesCount]; }; diff --git a/chromium/device/generic_sensor/public/interfaces/BUILD.gn b/chromium/device/generic_sensor/public/interfaces/BUILD.gn index 8093ccaf4f7..24aabe84cb4 100644 --- a/chromium/device/generic_sensor/public/interfaces/BUILD.gn +++ b/chromium/device/generic_sensor/public/interfaces/BUILD.gn @@ -7,6 +7,7 @@ import("//mojo/public/tools/bindings/mojom.gni") mojom("interfaces") { visibility = [ "//device/generic_sensor/public/cpp" ] visibility_blink = [ "//third_party/WebKit/Source/*" ] + component_output_prefix = "generic_sensor_public_interfaces" export_class_attribute = "DEVICE_GENERIC_SENSOR_PUBLIC_EXPORT" export_define = "DEVICE_GENERIC_SENSOR_PUBLIC_IMPLEMENTATION=1" export_header = @@ -15,4 +16,7 @@ mojom("interfaces") { "sensor.mojom", "sensor_provider.mojom", ] + + # TODO(crbug.com/714018): Convert the implementation to use OnceCallback. + use_once_callback = false } diff --git a/chromium/device/generic_sensor/public/interfaces/sensor.mojom b/chromium/device/generic_sensor/public/interfaces/sensor.mojom index 3a6bfb530c9..533272a84ba 100644 --- a/chromium/device/generic_sensor/public/interfaces/sensor.mojom +++ b/chromium/device/generic_sensor/public/interfaces/sensor.mojom @@ -5,6 +5,8 @@ module device.mojom; // Types of supported sensors +// When adding new sensor type, update the documentation of sensor data values +// in SensorReading struct at sensor_reading.h file. enum SensorType { FIRST = 1, AMBIENT_LIGHT = FIRST, @@ -15,7 +17,8 @@ enum SensorType { MAGNETOMETER, PRESSURE, ABSOLUTE_ORIENTATION, - LAST = ABSOLUTE_ORIENTATION // Note: LAST is also equal to the types count. + RELATIVE_ORIENTATION, + LAST = RELATIVE_ORIENTATION // Note: LAST is also equal to the types count. }; // Reporting mode supported by the Sensor. diff --git a/chromium/device/generic_sensor/sensor_provider_impl.h b/chromium/device/generic_sensor/sensor_provider_impl.h index eb77ae5293b..3435f12351c 100644 --- a/chromium/device/generic_sensor/sensor_provider_impl.h +++ b/chromium/device/generic_sensor/sensor_provider_impl.h @@ -6,6 +6,7 @@ #define DEVICE_GENERIC_SENSOR_SENSOR_PROVIDER_IMPL_H_ #include "base/macros.h" +#include "base/single_thread_task_runner.h" #include "device/generic_sensor/generic_sensor_export.h" #include "device/generic_sensor/public/interfaces/sensor_provider.mojom.h" diff --git a/chromium/device/geolocation/BUILD.gn b/chromium/device/geolocation/BUILD.gn index 19ba0bf135b..51b12846c8e 100644 --- a/chromium/device/geolocation/BUILD.gn +++ b/chromium/device/geolocation/BUILD.gn @@ -5,6 +5,7 @@ import("//build/config/features.gni") if (is_android) { + import("//build/config/android/config.gni") import("//build/config/android/rules.gni") # For generate_jni(). } @@ -127,11 +128,15 @@ if (is_android) { "android/java/src/org/chromium/device/geolocation/LocationProviderAdapter.java", "android/java/src/org/chromium/device/geolocation/LocationProviderAndroid.java", "android/java/src/org/chromium/device/geolocation/LocationProviderFactory.java", + "android/java/src/org/chromium/device/geolocation/LocationProviderGmsCore.java", ] deps = [ ":geolocation", ":geolocation_jni_headers", + "$google_play_services_package:google_play_services_base_java", + "$google_play_services_package:google_play_services_basement_java", + "$google_play_services_package:google_play_services_location_java", "//base:base_java", ] } diff --git a/chromium/device/geolocation/OWNERS b/chromium/device/geolocation/OWNERS index 0e2f7ccee04..9a6b2e1b369 100644 --- a/chromium/device/geolocation/OWNERS +++ b/chromium/device/geolocation/OWNERS @@ -1,4 +1,5 @@ mcasas@chromium.org timvolodine@chromium.org +# TEAM: device-dev@chromium.org # COMPONENT: Blink>Location diff --git a/chromium/device/geolocation/geolocation_provider_impl_unittest.cc b/chromium/device/geolocation/geolocation_provider_impl_unittest.cc index 1ba82a56f97..190c34859e3 100644 --- a/chromium/device/geolocation/geolocation_provider_impl_unittest.cc +++ b/chromium/device/geolocation/geolocation_provider_impl_unittest.cc @@ -13,9 +13,12 @@ #include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/memory/ref_counted.h" +#include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/single_thread_task_runner.h" #include "base/strings/string16.h" +#include "base/test/scoped_task_environment.h" +#include "base/threading/thread_checker.h" #include "base/time/time.h" #include "device/geolocation/access_token_store.h" #include "device/geolocation/fake_location_provider.h" @@ -98,7 +101,10 @@ void DummyFunction(const LocationProvider* provider, class GeolocationProviderTest : public testing::Test { protected: - GeolocationProviderTest() : arbitrator_(new FakeLocationProvider) { + GeolocationProviderTest() + : scoped_task_environment_( + base::test::ScopedTaskEnvironment::MainThreadType::UI), + arbitrator_(new FakeLocationProvider) { provider()->SetArbitratorForTesting(base::WrapUnique(arbitrator_)); } @@ -123,7 +129,9 @@ class GeolocationProviderTest : public testing::Test { // test completes. base::ShadowingAtExitManager at_exit_; - base::MessageLoopForUI message_loop_; + base::test::ScopedTaskEnvironment scoped_task_environment_; + + base::ThreadChecker thread_checker_; // Owned by the GeolocationProviderImpl class. FakeLocationProvider* arbitrator_; @@ -136,7 +144,7 @@ class GeolocationProviderTest : public testing::Test { bool GeolocationProviderTest::ProvidersStarted() { DCHECK(provider()->IsRunning()); - DCHECK(base::MessageLoop::current() == &message_loop_); + DCHECK(thread_checker_.CalledOnValidThread()); provider()->task_runner()->PostTaskAndReply( FROM_HERE, base::Bind(&GeolocationProviderTest::GetProvidersStarted, @@ -153,7 +161,7 @@ void GeolocationProviderTest::GetProvidersStarted() { void GeolocationProviderTest::SendMockLocation(const Geoposition& position) { DCHECK(provider()->IsRunning()); - DCHECK(base::MessageLoop::current() == &message_loop_); + DCHECK(thread_checker_.CalledOnValidThread()); provider()->task_runner()->PostTask( FROM_HERE, base::Bind(&GeolocationProviderImpl::OnLocationUpdate, diff --git a/chromium/device/geolocation/geolocation_service_context.cc b/chromium/device/geolocation/geolocation_service_context.cc index b1bb14bd9f5..c8546a44358 100644 --- a/chromium/device/geolocation/geolocation_service_context.cc +++ b/chromium/device/geolocation/geolocation_service_context.cc @@ -16,7 +16,8 @@ GeolocationServiceContext::GeolocationServiceContext() {} GeolocationServiceContext::~GeolocationServiceContext() {} void GeolocationServiceContext::CreateService( - mojo::InterfaceRequest<mojom::GeolocationService> request) { + const service_manager::BindSourceInfo& source_info, + mojom::GeolocationServiceRequest request) { GeolocationServiceImpl* service = new GeolocationServiceImpl(std::move(request), this); services_.push_back(base::WrapUnique<GeolocationServiceImpl>(service)); diff --git a/chromium/device/geolocation/geolocation_service_context.h b/chromium/device/geolocation/geolocation_service_context.h index 5b7c2f0c290..581fd99106e 100644 --- a/chromium/device/geolocation/geolocation_service_context.h +++ b/chromium/device/geolocation/geolocation_service_context.h @@ -12,6 +12,10 @@ #include "device/geolocation/geolocation_export.h" #include "device/geolocation/public/interfaces/geolocation.mojom.h" +namespace service_manager { +struct BindSourceInfo; +} + namespace device { class GeolocationServiceImpl; @@ -26,7 +30,8 @@ class DEVICE_GEOLOCATION_EXPORT GeolocationServiceContext { virtual ~GeolocationServiceContext(); // Creates a GeolocationServiceImpl that is weakly bound to |request|. - void CreateService(mojo::InterfaceRequest<mojom::GeolocationService> request); + void CreateService(const service_manager::BindSourceInfo& source_info, + mojom::GeolocationServiceRequest request); // Called when a service has a connection error. After this call, it is no // longer safe to access |service|. diff --git a/chromium/device/geolocation/location_api_adapter_android.cc b/chromium/device/geolocation/location_api_adapter_android.cc index 61f47902561..fd77631dcb3 100644 --- a/chromium/device/geolocation/location_api_adapter_android.cc +++ b/chromium/device/geolocation/location_api_adapter_android.cc @@ -4,7 +4,6 @@ #include "device/geolocation/location_api_adapter_android.h" -#include "base/android/context_utils.h" #include "base/android/jni_android.h" #include "base/android/jni_string.h" #include "base/bind.h" @@ -54,8 +53,8 @@ bool LocationApiAdapterAndroid::Start(OnGeopositionCB on_geoposition_callback, on_geoposition_callback_ = on_geoposition_callback; DCHECK(java_location_provider_adapter_.is_null()); - java_location_provider_adapter_.Reset(Java_LocationProviderAdapter_create( - env, base::android::GetApplicationContext())); + java_location_provider_adapter_.Reset( + Java_LocationProviderAdapter_create(env)); } // At this point we should have all our pre-conditions ready, and they'd only diff --git a/chromium/device/geolocation/location_arbitrator_unittest.cc b/chromium/device/geolocation/location_arbitrator_unittest.cc index 8bb36397ca2..f19b0c26be3 100644 --- a/chromium/device/geolocation/location_arbitrator_unittest.cc +++ b/chromium/device/geolocation/location_arbitrator_unittest.cc @@ -9,6 +9,7 @@ #include "base/bind.h" #include "base/memory/ptr_util.h" +#include "base/message_loop/message_loop.h" #include "device/geolocation/fake_access_token_store.h" #include "device/geolocation/fake_location_provider.h" #include "device/geolocation/geolocation_delegate.h" diff --git a/chromium/device/geolocation/network_location_provider.cc b/chromium/device/geolocation/network_location_provider.cc index 52aec681a20..64bb9d92130 100644 --- a/chromium/device/geolocation/network_location_provider.cc +++ b/chromium/device/geolocation/network_location_provider.cc @@ -117,40 +117,46 @@ NetworkLocationProvider::NetworkLocationProvider( access_token_(access_token), is_permission_granted_(false), is_new_data_available_(false), + request_(new NetworkLocationRequest( + url_context_getter, + url, + base::Bind(&NetworkLocationProvider::OnLocationResponse, + base::Unretained(this)))), position_cache_(new PositionCache), weak_factory_(this) { - request_.reset(new NetworkLocationRequest( - url_context_getter, url, - base::Bind(&NetworkLocationProvider::OnLocationResponse, - base::Unretained(this)))); + DLOG_IF(WARNING, !url.is_valid()) + << __func__ << " Bad URL: " << url.possibly_invalid_spec(); } NetworkLocationProvider::~NetworkLocationProvider() { - StopProvider(); -} - -// LocationProvider implementation -const Geoposition& NetworkLocationProvider::GetPosition() { - return position_; + DCHECK(thread_checker_.CalledOnValidThread()); + if (IsStarted()) + StopProvider(); } void NetworkLocationProvider::SetUpdateCallback( const LocationProvider::LocationProviderUpdateCallback& callback) { + DCHECK(thread_checker_.CalledOnValidThread()); location_provider_update_callback_ = callback; } void NetworkLocationProvider::OnPermissionGranted() { const bool was_permission_granted = is_permission_granted_; is_permission_granted_ = true; - if (!was_permission_granted && IsStarted()) { + if (!was_permission_granted && IsStarted()) RequestPosition(); - } } void NetworkLocationProvider::OnWifiDataUpdate() { - DCHECK(wifi_data_provider_manager_); + DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(IsStarted()); is_wifi_data_complete_ = wifi_data_provider_manager_->GetData(&wifi_data_); - OnWifiDataUpdated(); + if (!is_wifi_data_complete_) + return; + + wifi_timestamp_ = base::Time::Now(); + is_new_data_available_ = true; + RequestPosition(); } void NetworkLocationProvider::OnLocationResponse( @@ -158,12 +164,11 @@ void NetworkLocationProvider::OnLocationResponse( bool server_error, const base::string16& access_token, const WifiData& wifi_data) { - DCHECK(CalledOnValidThread()); + DCHECK(thread_checker_.CalledOnValidThread()); // Record the position and update our cache. position_ = position; - if (position.Validate()) { + if (position.Validate()) position_cache_->CachePosition(wifi_data, position); - } // Record access_token if it's set. if (!access_token.empty() && access_token_ != access_token) { @@ -177,19 +182,14 @@ void NetworkLocationProvider::OnLocationResponse( } bool NetworkLocationProvider::StartProvider(bool high_accuracy) { - DCHECK(CalledOnValidThread()); + DCHECK(thread_checker_.CalledOnValidThread()); if (IsStarted()) return true; - DCHECK(!wifi_data_provider_manager_); - if (!request_->url().is_valid()) { - LOG(WARNING) << "StartProvider() : Failed, Bad URL: " - << request_->url().possibly_invalid_spec(); + if (!request_->url().is_valid()) return false; - } - // Registers a callback with the data provider. The first call to Register - // will create a singleton data provider and it will be deleted when the last - // callback is removed with Unregister. + // Registers a callback with the data provider. The first call to Register() + // will create a singleton data provider that will be deleted on Unregister(). wifi_data_provider_manager_ = WifiDataProviderManager::Register(&wifi_data_update_callback_); @@ -197,44 +197,33 @@ bool NetworkLocationProvider::StartProvider(bool high_accuracy) { FROM_HERE, base::Bind(&NetworkLocationProvider::RequestPosition, weak_factory_.GetWeakPtr()), base::TimeDelta::FromSeconds(kDataCompleteWaitSeconds)); - // Get the wifi data. - is_wifi_data_complete_ = wifi_data_provider_manager_->GetData(&wifi_data_); - if (is_wifi_data_complete_) - OnWifiDataUpdated(); - return true; -} -void NetworkLocationProvider::OnWifiDataUpdated() { - DCHECK(CalledOnValidThread()); - wifi_timestamp_ = base::Time::Now(); - - is_new_data_available_ = is_wifi_data_complete_; - RequestPosition(); + OnWifiDataUpdate(); + return true; } void NetworkLocationProvider::StopProvider() { - DCHECK(CalledOnValidThread()); - if (IsStarted()) { - wifi_data_provider_manager_->Unregister(&wifi_data_update_callback_); - } + DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(IsStarted()); + wifi_data_provider_manager_->Unregister(&wifi_data_update_callback_); wifi_data_provider_manager_ = nullptr; weak_factory_.InvalidateWeakPtrs(); } -// Other methods +const Geoposition& NetworkLocationProvider::GetPosition() { + return position_; +} + void NetworkLocationProvider::RequestPosition() { - DCHECK(CalledOnValidThread()); + DCHECK(thread_checker_.CalledOnValidThread()); - // TODO(mcasas): consider not using HasWeakPtrs() https://crbug.com/629158. - if (weak_factory_.HasWeakPtrs() && !is_wifi_data_complete_) - return; - if (!is_new_data_available_) + if (!is_new_data_available_ || !is_wifi_data_complete_) return; + DCHECK(!wifi_timestamp_.is_null()) + << "|wifi_timestamp_| must be set before looking up position"; const Geoposition* cached_position = position_cache_->FindPosition(wifi_data_); - DCHECK(!wifi_timestamp_.is_null()) - << "Timestamp must be set before looking up position"; if (cached_position) { DCHECK(cached_position->Validate()); // Record the position and update its timestamp. @@ -255,16 +244,15 @@ void NetworkLocationProvider::RequestPosition() { if (!is_permission_granted_) return; - weak_factory_.InvalidateWeakPtrs(); is_new_data_available_ = false; // TODO(joth): Rather than cancel pending requests, we should create a new // NetworkLocationRequest for each and hold a set of pending requests. - if (request_->is_request_pending()) { - DVLOG(1) << "NetworkLocationProvider - pre-empting pending network request " - "with new data. Wifi APs: " - << wifi_data_.access_point_data.size(); - } + DLOG_IF(WARNING, request_->is_request_pending()) + << "NetworkLocationProvider - pre-empting pending network request " + "with new data. Wifi APs: " + << wifi_data_.access_point_data.size(); + request_->MakeRequest(access_token_, wifi_data_, wifi_timestamp_); } diff --git a/chromium/device/geolocation/network_location_provider.h b/chromium/device/geolocation/network_location_provider.h index dc3fb217f7f..634da9a9665 100644 --- a/chromium/device/geolocation/network_location_provider.h +++ b/chromium/device/geolocation/network_location_provider.h @@ -15,8 +15,8 @@ #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/strings/string16.h" -#include "base/threading/non_thread_safe.h" #include "base/threading/thread.h" +#include "base/threading/thread_checker.h" #include "device/geolocation/geolocation_export.h" #include "device/geolocation/geoposition.h" #include "device/geolocation/location_provider.h" @@ -26,8 +26,7 @@ namespace device { class AccessTokenStore; -class NetworkLocationProvider : public base::NonThreadSafe, - public LocationProvider { +class NetworkLocationProvider : public LocationProvider { public: // Cache of recently resolved locations. Public for tests. class DEVICE_GEOLOCATION_EXPORT PositionCache { @@ -71,23 +70,20 @@ class NetworkLocationProvider : public base::NonThreadSafe, ~NetworkLocationProvider() override; // LocationProvider implementation - void SetUpdateCallback( - const LocationProviderUpdateCallback& callback) override; + void SetUpdateCallback(const LocationProviderUpdateCallback& cb) override; bool StartProvider(bool high_accuracy) override; void StopProvider() override; const Geoposition& GetPosition() override; void OnPermissionGranted() override; private: - // Satisfies a position request from cache or network. + // Tries to update |position_| request from cache or network. void RequestPosition(); - // Gets called when new wifi data is available. + // Gets called when new wifi data is available, either via explicit request to + // or callback from |wifi_data_provider_manager_|. void OnWifiDataUpdate(); - // Internal helper used by OnWifiDataUpdate. - void OnWifiDataUpdated(); - bool IsStarted() const; void OnLocationResponse(const Geoposition& position, @@ -97,7 +93,8 @@ class NetworkLocationProvider : public base::NonThreadSafe, const scoped_refptr<AccessTokenStore> access_token_store_; - // The wifi data provider, acquired via global factories. + // The wifi data provider, acquired via global factories. Valid between + // StartProvider() and StopProvider(), and checked via IsStarted(). WifiDataProviderManager* wifi_data_provider_manager_; WifiDataProviderManager::WifiDataUpdateCallback wifi_data_update_callback_; @@ -125,11 +122,13 @@ class NetworkLocationProvider : public base::NonThreadSafe, bool is_new_data_available_; // The network location request object, and the url it uses. - std::unique_ptr<NetworkLocationRequest> request_; + const std::unique_ptr<NetworkLocationRequest> request_; // The cache of positions. const std::unique_ptr<PositionCache> position_cache_; + base::ThreadChecker thread_checker_; + base::WeakPtrFactory<NetworkLocationProvider> weak_factory_; DISALLOW_COPY_AND_ASSIGN(NetworkLocationProvider); diff --git a/chromium/device/geolocation/network_location_provider_unittest.cc b/chromium/device/geolocation/network_location_provider_unittest.cc index 2d0d754af02..0129625bde3 100644 --- a/chromium/device/geolocation/network_location_provider_unittest.cc +++ b/chromium/device/geolocation/network_location_provider_unittest.cc @@ -14,6 +14,7 @@ #include "base/json/json_reader.h" #include "base/json/json_writer.h" #include "base/macros.h" +#include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" diff --git a/chromium/device/geolocation/network_location_request.cc b/chromium/device/geolocation/network_location_request.cc index 191f7a561ba..0db378af8d1 100644 --- a/chromium/device/geolocation/network_location_request.cc +++ b/chromium/device/geolocation/network_location_request.cc @@ -22,6 +22,7 @@ #include "google_apis/google_api_keys.h" #include "net/base/escape.h" #include "net/base/load_flags.h" +#include "net/traffic_annotation/network_traffic_annotation.h" #include "net/url_request/url_fetcher.h" #include "net/url_request/url_request_context_getter.h" #include "net/url_request/url_request_status.h" @@ -124,8 +125,33 @@ bool NetworkLocationRequest::MakeRequest(const base::string16& access_token, wifi_timestamp_ = wifi_timestamp; GURL request_url = FormRequestURL(url_); - url_fetcher_ = net::URLFetcher::Create(url_fetcher_id_for_tests, request_url, - net::URLFetcher::POST, this); + net::NetworkTrafficAnnotationTag traffic_annotation = + net::DefineNetworkTrafficAnnotation("device_geolocation_request", R"( + semantics { + sender: "Network Location Provider" + description: + "Obtains geo position based on current IP address." + trigger: + "Location requests are sent when the page requests them or new " + "IP address is available." + data: "IP Address." + destination: GOOGLE_OWNED_SERVICE + } + policy { + cookies_allowed: false + setting: + "Users can control this feature via the Location setting under " + "'Privacy', 'Content Settings...'." + chrome_policy { + DefaultGeolocationSetting { + policy_options {mode: MANDATORY} + DefaultGeolocationSetting: 2 + } + } + })"); + url_fetcher_ = + net::URLFetcher::Create(url_fetcher_id_for_tests, request_url, + net::URLFetcher::POST, this, traffic_annotation); url_fetcher_->SetRequestContext(url_context_.get()); std::string upload_data; FormUploadData(wifi_data, wifi_timestamp, access_token, &upload_data); diff --git a/chromium/device/geolocation/public/interfaces/BUILD.gn b/chromium/device/geolocation/public/interfaces/BUILD.gn index 6bdfc1ac3d8..1fcd5431f4e 100644 --- a/chromium/device/geolocation/public/interfaces/BUILD.gn +++ b/chromium/device/geolocation/public/interfaces/BUILD.gn @@ -8,4 +8,7 @@ mojom("interfaces") { sources = [ "geolocation.mojom", ] + + # TODO(crbug.com/714018): Convert the implementation to use OnceCallback. + use_once_callback = false } diff --git a/chromium/device/geolocation/wifi_data_provider_chromeos_unittest.cc b/chromium/device/geolocation/wifi_data_provider_chromeos_unittest.cc index 9234cb0c3b2..66d750ec1eb 100644 --- a/chromium/device/geolocation/wifi_data_provider_chromeos_unittest.cc +++ b/chromium/device/geolocation/wifi_data_provider_chromeos_unittest.cc @@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/message_loop/message_loop.h" +#include "device/geolocation/wifi_data_provider_chromeos.h" #include "base/run_loop.h" #include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" +#include "base/test/scoped_task_environment.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/shill_manager_client.h" #include "chromeos/network/geolocation_handler.h" -#include "device/geolocation/wifi_data_provider_chromeos.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/cros_system_api/dbus/service_constants.h" @@ -18,7 +18,9 @@ namespace device { class GeolocationChromeOsWifiDataProviderTest : public testing::Test { protected: - GeolocationChromeOsWifiDataProviderTest() {} + GeolocationChromeOsWifiDataProviderTest() + : scoped_task_environment_( + base::test::ScopedTaskEnvironment::MainThreadType::UI) {} void SetUp() override { chromeos::DBusThreadManager::Initialize(); @@ -59,7 +61,7 @@ class GeolocationChromeOsWifiDataProviderTest : public testing::Test { base::RunLoop().RunUntilIdle(); } - base::MessageLoopForUI message_loop_; + base::test::ScopedTaskEnvironment scoped_task_environment_; scoped_refptr<WifiDataProviderChromeOs> provider_; chromeos::ShillManagerClient* manager_client_; chromeos::ShillManagerClient::TestInterface* manager_test_; diff --git a/chromium/device/geolocation/wifi_data_provider_common.cc b/chromium/device/geolocation/wifi_data_provider_common.cc index 729efb60074..9d80043609e 100644 --- a/chromium/device/geolocation/wifi_data_provider_common.cc +++ b/chromium/device/geolocation/wifi_data_provider_common.cc @@ -13,7 +13,7 @@ namespace device { base::string16 MacAddressAsString16(const uint8_t mac_as_int[6]) { - // mac_as_int is big-endian. Write in byte chunks. + // |mac_as_int| is big-endian. Write in byte chunks. // Format is XX-XX-XX-XX-XX-XX. static const char* const kMacFormatString = "%02x-%02x-%02x-%02x-%02x-%02x"; return base::ASCIIToUTF16(base::StringPrintf( @@ -27,17 +27,17 @@ WifiDataProviderCommon::WifiDataProviderCommon() WifiDataProviderCommon::~WifiDataProviderCommon() {} void WifiDataProviderCommon::StartDataProvider() { - DCHECK(wlan_api_ == NULL); - wlan_api_.reset(NewWlanApi()); - if (wlan_api_ == NULL) { + DCHECK(!wlan_api_); + wlan_api_ = CreateWlanApi(); + if (!wlan_api_) { // Error! Can't do scans, so don't try and schedule one. is_first_scan_complete_ = true; return; } - DCHECK(polling_policy_ == NULL); - polling_policy_.reset(NewPollingPolicy()); - DCHECK(polling_policy_ != NULL); + DCHECK(!polling_policy_); + polling_policy_ = CreatePollingPolicy(); + DCHECK(polling_policy_); // Perform first scan ASAP regardless of the polling policy. If this scan // fails we'll retry at a rate in line with the polling policy. diff --git a/chromium/device/geolocation/wifi_data_provider_common.h b/chromium/device/geolocation/wifi_data_provider_common.h index 68f9c4c6f49..44a312cb4ed 100644 --- a/chromium/device/geolocation/wifi_data_provider_common.h +++ b/chromium/device/geolocation/wifi_data_provider_common.h @@ -50,11 +50,12 @@ class DEVICE_GEOLOCATION_EXPORT WifiDataProviderCommon protected: ~WifiDataProviderCommon() override; + // TODO(mcasas): change return types and possibly names of these two methods, + // see https://crbug.com/714348. // Returns ownership. - virtual WlanApiInterface* NewWlanApi() = 0; - + virtual std::unique_ptr<WlanApiInterface> CreateWlanApi() = 0; // Returns ownership. - virtual WifiPollingPolicy* NewPollingPolicy() = 0; + virtual std::unique_ptr<WifiPollingPolicy> CreatePollingPolicy() = 0; private: // Runs a scan. Calls the callbacks if new data is found. diff --git a/chromium/device/geolocation/wifi_data_provider_common_unittest.cc b/chromium/device/geolocation/wifi_data_provider_common_unittest.cc index eb3257e24b2..ff914d1ff6e 100644 --- a/chromium/device/geolocation/wifi_data_provider_common_unittest.cc +++ b/chromium/device/geolocation/wifi_data_provider_common_unittest.cc @@ -10,6 +10,7 @@ #include "base/run_loop.h" #include "base/single_thread_task_runner.h" #include "base/strings/utf_string_conversions.h" +#include "base/test/scoped_task_environment.h" #include "base/third_party/dynamic_annotations/dynamic_annotations.h" #include "base/threading/thread_task_runner_handle.h" #include "device/geolocation/wifi_data_provider_manager.h" @@ -17,33 +18,28 @@ #include "testing/gtest/include/gtest/gtest.h" using testing::_; +using testing::AnyNumber; using testing::AtLeast; -using testing::DoDefault; +using testing::DoAll; using testing::Invoke; +using testing::InvokeWithoutArgs; using testing::Return; +using testing::SetArgPointee; +using testing::WithArgs; namespace device { class MockWlanApi : public WifiDataProviderCommon::WlanApiInterface { public: - MockWlanApi() : calls_(0), bool_return_(true) { - ANNOTATE_BENIGN_RACE(&calls_, "This is a test-only data race on a counter"); + MockWlanApi() { ON_CALL(*this, GetAccessPointData(_)) - .WillByDefault(Invoke(this, &MockWlanApi::GetAccessPointDataInternal)); + .WillByDefault(DoAll(SetArgPointee<0>(data_out_), Return(true))); } MOCK_METHOD1(GetAccessPointData, bool(WifiData::AccessPointDataSet* data)); - int calls_; - bool bool_return_; - WifiData::AccessPointDataSet data_out_; - private: - bool GetAccessPointDataInternal(WifiData::AccessPointDataSet* data) { - ++calls_; - *data = data_out_; - return bool_return_; - } + WifiData::AccessPointDataSet data_out_; }; class MockPollingPolicy : public WifiPollingPolicy { @@ -51,32 +47,31 @@ class MockPollingPolicy : public WifiPollingPolicy { MockPollingPolicy() { ON_CALL(*this, PollingInterval()).WillByDefault(Return(1)); ON_CALL(*this, NoWifiInterval()).WillByDefault(Return(1)); + // We are not interested in calls to UpdatePollingInterval() method. + EXPECT_CALL(*this, UpdatePollingInterval(_)).Times(AnyNumber()); } + // WifiPollingPolicy implementation. + MOCK_METHOD1(UpdatePollingInterval, void(bool)); MOCK_METHOD0(PollingInterval, int()); MOCK_METHOD0(NoWifiInterval, int()); - - virtual void UpdatePollingInterval(bool) {} }; class WifiDataProviderCommonWithMock : public WifiDataProviderCommon { public: WifiDataProviderCommonWithMock() - : new_wlan_api_(new MockWlanApi), - new_polling_policy_(new MockPollingPolicy) {} + : wlan_api_(new MockWlanApi), polling_policy_(new MockPollingPolicy) {} // WifiDataProviderCommon - WlanApiInterface* NewWlanApi() override { - CHECK(new_wlan_api_ != NULL); - return new_wlan_api_.release(); + std::unique_ptr<WlanApiInterface> CreateWlanApi() override { + return std::move(wlan_api_); } - WifiPollingPolicy* NewPollingPolicy() override { - CHECK(new_polling_policy_ != NULL); - return new_polling_policy_.release(); + std::unique_ptr<WifiPollingPolicy> CreatePollingPolicy() override { + return std::move(polling_policy_); } - std::unique_ptr<MockWlanApi> new_wlan_api_; - std::unique_ptr<MockPollingPolicy> new_polling_policy_; + std::unique_ptr<MockWlanApi> wlan_api_; + std::unique_ptr<MockPollingPolicy> polling_policy_; private: ~WifiDataProviderCommonWithMock() override {} @@ -84,119 +79,95 @@ class WifiDataProviderCommonWithMock : public WifiDataProviderCommon { DISALLOW_COPY_AND_ASSIGN(WifiDataProviderCommonWithMock); }; -WifiDataProvider* CreateWifiDataProviderCommonWithMock() { - return new WifiDataProviderCommonWithMock; -} - // Main test fixture class GeolocationWifiDataProviderCommonTest : public testing::Test { public: GeolocationWifiDataProviderCommonTest() - : main_task_runner_(base::ThreadTaskRunnerHandle::Get()), - wifi_data_callback_( - base::Bind(&GeolocationWifiDataProviderCommonTest::OnWifiDataUpdate, - base::Unretained(this))) {} + : scoped_task_environment_( + base::test::ScopedTaskEnvironment::MainThreadType::UI), + wifi_data_callback_(base::Bind(&base::DoNothing)), + provider_(new WifiDataProviderCommonWithMock), + wlan_api_(provider_->wlan_api_.get()), + polling_policy_(provider_->polling_policy_.get()) {} void SetUp() override { - provider_ = new WifiDataProviderCommonWithMock; - wlan_api_ = provider_->new_wlan_api_.get(); - polling_policy_ = provider_->new_polling_policy_.get(); provider_->AddCallback(&wifi_data_callback_); } void TearDown() override { provider_->RemoveCallback(&wifi_data_callback_); provider_->StopDataProvider(); - provider_ = NULL; - } - - void OnWifiDataUpdate() { - // Callbacks must run on the originating thread. - EXPECT_TRUE(main_task_runner_->BelongsToCurrentThread()); - run_loop_->Quit(); - } - - void RunLoop() { - run_loop_.reset(new base::RunLoop()); - run_loop_->Run(); } protected: - base::MessageLoopForUI message_loop_; - scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; - std::unique_ptr<base::RunLoop> run_loop_; + const base::test::ScopedTaskEnvironment scoped_task_environment_; WifiDataProviderManager::WifiDataUpdateCallback wifi_data_callback_; - scoped_refptr<WifiDataProviderCommonWithMock> provider_; - MockWlanApi* wlan_api_; - MockPollingPolicy* polling_policy_; + const scoped_refptr<WifiDataProviderCommonWithMock> provider_; + + MockWlanApi* const wlan_api_; + MockPollingPolicy* const polling_policy_; }; TEST_F(GeolocationWifiDataProviderCommonTest, CreateDestroy) { // Test fixture members were SetUp correctly. - EXPECT_TRUE(main_task_runner_->BelongsToCurrentThread()); - EXPECT_TRUE(NULL != provider_.get()); - EXPECT_TRUE(NULL != wlan_api_); -} - -TEST_F(GeolocationWifiDataProviderCommonTest, RunNormal) { - EXPECT_CALL(*wlan_api_, GetAccessPointData(_)).Times(AtLeast(1)); - EXPECT_CALL(*polling_policy_, PollingInterval()).Times(AtLeast(1)); - provider_->StartDataProvider(); - RunLoop(); - SUCCEED(); + EXPECT_TRUE(provider_); + EXPECT_TRUE(wlan_api_); + EXPECT_TRUE(polling_policy_); } TEST_F(GeolocationWifiDataProviderCommonTest, NoWifi) { + base::RunLoop run_loop; EXPECT_CALL(*polling_policy_, NoWifiInterval()).Times(AtLeast(1)); - EXPECT_CALL(*wlan_api_, GetAccessPointData(_)).WillRepeatedly(Return(false)); + EXPECT_CALL(*wlan_api_, GetAccessPointData(_)) + .WillOnce(InvokeWithoutArgs([&run_loop]() { + run_loop.Quit(); + return false; + })); + provider_->StartDataProvider(); - RunLoop(); + run_loop.Run(); } TEST_F(GeolocationWifiDataProviderCommonTest, IntermittentWifi) { + base::RunLoop run_loop; EXPECT_CALL(*polling_policy_, PollingInterval()).Times(AtLeast(1)); EXPECT_CALL(*polling_policy_, NoWifiInterval()).Times(1); EXPECT_CALL(*wlan_api_, GetAccessPointData(_)) .WillOnce(Return(true)) - .WillOnce(Return(false)) - .WillRepeatedly(DoDefault()); - - AccessPointData single_access_point; - single_access_point.channel = 2; - single_access_point.mac_address = 3; - single_access_point.radio_signal_strength = 4; - single_access_point.signal_to_noise = 5; - single_access_point.ssid = base::ASCIIToUTF16("foossid"); - wlan_api_->data_out_.insert(single_access_point); + .WillOnce(InvokeWithoutArgs([&run_loop]() { + run_loop.Quit(); + return false; + })); provider_->StartDataProvider(); - RunLoop(); - RunLoop(); + run_loop.Run(); } -#if defined(OS_MACOSX) -#define MAYBE_DoAnEmptyScan DISABLED_DoAnEmptyScan -#else -#define MAYBE_DoAnEmptyScan DoAnEmptyScan -#endif -TEST_F(GeolocationWifiDataProviderCommonTest, MAYBE_DoAnEmptyScan) { - EXPECT_CALL(*wlan_api_, GetAccessPointData(_)).Times(AtLeast(1)); +// This test runs StartDataProvider() and expects that GetAccessPointData() is +// called. The retrieved WifiData is expected to be empty. +TEST_F(GeolocationWifiDataProviderCommonTest, DoAnEmptyScan) { + base::RunLoop run_loop; + EXPECT_CALL(*polling_policy_, PollingInterval()).Times(AtLeast(1)); + EXPECT_CALL(*wlan_api_, GetAccessPointData(_)) + .WillOnce(InvokeWithoutArgs([&run_loop]() { + run_loop.Quit(); + return true; + })); + provider_->StartDataProvider(); - RunLoop(); - EXPECT_EQ(wlan_api_->calls_, 1); + run_loop.Run(); + WifiData data; EXPECT_TRUE(provider_->GetData(&data)); - EXPECT_EQ(0, static_cast<int>(data.access_point_data.size())); + EXPECT_TRUE(data.access_point_data.empty()); } -#if defined(OS_MACOSX) -#define MAYBE_DoScanWithResults DISABLED_DoScanWithResults -#else -#define MAYBE_DoScanWithResults DoScanWithResults -#endif -TEST_F(GeolocationWifiDataProviderCommonTest, MAYBE_DoScanWithResults) { - EXPECT_CALL(*wlan_api_, GetAccessPointData(_)).Times(AtLeast(1)); +// This test runs StartDataProvider() and expects that GetAccessPointData() is +// called. Some mock WifiData is returned then and expected to be retrieved. +TEST_F(GeolocationWifiDataProviderCommonTest, DoScanWithResults) { + base::RunLoop run_loop; + EXPECT_CALL(*polling_policy_, PollingInterval()).Times(AtLeast(1)); AccessPointData single_access_point; single_access_point.channel = 2; @@ -204,24 +175,24 @@ TEST_F(GeolocationWifiDataProviderCommonTest, MAYBE_DoScanWithResults) { single_access_point.radio_signal_strength = 4; single_access_point.signal_to_noise = 5; single_access_point.ssid = base::ASCIIToUTF16("foossid"); - wlan_api_->data_out_.insert(single_access_point); + + WifiData::AccessPointDataSet data_out({single_access_point}); + + EXPECT_CALL(*wlan_api_, GetAccessPointData(_)) + .WillOnce(WithArgs<0>( + Invoke([&data_out, &run_loop](WifiData::AccessPointDataSet* data) { + *data = data_out; + run_loop.Quit(); + return true; + }))); provider_->StartDataProvider(); - RunLoop(); - EXPECT_EQ(wlan_api_->calls_, 1); + run_loop.Run(); + WifiData data; EXPECT_TRUE(provider_->GetData(&data)); - EXPECT_EQ(1, static_cast<int>(data.access_point_data.size())); + ASSERT_EQ(1u, data.access_point_data.size()); EXPECT_EQ(single_access_point.ssid, data.access_point_data.begin()->ssid); } -TEST_F(GeolocationWifiDataProviderCommonTest, RegisterUnregister) { - WifiDataProviderManager::SetFactoryForTesting( - CreateWifiDataProviderCommonWithMock); - WifiDataProviderManager::Register(&wifi_data_callback_); - RunLoop(); - WifiDataProviderManager::Unregister(&wifi_data_callback_); - WifiDataProviderManager::ResetFactoryForTesting(); -} - } // namespace device diff --git a/chromium/device/geolocation/wifi_data_provider_linux.cc b/chromium/device/geolocation/wifi_data_provider_linux.cc index cfa1e027b8c..832672c5f47 100644 --- a/chromium/device/geolocation/wifi_data_provider_linux.cc +++ b/chromium/device/geolocation/wifi_data_provider_linux.cc @@ -14,6 +14,7 @@ #include <memory> #include "base/macros.h" +#include "base/memory/ptr_util.h" #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "dbus/bus.h" @@ -86,7 +87,7 @@ class NetworkManagerWlanApi : public WifiDataProviderCommon::WlanApiInterface { }; // Convert a wifi frequency to the corresponding channel. Adapted from -// geolocaiton/wifilib.cc in googleclient (internal to google). +// geolocation/wifilib.cc in googleclient (internal to google). int frquency_in_khz_to_channel(int frequency_khz) { if (frequency_khz >= 2412000 && frequency_khz <= 2472000) // Channels 1-13. return (frequency_khz - 2407000) / 5000; @@ -135,8 +136,7 @@ bool NetworkManagerWlanApi::GetAccessPointData( int fail_count = 0; // Iterate the devices, getting APs for each wireless adapter found - for (size_t i = 0; i < device_paths.size(); ++i) { - const dbus::ObjectPath& device_path = device_paths[i]; + for (const dbus::ObjectPath& device_path : device_paths) { VLOG(1) << "Checking device: " << device_path.value(); dbus::ObjectProxy* device_proxy = @@ -219,8 +219,7 @@ bool NetworkManagerWlanApi::GetAccessPointsForAdapter( VLOG(1) << "Wireless adapter " << adapter_path.value() << " found " << access_point_paths.size() << " access points."; - for (size_t i = 0; i < access_point_paths.size(); ++i) { - const dbus::ObjectPath& access_point_path = access_point_paths[i]; + for (const dbus::ObjectPath& access_point_path : access_point_paths) { VLOG(1) << "Checking access point: " << access_point_path.value(); dbus::ObjectProxy* access_point_proxy = system_bus_->GetObjectProxy( @@ -345,26 +344,29 @@ WifiDataProviderLinux::WifiDataProviderLinux() {} WifiDataProviderLinux::~WifiDataProviderLinux() {} -WifiDataProviderCommon::WlanApiInterface* WifiDataProviderLinux::NewWlanApi() { +std::unique_ptr<WifiDataProviderCommon::WlanApiInterface> +WifiDataProviderLinux::CreateWlanApi() { std::unique_ptr<NetworkManagerWlanApi> wlan_api(new NetworkManagerWlanApi); if (wlan_api->Init()) - return wlan_api.release(); - return NULL; + return std::move(wlan_api); + return nullptr; } -WifiPollingPolicy* WifiDataProviderLinux::NewPollingPolicy() { - return new GenericWifiPollingPolicy<kDefaultPollingIntervalMilliseconds, - kNoChangePollingIntervalMilliseconds, - kTwoNoChangePollingIntervalMilliseconds, - kNoWifiPollingIntervalMilliseconds>; +std::unique_ptr<WifiPollingPolicy> +WifiDataProviderLinux::CreatePollingPolicy() { + return base::MakeUnique<GenericWifiPollingPolicy< + kDefaultPollingIntervalMilliseconds, kNoChangePollingIntervalMilliseconds, + kTwoNoChangePollingIntervalMilliseconds, + kNoWifiPollingIntervalMilliseconds>>(); } -WifiDataProviderCommon::WlanApiInterface* -WifiDataProviderLinux::NewWlanApiForTesting(dbus::Bus* bus) { +std::unique_ptr<WifiDataProviderCommon::WlanApiInterface> +WifiDataProviderLinux::CreateWlanApiForTesting(dbus::Bus* bus) { std::unique_ptr<NetworkManagerWlanApi> wlan_api(new NetworkManagerWlanApi); if (wlan_api->InitWithBus(bus)) - return wlan_api.release(); - return NULL; + return std::move(wlan_api); + return nullptr; + ; } } // namespace device diff --git a/chromium/device/geolocation/wifi_data_provider_linux.h b/chromium/device/geolocation/wifi_data_provider_linux.h index 69dd37e5136..23868211198 100644 --- a/chromium/device/geolocation/wifi_data_provider_linux.h +++ b/chromium/device/geolocation/wifi_data_provider_linux.h @@ -26,12 +26,11 @@ class DEVICE_GEOLOCATION_EXPORT WifiDataProviderLinux ~WifiDataProviderLinux() override; - // WifiDataProviderCommon - WlanApiInterface* NewWlanApi() override; - WifiPollingPolicy* NewPollingPolicy() override; + // WifiDataProviderCommon implementation + std::unique_ptr<WlanApiInterface> CreateWlanApi() override; + std::unique_ptr<WifiPollingPolicy> CreatePollingPolicy() override; - // For testing. - WlanApiInterface* NewWlanApiForTesting(dbus::Bus* bus); + std::unique_ptr<WlanApiInterface> CreateWlanApiForTesting(dbus::Bus* bus); DISALLOW_COPY_AND_ASSIGN(WifiDataProviderLinux); }; diff --git a/chromium/device/geolocation/wifi_data_provider_linux_unittest.cc b/chromium/device/geolocation/wifi_data_provider_linux_unittest.cc index 99e7557f317..1153a396835 100644 --- a/chromium/device/geolocation/wifi_data_provider_linux_unittest.cc +++ b/chromium/device/geolocation/wifi_data_provider_linux_unittest.cc @@ -10,8 +10,8 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/message_loop/message_loop.h" #include "base/strings/utf_string_conversions.h" +#include "base/test/scoped_task_environment.h" #include "dbus/message.h" #include "dbus/mock_bus.h" #include "dbus/mock_object_proxy.h" @@ -92,15 +92,18 @@ class GeolocationWifiDataProviderLinuxTest : public testing::Test { // Create the wlan API with the mock bus object injected. wifi_provider_linux_ = new WifiDataProviderLinux; - wlan_api_.reset( - wifi_provider_linux_->NewWlanApiForTesting(mock_bus_.get())); - ASSERT_TRUE(wlan_api_.get()); + wlan_api_ = wifi_provider_linux_->CreateWlanApiForTesting(mock_bus_.get()); + ASSERT_TRUE(wlan_api_); } protected: + GeolocationWifiDataProviderLinuxTest() + : scoped_task_environment_( + base::test::ScopedTaskEnvironment::MainThreadType::UI) {} + // WifiDataProvider requires a task runner to be present. The |message_loop_| // is defined here, as it should outlive |wifi_provider_linux_|. - base::MessageLoopForUI message_loop_; + base::test::ScopedTaskEnvironment scoped_task_environment_; scoped_refptr<dbus::MockBus> mock_bus_; scoped_refptr<dbus::MockObjectProxy> mock_network_manager_proxy_; scoped_refptr<dbus::MockObjectProxy> mock_access_point_proxy_; diff --git a/chromium/device/geolocation/wifi_data_provider_mac.h b/chromium/device/geolocation/wifi_data_provider_mac.h index 42f28984d56..0c38c3a2c91 100644 --- a/chromium/device/geolocation/wifi_data_provider_mac.h +++ b/chromium/device/geolocation/wifi_data_provider_mac.h @@ -20,9 +20,9 @@ class WifiDataProviderMac : public WifiDataProviderCommon { private: ~WifiDataProviderMac() override; - // WifiDataProviderCommon - WlanApiInterface* NewWlanApi() override; - WifiPollingPolicy* NewPollingPolicy() override; + // WifiDataProviderCommon implementation + std::unique_ptr<WlanApiInterface> CreateWlanApi() override; + std::unique_ptr<WifiPollingPolicy> CreatePollingPolicy() override; DISALLOW_COPY_AND_ASSIGN(WifiDataProviderMac); }; diff --git a/chromium/device/geolocation/wifi_data_provider_mac.mm b/chromium/device/geolocation/wifi_data_provider_mac.mm index a5f978bf7f7..6edf1793bc4 100644 --- a/chromium/device/geolocation/wifi_data_provider_mac.mm +++ b/chromium/device/geolocation/wifi_data_provider_mac.mm @@ -10,6 +10,7 @@ #include "base/mac/scoped_nsautorelease_pool.h" #include "base/mac/scoped_nsobject.h" #include "base/macros.h" +#include "base/memory/ptr_util.h" #include "base/metrics/histogram_macros.h" #include "base/strings/sys_string_conversions.h" #include "device/geolocation/wifi_data_provider_common.h" @@ -122,14 +123,15 @@ WifiDataProviderMac::WifiDataProviderMac() {} WifiDataProviderMac::~WifiDataProviderMac() {} -WifiDataProviderMac::WlanApiInterface* WifiDataProviderMac::NewWlanApi() { - return new CoreWlanApi(); +std::unique_ptr<WifiDataProviderMac::WlanApiInterface> +WifiDataProviderMac::CreateWlanApi() { + return base::MakeUnique<CoreWlanApi>(); } -WifiPollingPolicy* WifiDataProviderMac::NewPollingPolicy() { - return new GenericWifiPollingPolicy< +std::unique_ptr<WifiPollingPolicy> WifiDataProviderMac::CreatePollingPolicy() { + return base::MakeUnique<GenericWifiPollingPolicy< kDefaultPollingInterval, kNoChangePollingInterval, - kTwoNoChangePollingInterval, kNoWifiPollingIntervalMilliseconds>; + kTwoNoChangePollingInterval, kNoWifiPollingIntervalMilliseconds>>(); } } // namespace device diff --git a/chromium/device/geolocation/wifi_data_provider_win.cc b/chromium/device/geolocation/wifi_data_provider_win.cc index c31440f675c..908d06c4f54 100644 --- a/chromium/device/geolocation/wifi_data_provider_win.cc +++ b/chromium/device/geolocation/wifi_data_provider_win.cc @@ -2,25 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Windows Vista uses the Native Wifi (WLAN) API for accessing WiFi cards. See -// http://msdn.microsoft.com/en-us/library/ms705945(VS.85).aspx. Windows XP -// Service Pack 3 (and Windows XP Service Pack 2, if upgraded with a hot fix) -// also support a limited version of the WLAN API. See -// http://msdn.microsoft.com/en-us/library/bb204766.aspx. The WLAN API uses -// wlanapi.h, which is not part of the SDK used by Gears, so is replicated -// locally using data from the MSDN. -// -// Windows XP from Service Pack 2 onwards supports the Wireless Zero -// Configuration (WZC) programming interface. See -// http://msdn.microsoft.com/en-us/library/ms706587(VS.85).aspx. -// -// The MSDN recommends that one use the WLAN API where available, and WZC -// otherwise. -// -// However, it seems that WZC fails for some wireless cards. Also, WLAN seems -// not to work on XP SP3. So we use WLAN on Vista, and use NDIS directly -// otherwise. - #include "device/geolocation/wifi_data_provider_win.h" #include <windows.h> @@ -28,31 +9,23 @@ #include <wlanapi.h> #include "base/memory/free_deleter.h" +#include "base/memory/ptr_util.h" #include "base/metrics/histogram_macros.h" #include "base/strings/utf_string_conversions.h" +#include "base/timer/elapsed_timer.h" #include "base/win/windows_version.h" #include "device/geolocation/wifi_data_provider_common.h" #include "device/geolocation/wifi_data_provider_common_win.h" #include "device/geolocation/wifi_data_provider_manager.h" -// Taken from ndis.h for WinCE. -#define NDIS_STATUS_INVALID_LENGTH ((NDIS_STATUS)0xC0010014L) -#define NDIS_STATUS_BUFFER_TOO_SHORT ((NDIS_STATUS)0xC0010016L) - namespace device { -namespace { -// The limits on the size of the buffer used for the OID query. -const int kInitialBufferSize = 2 << 12; // Good for about 50 APs. -const int kMaximumBufferSize = 2 << 20; // 2MB -// Length for generic string buffers passed to Windows APIs. -const int kStringLength = 512; +namespace { -// The time periods, in milliseconds, between successive polls of the wifi data. -const int kDefaultPollingInterval = 10000; // 10s -const int kNoChangePollingInterval = 120000; // 2 mins -const int kTwoNoChangePollingInterval = 600000; // 10 mins -const int kNoWifiPollingIntervalMilliseconds = 20 * 1000; // 20s +static const int kDefaultPollingIntervalMs = 10 * 1000; // 10s +static const int kNoChangePollingIntervalMs = 2 * 60 * 1000; // 2 mins +static const int kTwoNoChangePollingIntervalMs = 10 * 60 * 1000; // 10 mins +static const int kNoWifiPollingIntervalMs = 20 * 1000; // 20s // WlanOpenHandle typedef DWORD(WINAPI* WlanOpenHandleFunction)(DWORD dwClientVersion, @@ -83,29 +56,47 @@ typedef VOID(WINAPI* WlanFreeMemoryFunction)(PVOID pMemory); typedef DWORD(WINAPI* WlanCloseHandleFunction)(HANDLE hClientHandle, PVOID pReserved); -// Local classes and functions +// Extracts data for an access point and converts to AccessPointData. +AccessPointData GetNetworkData(const WLAN_BSS_ENTRY& bss_entry) { + AccessPointData access_point_data; + // Currently we get only MAC address, signal strength and SSID. + access_point_data.mac_address = MacAddressAsString16(bss_entry.dot11Bssid); + access_point_data.radio_signal_strength = bss_entry.lRssi; + // bss_entry.dot11Ssid.ucSSID is not null-terminated. + base::UTF8ToUTF16(reinterpret_cast<const char*>(bss_entry.dot11Ssid.ucSSID), + static_cast<ULONG>(bss_entry.dot11Ssid.uSSIDLength), + &access_point_data.ssid); + + // TODO(steveblock): Is it possible to get the following? + // access_point_data.signal_to_noise + // access_point_data.age + // access_point_data.channel + return access_point_data; +} + +// This class encapsulates loading and interacting with wlan_api.dll, which can +// not be loaded statically because it's not available in Server 2008 R2, where +// it must be installed explicitly by the user if and when they wants to use the +// Wireless interface. +// https://www.bonusbits.com/wiki/KB:Wlanapi.dll_missing_on_Windows_Server_2008_R2 class WindowsWlanApi : public WifiDataProviderCommon::WlanApiInterface { public: - ~WindowsWlanApi() override; - // Factory function. Will return NULL if this API is unavailable. - static WindowsWlanApi* Create(); - - // WlanApiInterface - bool GetAccessPointData(WifiData::AccessPointDataSet* data) override; + static std::unique_ptr<WindowsWlanApi> Create(); - private: // Takes ownership of the library handle. explicit WindowsWlanApi(HINSTANCE library); + ~WindowsWlanApi() override; - // Loads the required functions from the DLL. - void GetWLANFunctions(HINSTANCE wlan_library); - int GetInterfaceDataWLAN(HANDLE wlan_handle, - const GUID& interface_id, - WifiData::AccessPointDataSet* data); + // WlanApiInterface implementation + bool GetAccessPointData(WifiData::AccessPointDataSet* data) override; + private: // Logs number of detected wlan interfaces. static void LogWlanInterfaceCount(int count); + bool GetInterfaceDataWLAN(HANDLE wlan_handle, + const GUID& interface_id, + WifiData::AccessPointDataSet* data); // Handle to the wlanapi.dll library. HINSTANCE library_; @@ -117,133 +108,56 @@ class WindowsWlanApi : public WifiDataProviderCommon::WlanApiInterface { WlanCloseHandleFunction WlanCloseHandle_function_; }; -class WindowsNdisApi : public WifiDataProviderCommon::WlanApiInterface { - public: - ~WindowsNdisApi() override; - static WindowsNdisApi* Create(); - - // WlanApiInterface - bool GetAccessPointData(WifiData::AccessPointDataSet* data) override; - - private: - static bool GetInterfacesNDIS( - std::vector<base::string16>* interface_service_names_out); - - // Swaps in content of the vector passed - explicit WindowsNdisApi(std::vector<base::string16>* interface_service_names); - - bool GetInterfaceDataNDIS(HANDLE adapter_handle, - WifiData::AccessPointDataSet* data); - // NDIS variables. - std::vector<base::string16> interface_service_names_; - - // Remembers scan result buffer size across calls. - int oid_buffer_size_; -}; - -// Extracts data for an access point and converts to Gears format. -bool GetNetworkData(const WLAN_BSS_ENTRY& bss_entry, - AccessPointData* access_point_data); -bool UndefineDosDevice(const base::string16& device_name); -bool DefineDosDeviceIfNotExists(const base::string16& device_name); -HANDLE GetFileHandle(const base::string16& device_name); -// Makes the OID query and returns a Windows API error code. -int PerformQuery(HANDLE adapter_handle, - BYTE* buffer, - DWORD buffer_size, - DWORD* bytes_out); -bool ResizeBuffer(int requested_size, - std::unique_ptr<BYTE, base::FreeDeleter>* buffer); -// Gets the system directory and appends a trailing slash if not already -// present. -bool GetSystemDirectory(base::string16* path); -} // namespace - -WifiDataProvider* WifiDataProviderManager::DefaultFactoryFunction() { - return new WifiDataProviderWin(); +// static +std::unique_ptr<WindowsWlanApi> WindowsWlanApi::Create() { + // Use an absolute path to load the DLL to avoid DLL preloading attacks. + static const wchar_t* const kDLL = L"%WINDIR%\\system32\\wlanapi.dll"; + wchar_t path[MAX_PATH] = {0}; + ExpandEnvironmentStrings(kDLL, path, arraysize(path)); + HINSTANCE library = LoadLibraryEx(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); + if (!library) + return nullptr; + return base::MakeUnique<WindowsWlanApi>(library); } -WifiDataProviderWin::WifiDataProviderWin() {} - -WifiDataProviderWin::~WifiDataProviderWin() {} - -WifiDataProviderCommon::WlanApiInterface* WifiDataProviderWin::NewWlanApi() { - // Use the WLAN interface if we're on Vista and if it's available. Otherwise, - // use NDIS. - WlanApiInterface* api = WindowsWlanApi::Create(); - if (api) { - return api; - } - return WindowsNdisApi::Create(); -} - -WifiPollingPolicy* WifiDataProviderWin::NewPollingPolicy() { - return new GenericWifiPollingPolicy< - kDefaultPollingInterval, kNoChangePollingInterval, - kTwoNoChangePollingInterval, kNoWifiPollingIntervalMilliseconds>; -} - -// Local classes and functions -namespace { - -// WindowsWlanApi WindowsWlanApi::WindowsWlanApi(HINSTANCE library) : library_(library) { - GetWLANFunctions(library_); -} - -WindowsWlanApi::~WindowsWlanApi() { - FreeLibrary(library_); -} - -WindowsWlanApi* WindowsWlanApi::Create() { - if (base::win::GetVersion() < base::win::VERSION_VISTA) - return NULL; - // We use an absolute path to load the DLL to avoid DLL preloading attacks. - base::string16 system_directory; - if (!GetSystemDirectory(&system_directory)) { - return NULL; - } - DCHECK(!system_directory.empty()); - base::string16 dll_path = system_directory + L"wlanapi.dll"; - HINSTANCE library = - LoadLibraryEx(dll_path.c_str(), NULL, LOAD_WITH_ALTERED_SEARCH_PATH); - if (!library) { - return NULL; - } - return new WindowsWlanApi(library); -} - -void WindowsWlanApi::GetWLANFunctions(HINSTANCE wlan_library) { - DCHECK(wlan_library); + DCHECK(library_); + // Extract all methods from |library_|. WlanOpenHandle_function_ = reinterpret_cast<WlanOpenHandleFunction>( - GetProcAddress(wlan_library, "WlanOpenHandle")); + GetProcAddress(library_, "WlanOpenHandle")); WlanEnumInterfaces_function_ = reinterpret_cast<WlanEnumInterfacesFunction>( - GetProcAddress(wlan_library, "WlanEnumInterfaces")); + GetProcAddress(library_, "WlanEnumInterfaces")); WlanGetNetworkBssList_function_ = reinterpret_cast<WlanGetNetworkBssListFunction>( - GetProcAddress(wlan_library, "WlanGetNetworkBssList")); + GetProcAddress(library_, "WlanGetNetworkBssList")); WlanFreeMemory_function_ = reinterpret_cast<WlanFreeMemoryFunction>( - GetProcAddress(wlan_library, "WlanFreeMemory")); + GetProcAddress(library_, "WlanFreeMemory")); WlanCloseHandle_function_ = reinterpret_cast<WlanCloseHandleFunction>( - GetProcAddress(wlan_library, "WlanCloseHandle")); + GetProcAddress(library_, "WlanCloseHandle")); + DCHECK(WlanOpenHandle_function_ && WlanEnumInterfaces_function_ && WlanGetNetworkBssList_function_ && WlanFreeMemory_function_ && WlanCloseHandle_function_); } +WindowsWlanApi::~WindowsWlanApi() { + FreeLibrary(library_); +} + +// static void WindowsWlanApi::LogWlanInterfaceCount(int count) { - UMA_HISTOGRAM_CUSTOM_COUNTS("Net.Wifi.InterfaceCount", count, 1, 5, 6); + UMA_HISTOGRAM_CUSTOM_COUNTS("Net.Wifi.InterfaceCount", count, 1 /* min */, + 5 /* max */, 6 /* bucket_count */); } bool WindowsWlanApi::GetAccessPointData(WifiData::AccessPointDataSet* data) { DCHECK(data); - // Get the handle to the WLAN API. DWORD negotiated_version; - HANDLE wlan_handle = NULL; - // We could be executing on either Windows XP or Windows Vista, so use the - // lower version of the client WLAN API. It seems that the negotiated version - // is the Vista version irrespective of what we pass! + HANDLE wlan_handle = nullptr; + // Highest WLAN API version supported by the client; pass the lowest. It seems + // that the negotiated version is the Vista version (the highest) irrespective + // of what we pass! static const int kXpWlanClientVersion = 1; if ((*WlanOpenHandle_function_)(kXpWlanClientVersion, NULL, &negotiated_version, @@ -253,8 +167,8 @@ bool WindowsWlanApi::GetAccessPointData(WifiData::AccessPointDataSet* data) { } DCHECK(wlan_handle); - // Get the list of interfaces. WlanEnumInterfaces allocates interface_list. - WLAN_INTERFACE_INFO_LIST* interface_list = NULL; + // Get the list of interfaces. WlanEnumInterfaces allocates |interface_list|. + WLAN_INTERFACE_INFO_LIST* interface_list = nullptr; if ((*WlanEnumInterfaces_function_)(wlan_handle, NULL, &interface_list) != ERROR_SUCCESS) { LogWlanInterfaceCount(0); @@ -265,333 +179,78 @@ bool WindowsWlanApi::GetAccessPointData(WifiData::AccessPointDataSet* data) { LogWlanInterfaceCount(interface_list->dwNumberOfItems); // Go through the list of interfaces and get the data for each. - for (int i = 0; i < static_cast<int>(interface_list->dwNumberOfItems); ++i) { + for (size_t i = 0; i < interface_list->dwNumberOfItems; ++i) { + const WLAN_INTERFACE_INFO interface_info = interface_list->InterfaceInfo[i]; + // Skip any interface that is midway through association; the // WlanGetNetworkBssList function call is known to hang indefinitely - // when it's in this state. http://crbug.com/39300 - if (interface_list->InterfaceInfo[i].isState == - wlan_interface_state_associating) { - LOG(WARNING) << "Skipping wifi scan on adapter " << i << " (" - << interface_list->InterfaceInfo[i].strInterfaceDescription - << ") in 'associating' state. Repeated occurrences " - "indicates a non-responding adapter."; + // when it's in this state. https://crbug.com/39300 + if (interface_info.isState == wlan_interface_state_associating) { + DLOG(WARNING) << "Skipping wifi scan on adapter " << i << " (" + << interface_info.strInterfaceDescription + << ") in 'associating' state. Repeated occurrences " + "indicates a non-responding adapter."; continue; } - GetInterfaceDataWLAN(wlan_handle, - interface_list->InterfaceInfo[i].InterfaceGuid, data); + GetInterfaceDataWLAN(wlan_handle, interface_info.InterfaceGuid, data); } - // Free interface_list. (*WlanFreeMemory_function_)(interface_list); - // Close the handle. - if ((*WlanCloseHandle_function_)(wlan_handle, NULL) != ERROR_SUCCESS) { - return false; - } - - return true; + return (*WlanCloseHandle_function_)(wlan_handle, NULL) == ERROR_SUCCESS; } -// Appends the data for a single interface to the data vector. Returns the -// number of access points found, or -1 on error. -int WindowsWlanApi::GetInterfaceDataWLAN(const HANDLE wlan_handle, - const GUID& interface_id, - WifiData::AccessPointDataSet* data) { - DCHECK(data); - - const base::TimeTicks start_time = base::TimeTicks::Now(); - - // WlanGetNetworkBssList allocates bss_list. - WLAN_BSS_LIST* bss_list = NULL; +// Appends the data for a single interface to |data|. Returns false for error. +bool WindowsWlanApi::GetInterfaceDataWLAN(const HANDLE wlan_handle, + const GUID& interface_id, + WifiData::AccessPointDataSet* data) { + base::ElapsedTimer wlan_get_network_list_timer; + // WlanGetNetworkBssList allocates |bss_list|. + WLAN_BSS_LIST* bss_list = nullptr; if ((*WlanGetNetworkBssList_function_)(wlan_handle, &interface_id, NULL, // Use all SSIDs. dot11_BSS_type_any, false, // bSecurityEnabled - unused NULL, // reserved &bss_list) != ERROR_SUCCESS) { - return -1; + return false; } - // According to http://www.attnetclient.com/kb/questions.php?questionid=75 - // WlanGetNetworkBssList can sometimes return success, but leave the bss - // list as NULL. + // WlanGetNetworkBssList() can return success without filling |bss_list|. if (!bss_list) - return -1; - - const base::TimeDelta duration = base::TimeTicks::Now() - start_time; + return false; - UMA_HISTOGRAM_CUSTOM_TIMES("Net.Wifi.ScanLatency", duration, + UMA_HISTOGRAM_CUSTOM_TIMES("Net.Wifi.ScanLatency", + wlan_get_network_list_timer.Elapsed(), base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(1), 100); - int found = 0; - for (int i = 0; i < static_cast<int>(bss_list->dwNumberOfItems); ++i) { - AccessPointData access_point_data; - if (GetNetworkData(bss_list->wlanBssEntries[i], &access_point_data)) { - ++found; - data->insert(access_point_data); - } - } + for (size_t i = 0; i < bss_list->dwNumberOfItems; ++i) + data->insert(GetNetworkData(bss_list->wlanBssEntries[i])); (*WlanFreeMemory_function_)(bss_list); - return found; -} - -// WindowsNdisApi -WindowsNdisApi::WindowsNdisApi( - std::vector<base::string16>* interface_service_names) - : oid_buffer_size_(kInitialBufferSize) { - DCHECK(!interface_service_names->empty()); - interface_service_names_.swap(*interface_service_names); -} - -WindowsNdisApi::~WindowsNdisApi() {} - -WindowsNdisApi* WindowsNdisApi::Create() { - std::vector<base::string16> interface_service_names; - if (GetInterfacesNDIS(&interface_service_names)) { - return new WindowsNdisApi(&interface_service_names); - } - return NULL; -} - -bool WindowsNdisApi::GetAccessPointData(WifiData::AccessPointDataSet* data) { - DCHECK(data); - int interfaces_failed = 0; - int interfaces_succeeded = 0; - - for (int i = 0; i < static_cast<int>(interface_service_names_.size()); ++i) { - // First, check that we have a DOS device for this adapter. - if (!DefineDosDeviceIfNotExists(interface_service_names_[i])) { - continue; - } - - // Get the handle to the device. This will fail if the named device is not - // valid. - HANDLE adapter_handle = GetFileHandle(interface_service_names_[i]); - if (adapter_handle == INVALID_HANDLE_VALUE) { - continue; - } - - // Get the data. - if (GetInterfaceDataNDIS(adapter_handle, data)) { - ++interfaces_succeeded; - } else { - ++interfaces_failed; - } - - // Clean up. - CloseHandle(adapter_handle); - UndefineDosDevice(interface_service_names_[i]); - } - - // Return true if at least one interface succeeded, or at the very least none - // failed. - return interfaces_succeeded > 0 || interfaces_failed == 0; -} - -bool WindowsNdisApi::GetInterfacesNDIS( - std::vector<base::string16>* interface_service_names_out) { - HKEY network_cards_key = NULL; - if (RegOpenKeyEx( - HKEY_LOCAL_MACHINE, - L"Software\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards", 0, - KEY_READ, &network_cards_key) != ERROR_SUCCESS) { - return false; - } - DCHECK(network_cards_key); - - for (int i = 0;; ++i) { - TCHAR name[kStringLength]; - DWORD name_size = kStringLength; - FILETIME time; - if (RegEnumKeyEx(network_cards_key, i, name, &name_size, NULL, NULL, NULL, - &time) != ERROR_SUCCESS) { - break; - } - HKEY hardware_key = NULL; - if (RegOpenKeyEx(network_cards_key, name, 0, KEY_READ, &hardware_key) != - ERROR_SUCCESS) { - break; - } - DCHECK(hardware_key); - - TCHAR service_name[kStringLength]; - DWORD service_name_size = kStringLength; - DWORD type = 0; - if (RegQueryValueEx(hardware_key, L"ServiceName", NULL, &type, - reinterpret_cast<LPBYTE>(service_name), - &service_name_size) == ERROR_SUCCESS) { - interface_service_names_out->push_back(service_name); - } - RegCloseKey(hardware_key); - } - - RegCloseKey(network_cards_key); return true; } -bool WindowsNdisApi::GetInterfaceDataNDIS(HANDLE adapter_handle, - WifiData::AccessPointDataSet* data) { - DCHECK(data); +} // anonymous namespace - std::unique_ptr<BYTE, base::FreeDeleter> buffer( - static_cast<BYTE*>(malloc(oid_buffer_size_))); - if (buffer == NULL) { - return false; - } - - DWORD bytes_out; - int result; - - while (true) { - bytes_out = 0; - result = PerformQuery(adapter_handle, buffer.get(), oid_buffer_size_, - &bytes_out); - if (result == ERROR_GEN_FAILURE || // Returned by some Intel cards. - result == ERROR_INSUFFICIENT_BUFFER || result == ERROR_MORE_DATA || - result == NDIS_STATUS_INVALID_LENGTH || - result == NDIS_STATUS_BUFFER_TOO_SHORT) { - // The buffer we supplied is too small, so increase it. bytes_out should - // provide the required buffer size, but this is not always the case. - if (bytes_out > static_cast<DWORD>(oid_buffer_size_)) { - oid_buffer_size_ = bytes_out; - } else { - oid_buffer_size_ *= 2; - } - if (!ResizeBuffer(oid_buffer_size_, &buffer)) { - oid_buffer_size_ = kInitialBufferSize; // Reset for next time. - return false; - } - } else { - // The buffer is not too small. - break; - } - } - DCHECK(buffer.get()); - - if (result == ERROR_SUCCESS) { - NDIS_802_11_BSSID_LIST* bssid_list = - reinterpret_cast<NDIS_802_11_BSSID_LIST*>(buffer.get()); - GetDataFromBssIdList(*bssid_list, oid_buffer_size_, data); - } - - return true; -} - -bool GetNetworkData(const WLAN_BSS_ENTRY& bss_entry, - AccessPointData* access_point_data) { - // Currently we get only MAC address, signal strength and SSID. - DCHECK(access_point_data); - access_point_data->mac_address = MacAddressAsString16(bss_entry.dot11Bssid); - access_point_data->radio_signal_strength = bss_entry.lRssi; - // bss_entry.dot11Ssid.ucSSID is not null-terminated. - base::UTF8ToUTF16(reinterpret_cast<const char*>(bss_entry.dot11Ssid.ucSSID), - static_cast<ULONG>(bss_entry.dot11Ssid.uSSIDLength), - &access_point_data->ssid); - // TODO(steveblock): Is it possible to get the following? - // access_point_data->signal_to_noise - // access_point_data->age - // access_point_data->channel - return true; -} - -bool UndefineDosDevice(const base::string16& device_name) { - // We remove only the mapping we use, that is \Device\<device_name>. - base::string16 target_path = L"\\Device\\" + device_name; - return DefineDosDevice(DDD_RAW_TARGET_PATH | DDD_REMOVE_DEFINITION | - DDD_EXACT_MATCH_ON_REMOVE, - device_name.c_str(), target_path.c_str()) == TRUE; -} - -bool DefineDosDeviceIfNotExists(const base::string16& device_name) { - // We create a DOS device name for the device at \Device\<device_name>. - base::string16 target_path = L"\\Device\\" + device_name; - - TCHAR target[kStringLength]; - if (QueryDosDevice(device_name.c_str(), target, kStringLength) > 0 && - target_path.compare(target) == 0) { - // Device already exists. - return true; - } - - if (GetLastError() != ERROR_FILE_NOT_FOUND) { - return false; - } - - if (!DefineDosDevice(DDD_RAW_TARGET_PATH, device_name.c_str(), - target_path.c_str())) { - return false; - } - - // Check that the device is really there. - return QueryDosDevice(device_name.c_str(), target, kStringLength) > 0 && - target_path.compare(target) == 0; +WifiDataProvider* WifiDataProviderManager::DefaultFactoryFunction() { + return new WifiDataProviderWin(); } -HANDLE GetFileHandle(const base::string16& device_name) { - // We access a device with DOS path \Device\<device_name> at - // \\.\<device_name>. - base::string16 formatted_device_name = L"\\\\.\\" + device_name; - - return CreateFile(formatted_device_name.c_str(), GENERIC_READ, - FILE_SHARE_READ | FILE_SHARE_WRITE, // share mode - 0, // security attributes - OPEN_EXISTING, - 0, // flags and attributes - INVALID_HANDLE_VALUE); -} +WifiDataProviderWin::WifiDataProviderWin() = default; -int PerformQuery(HANDLE adapter_handle, - BYTE* buffer, - DWORD buffer_size, - DWORD* bytes_out) { - DWORD oid = OID_802_11_BSSID_LIST; - if (!DeviceIoControl(adapter_handle, IOCTL_NDIS_QUERY_GLOBAL_STATS, &oid, - sizeof(oid), buffer, buffer_size, bytes_out, NULL)) { - return GetLastError(); - } - return ERROR_SUCCESS; -} - -bool ResizeBuffer(int requested_size, - std::unique_ptr<BYTE, base::FreeDeleter>* buffer) { - DCHECK_GT(requested_size, 0); - DCHECK(buffer); - if (requested_size > kMaximumBufferSize) { - buffer->reset(); - return false; - } +WifiDataProviderWin::~WifiDataProviderWin() = default; - buffer->reset( - reinterpret_cast<BYTE*>(realloc(buffer->release(), requested_size))); - return buffer != NULL; +std::unique_ptr<WifiDataProviderCommon::WlanApiInterface> +WifiDataProviderWin::CreateWlanApi() { + return WindowsWlanApi::Create(); } -bool GetSystemDirectory(base::string16* path) { - DCHECK(path); - // Return value includes terminating NULL. - int buffer_size = ::GetSystemDirectory(NULL, 0); - if (buffer_size == 0) { - return false; - } - std::unique_ptr<base::char16[]> buffer(new base::char16[buffer_size]); - - // Return value excludes terminating NULL. - int characters_written = ::GetSystemDirectory(buffer.get(), buffer_size); - if (characters_written == 0) { - return false; - } - DCHECK_EQ(buffer_size - 1, characters_written); - - path->assign(buffer.get(), characters_written); - - if (*path->rbegin() != L'\\') { - path->append(L"\\"); - } - DCHECK_EQ(L'\\', *path->rbegin()); - return true; +std::unique_ptr<WifiPollingPolicy> WifiDataProviderWin::CreatePollingPolicy() { + return base::MakeUnique<GenericWifiPollingPolicy< + kDefaultPollingIntervalMs, kNoChangePollingIntervalMs, + kTwoNoChangePollingIntervalMs, kNoWifiPollingIntervalMs>>(); } -} // namespace } // namespace device diff --git a/chromium/device/geolocation/wifi_data_provider_win.h b/chromium/device/geolocation/wifi_data_provider_win.h index 50e908bfeaa..e100e155aed 100644 --- a/chromium/device/geolocation/wifi_data_provider_win.h +++ b/chromium/device/geolocation/wifi_data_provider_win.h @@ -19,9 +19,9 @@ class DEVICE_GEOLOCATION_EXPORT WifiDataProviderWin private: ~WifiDataProviderWin() override; - // WifiDataProviderCommon - WlanApiInterface* NewWlanApi() override; - WifiPollingPolicy* NewPollingPolicy() override; + // WifiDataProviderCommon implementation + std::unique_ptr<WlanApiInterface> CreateWlanApi() override; + std::unique_ptr<WifiPollingPolicy> CreatePollingPolicy() override; DISALLOW_COPY_AND_ASSIGN(WifiDataProviderWin); }; diff --git a/chromium/device/hid/hid_connection_linux.cc b/chromium/device/hid/hid_connection_linux.cc index 62d06c35d6a..fd5fc01ee40 100644 --- a/chromium/device/hid/hid_connection_linux.cc +++ b/chromium/device/hid/hid_connection_linux.cc @@ -32,37 +32,37 @@ namespace device { -class HidConnectionLinux::FileThreadHelper { +class HidConnectionLinux::BlockingTaskHelper { public: - FileThreadHelper(base::ScopedFD fd, - scoped_refptr<HidDeviceInfo> device_info, - base::WeakPtr<HidConnectionLinux> connection) + BlockingTaskHelper(base::ScopedFD fd, + scoped_refptr<HidDeviceInfo> device_info, + base::WeakPtr<HidConnectionLinux> connection) : fd_(std::move(fd)), connection_(connection), origin_task_runner_(base::ThreadTaskRunnerHandle::Get()) { - sequence_checker_.DetachFromSequence(); + DETACH_FROM_SEQUENCE(sequence_checker_); // Report buffers must always have room for the report ID. report_buffer_size_ = device_info->max_input_report_size() + 1; has_report_id_ = device_info->has_report_id(); } - ~FileThreadHelper() { DCHECK(sequence_checker_.CalledOnValidSequence()); } + ~BlockingTaskHelper() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); } // Starts the FileDescriptorWatcher that reads input events from the device. // Must be called on a thread that has a base::MessageLoopForIO. void Start() { - DCHECK(sequence_checker_.CalledOnValidSequence()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); base::ThreadRestrictions::AssertIOAllowed(); file_watcher_ = base::FileDescriptorWatcher::WatchReadable( - fd_.get(), base::Bind(&FileThreadHelper::OnFileCanReadWithoutBlocking, + fd_.get(), base::Bind(&BlockingTaskHelper::OnFileCanReadWithoutBlocking, base::Unretained(this))); } void Write(scoped_refptr<net::IOBuffer> buffer, size_t size, const WriteCallback& callback) { - DCHECK(sequence_checker_.CalledOnValidSequence()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); ssize_t result = HANDLE_EINTR(write(fd_.get(), buffer->data(), size)); if (result < 0) { HID_PLOG(EVENT) << "Write failed"; @@ -77,7 +77,7 @@ class HidConnectionLinux::FileThreadHelper { void GetFeatureReport(uint8_t report_id, scoped_refptr<net::IOBufferWithSize> buffer, const ReadCallback& callback) { - DCHECK(sequence_checker_.CalledOnValidSequence()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); int result = HANDLE_EINTR( ioctl(fd_.get(), HIDIOCGFEATURE(buffer->size()), buffer->data())); if (result < 0) { @@ -103,7 +103,7 @@ class HidConnectionLinux::FileThreadHelper { void SendFeatureReport(scoped_refptr<net::IOBuffer> buffer, size_t size, const WriteCallback& callback) { - DCHECK(sequence_checker_.CalledOnValidSequence()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); int result = HANDLE_EINTR(ioctl(fd_.get(), HIDIOCSFEATURE(size), buffer->data())); if (result < 0) { @@ -116,7 +116,7 @@ class HidConnectionLinux::FileThreadHelper { private: void OnFileCanReadWithoutBlocking() { - DCHECK(sequence_checker_.CalledOnValidSequence()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(report_buffer_size_)); char* data = buffer->data(); @@ -151,7 +151,7 @@ class HidConnectionLinux::FileThreadHelper { connection_, buffer, bytes_read)); } - base::SequenceChecker sequence_checker_; + SEQUENCE_CHECKER(sequence_checker_); base::ScopedFD fd_; size_t report_buffer_size_; bool has_report_id_; @@ -159,7 +159,7 @@ class HidConnectionLinux::FileThreadHelper { const scoped_refptr<base::SequencedTaskRunner> origin_task_runner_; std::unique_ptr<base::FileDescriptorWatcher::Controller> file_watcher_; - DISALLOW_COPY_AND_ASSIGN(FileThreadHelper); + DISALLOW_COPY_AND_ASSIGN(BlockingTaskHelper); }; HidConnectionLinux::HidConnectionLinux( @@ -169,15 +169,15 @@ HidConnectionLinux::HidConnectionLinux( : HidConnection(device_info), blocking_task_runner_(std::move(blocking_task_runner)), weak_factory_(this) { - helper_ = base::MakeUnique<FileThreadHelper>(std::move(fd), device_info, - weak_factory_.GetWeakPtr()); + helper_ = base::MakeUnique<BlockingTaskHelper>(std::move(fd), device_info, + weak_factory_.GetWeakPtr()); blocking_task_runner_->PostTask( FROM_HERE, - base::Bind(&FileThreadHelper::Start, base::Unretained(helper_.get()))); + base::Bind(&BlockingTaskHelper::Start, base::Unretained(helper_.get()))); } HidConnectionLinux::~HidConnectionLinux() { - DCHECK(sequence_checker_.CalledOnValidSequence()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); } void HidConnectionLinux::PlatformClose() { @@ -207,7 +207,7 @@ void HidConnectionLinux::PlatformWrite(scoped_refptr<net::IOBuffer> buffer, // buffer can be used directly. blocking_task_runner_->PostTask( FROM_HERE, - base::Bind(&FileThreadHelper::Write, base::Unretained(helper_.get()), + base::Bind(&BlockingTaskHelper::Write, base::Unretained(helper_.get()), buffer, size, callback)); } @@ -223,7 +223,7 @@ void HidConnectionLinux::PlatformGetFeatureReport( blocking_task_runner_->PostTask( FROM_HERE, - base::Bind(&FileThreadHelper::GetFeatureReport, + base::Bind(&BlockingTaskHelper::GetFeatureReport, base::Unretained(helper_.get()), report_id, buffer, callback)); } @@ -235,7 +235,7 @@ void HidConnectionLinux::PlatformSendFeatureReport( // buffer can be used directly. blocking_task_runner_->PostTask( FROM_HERE, - base::Bind(&FileThreadHelper::SendFeatureReport, + base::Bind(&BlockingTaskHelper::SendFeatureReport, base::Unretained(helper_.get()), buffer, size, callback)); } diff --git a/chromium/device/hid/hid_connection_linux.h b/chromium/device/hid/hid_connection_linux.h index 574c732638b..1231d58a988 100644 --- a/chromium/device/hid/hid_connection_linux.h +++ b/chromium/device/hid/hid_connection_linux.h @@ -31,7 +31,7 @@ class HidConnectionLinux : public HidConnection { private: friend class base::RefCountedThreadSafe<HidConnectionLinux>; - class FileThreadHelper; + class BlockingTaskHelper; ~HidConnectionLinux() override; @@ -50,17 +50,17 @@ class HidConnectionLinux : public HidConnection { void ProcessInputReport(scoped_refptr<net::IOBuffer> buffer, size_t size); void ProcessReadQueue(); - // This object lives on the sequence to which |blocking_task_runner_| posts + // |helper_| lives on the sequence to which |blocking_task_runner_| posts // tasks so all calls must be posted there including this object's // destruction. - std::unique_ptr<FileThreadHelper> helper_; + std::unique_ptr<BlockingTaskHelper> helper_; const scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_; std::queue<PendingHidReport> pending_reports_; std::queue<PendingHidRead> pending_reads_; - base::SequenceChecker sequence_checker_; + SEQUENCE_CHECKER(sequence_checker_); base::WeakPtrFactory<HidConnectionLinux> weak_factory_; diff --git a/chromium/device/hid/hid_connection_mac.cc b/chromium/device/hid/hid_connection_mac.cc index c13fc2b0d8c..69b3c6f5626 100644 --- a/chromium/device/hid/hid_connection_mac.cc +++ b/chromium/device/hid/hid_connection_mac.cc @@ -10,9 +10,11 @@ #include "base/numerics/safe_math.h" #include "base/single_thread_task_runner.h" #include "base/strings/stringprintf.h" +#include "base/task_scheduler/post_task.h" #include "base/threading/thread_task_runner_handle.h" #include "components/device_event_log/device_event_log.h" #include "device/hid/hid_connection_mac.h" +#include "device/hid/hid_service.h" namespace device { @@ -24,23 +26,19 @@ std::string HexErrorCode(IOReturn error_code) { } // namespace -HidConnectionMac::HidConnectionMac( - base::ScopedCFTypeRef<IOHIDDeviceRef> device, - scoped_refptr<HidDeviceInfo> device_info, - scoped_refptr<base::SingleThreadTaskRunner> file_task_runner) +HidConnectionMac::HidConnectionMac(base::ScopedCFTypeRef<IOHIDDeviceRef> device, + scoped_refptr<HidDeviceInfo> device_info) : HidConnection(device_info), device_(std::move(device)), - file_task_runner_(file_task_runner) { - task_runner_ = base::ThreadTaskRunnerHandle::Get(); - DCHECK(task_runner_.get()); - + task_runner_(base::ThreadTaskRunnerHandle::Get()), + blocking_task_runner_(base::CreateSequencedTaskRunnerWithTraits( + HidService::kBlockingTaskTraits)) { IOHIDDeviceScheduleWithRunLoop( device_.get(), CFRunLoopGetMain(), kCFRunLoopDefaultMode); size_t expected_report_size = device_info->max_input_report_size(); - if (device_info->has_report_id()) { + if (device_info->has_report_id()) expected_report_size++; - } inbound_buffer_.resize(expected_report_size); if (inbound_buffer_.size() > 0) { @@ -54,8 +52,7 @@ HidConnectionMac::HidConnectionMac( } } -HidConnectionMac::~HidConnectionMac() { -} +HidConnectionMac::~HidConnectionMac() {} void HidConnectionMac::PlatformClose() { if (inbound_buffer_.size() > 0) { @@ -89,34 +86,25 @@ void HidConnectionMac::PlatformRead(const ReadCallback& callback) { void HidConnectionMac::PlatformWrite(scoped_refptr<net::IOBuffer> buffer, size_t size, const WriteCallback& callback) { - file_task_runner_->PostTask(FROM_HERE, - base::Bind(&HidConnectionMac::SetReportAsync, - this, - kIOHIDReportTypeOutput, - buffer, - size, - callback)); + blocking_task_runner_->PostTask( + FROM_HERE, base::Bind(&HidConnectionMac::SetReportAsync, this, + kIOHIDReportTypeOutput, buffer, size, callback)); } void HidConnectionMac::PlatformGetFeatureReport(uint8_t report_id, const ReadCallback& callback) { - file_task_runner_->PostTask( - FROM_HERE, - base::Bind( - &HidConnectionMac::GetFeatureReportAsync, this, report_id, callback)); + blocking_task_runner_->PostTask( + FROM_HERE, base::Bind(&HidConnectionMac::GetFeatureReportAsync, this, + report_id, callback)); } void HidConnectionMac::PlatformSendFeatureReport( scoped_refptr<net::IOBuffer> buffer, size_t size, const WriteCallback& callback) { - file_task_runner_->PostTask(FROM_HERE, - base::Bind(&HidConnectionMac::SetReportAsync, - this, - kIOHIDReportTypeFeature, - buffer, - size, - callback)); + blocking_task_runner_->PostTask( + FROM_HERE, base::Bind(&HidConnectionMac::SetReportAsync, this, + kIOHIDReportTypeFeature, buffer, size, callback)); } // static @@ -249,6 +237,8 @@ void HidConnectionMac::SetReportAsync(IOHIDReportType report_type, } void HidConnectionMac::ReturnAsyncResult(const base::Closure& callback) { + // This function is used so that the last reference to |this| can be released + // on the thread where it was created. callback.Run(); } diff --git a/chromium/device/hid/hid_connection_mac.h b/chromium/device/hid/hid_connection_mac.h index da0dacd501c..914d5101195 100644 --- a/chromium/device/hid/hid_connection_mac.h +++ b/chromium/device/hid/hid_connection_mac.h @@ -17,7 +17,7 @@ #include "device/hid/hid_connection.h" namespace base { -class SingleThreadTaskRunner; +class SequencedTaskRunner; } namespace net { @@ -28,10 +28,8 @@ namespace device { class HidConnectionMac : public HidConnection { public: - HidConnectionMac( - base::ScopedCFTypeRef<IOHIDDeviceRef> device, - scoped_refptr<HidDeviceInfo> device_info, - scoped_refptr<base::SingleThreadTaskRunner> file_task_runner); + HidConnectionMac(base::ScopedCFTypeRef<IOHIDDeviceRef> device, + scoped_refptr<HidDeviceInfo> device_info); private: ~HidConnectionMac() override; @@ -65,8 +63,8 @@ class HidConnectionMac : public HidConnection { void ReturnAsyncResult(const base::Closure& callback); base::ScopedCFTypeRef<IOHIDDeviceRef> device_; - scoped_refptr<base::SingleThreadTaskRunner> task_runner_; - scoped_refptr<base::SingleThreadTaskRunner> file_task_runner_; + const scoped_refptr<base::SequencedTaskRunner> task_runner_; + const scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_; std::vector<uint8_t> inbound_buffer_; std::queue<PendingHidReport> pending_reports_; diff --git a/chromium/device/hid/hid_connection_unittest.cc b/chromium/device/hid/hid_connection_unittest.cc index f05d79dc86f..590c27281f2 100644 --- a/chromium/device/hid/hid_connection_unittest.cc +++ b/chromium/device/hid/hid_connection_unittest.cc @@ -15,6 +15,7 @@ #include "base/run_loop.h" #include "base/scoped_observer.h" #include "base/strings/utf_string_conversions.h" +#include "base/test/scoped_task_environment.h" #include "base/test/test_io_thread.h" #include "device/hid/hid_service.h" #include "device/test/test_device_client.h" @@ -148,18 +149,20 @@ class TestIoCallback { } // namespace class HidConnectionTest : public testing::Test { + public: + HidConnectionTest() + : scoped_task_environment_( + base::test::ScopedTaskEnvironment::MainThreadType::UI), + io_thread_(base::TestIOThread::kAutoStart) {} + protected: void SetUp() override { if (!UsbTestGadget::IsTestEnabled()) return; - message_loop_.reset(new base::MessageLoopForUI()); - io_thread_.reset(new base::TestIOThread(base::TestIOThread::kAutoStart)); - device_client_.reset(new TestDeviceClient(io_thread_->task_runner())); - service_ = DeviceClient::Get()->GetHidService(); ASSERT_TRUE(service_); - test_gadget_ = UsbTestGadget::Claim(io_thread_->task_runner()); + test_gadget_ = UsbTestGadget::Claim(io_thread_.task_runner()); ASSERT_TRUE(test_gadget_); ASSERT_TRUE(test_gadget_->SetType(UsbTestGadget::HID_ECHO)); @@ -169,9 +172,9 @@ class HidConnectionTest : public testing::Test { ASSERT_NE(device_id_, kInvalidHidDeviceId); } - std::unique_ptr<base::MessageLoopForUI> message_loop_; - std::unique_ptr<base::TestIOThread> io_thread_; - std::unique_ptr<TestDeviceClient> device_client_; + base::test::ScopedTaskEnvironment scoped_task_environment_; + base::TestIOThread io_thread_; + TestDeviceClient device_client_; HidService* service_; std::unique_ptr<UsbTestGadget> test_gadget_; HidDeviceId device_id_; diff --git a/chromium/device/hid/hid_service.cc b/chromium/device/hid/hid_service.cc index cee3980b9dc..f129a9776fd 100644 --- a/chromium/device/hid/hid_service.cc +++ b/chromium/device/hid/hid_service.cc @@ -36,26 +36,21 @@ void HidService::Observer::OnDeviceRemovedCleanup( scoped_refptr<HidDeviceInfo> device_info) { } -std::unique_ptr<HidService> HidService::Create( - scoped_refptr<base::SingleThreadTaskRunner> file_task_runner) { +// static +constexpr base::TaskTraits HidService::kBlockingTaskTraits; + +std::unique_ptr<HidService> HidService::Create() { #if defined(OS_LINUX) && defined(USE_UDEV) - return base::WrapUnique(new HidServiceLinux(file_task_runner)); + return base::WrapUnique(new HidServiceLinux()); #elif defined(OS_MACOSX) - return base::WrapUnique(new HidServiceMac(file_task_runner)); + return base::WrapUnique(new HidServiceMac()); #elif defined(OS_WIN) - return base::WrapUnique(new HidServiceWin(file_task_runner)); + return base::WrapUnique(new HidServiceWin()); #else return nullptr; #endif } -void HidService::Shutdown() { -#if DCHECK_IS_ON() - DCHECK(!did_shutdown_); - did_shutdown_ = true; -#endif -} - void HidService::GetDevices(const GetDevicesCallback& callback) { DCHECK(thread_checker_.CalledOnValidThread()); if (enumeration_ready_) { @@ -93,9 +88,6 @@ HidService::HidService() = default; HidService::~HidService() { DCHECK(thread_checker_.CalledOnValidThread()); -#if DCHECK_IS_ON() - DCHECK(did_shutdown_); -#endif } void HidService::AddDevice(scoped_refptr<HidDeviceInfo> device_info) { diff --git a/chromium/device/hid/hid_service.h b/chromium/device/hid/hid_service.h index c46ce131391..1144837fdc4 100644 --- a/chromium/device/hid/hid_service.h +++ b/chromium/device/hid/hid_service.h @@ -16,6 +16,7 @@ #include "base/memory/ref_counted.h" #include "base/observer_list.h" #include "base/single_thread_task_runner.h" +#include "base/task_scheduler/task_traits.h" #include "base/threading/thread_checker.h" #include "device/hid/hid_device_info.h" @@ -41,22 +42,19 @@ class HidService { virtual void OnDeviceRemovedCleanup(scoped_refptr<HidDeviceInfo> info); }; - typedef base::Callback<void(const std::vector<scoped_refptr<HidDeviceInfo>>&)> - GetDevicesCallback; - typedef base::Callback<void(scoped_refptr<HidConnection> connection)> - ConnectCallback; + using GetDevicesCallback = + base::Callback<void(const std::vector<scoped_refptr<HidDeviceInfo>>&)>; + using ConnectCallback = + base::Callback<void(scoped_refptr<HidConnection> connection)>; - // This function should be called on a thread with a MessageLoopForUI and be - // passed the task runner for a thread with a MessageLoopForIO. - static std::unique_ptr<HidService> Create( - scoped_refptr<base::SingleThreadTaskRunner> file_task_runner); + static constexpr base::TaskTraits kBlockingTaskTraits = { + base::MayBlock(), base::TaskPriority::USER_VISIBLE, + base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}; - virtual ~HidService(); + // This function should be called on a thread with a MessageLoopForUI. + static std::unique_ptr<HidService> Create(); - // Shuts down the HidService. Must be called before destroying the HidService - // when tasks can still be posted to the |file_task_runner| provided to - // Create(). - virtual void Shutdown(); + virtual ~HidService(); // Enumerates available devices. The provided callback will always be posted // to the calling thread's task runner. @@ -96,10 +94,6 @@ class HidService { std::vector<GetDevicesCallback> pending_enumerations_; base::ObserverList<Observer, true> observer_list_; -#if DCHECK_IS_ON() - bool did_shutdown_ = false; -#endif - DISALLOW_COPY_AND_ASSIGN(HidService); }; diff --git a/chromium/device/hid/hid_service_linux.cc b/chromium/device/hid/hid_service_linux.cc index 6b524466403..506fb07f726 100644 --- a/chromium/device/hid/hid_service_linux.cc +++ b/chromium/device/hid/hid_service_linux.cc @@ -20,17 +20,19 @@ #include "base/location.h" #include "base/macros.h" #include "base/memory/ptr_util.h" -#include "base/scoped_observer.h" +#include "base/sequence_checker.h" +#include "base/sequenced_task_runner.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" +#include "base/task_scheduler/post_task.h" #include "base/threading/thread_restrictions.h" #include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" #include "components/device_event_log/device_event_log.h" -#include "device/base/device_monitor_linux.h" #include "device/hid/hid_connection_linux.h" #include "device/hid/hid_device_info_linux.h" #include "device/udev_linux/scoped_udev.h" +#include "device/udev_linux/udev_watcher.h" #if defined(OS_CHROMEOS) #include "base/sys_info.h" @@ -52,13 +54,12 @@ const char kSysfsReportDescriptorKey[] = "report_descriptor"; struct HidServiceLinux::ConnectParams { ConnectParams(scoped_refptr<HidDeviceInfoLinux> device_info, - const ConnectCallback& callback, - scoped_refptr<base::SequencedTaskRunner> task_runner, - scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) + const ConnectCallback& callback) : device_info(std::move(device_info)), callback(callback), - task_runner(std::move(task_runner)), - blocking_task_runner(std::move(blocking_task_runner)) {} + task_runner(base::ThreadTaskRunnerHandle::Get()), + blocking_task_runner( + base::CreateSequencedTaskRunnerWithTraits(kBlockingTaskTraits)) {} ~ConnectParams() {} scoped_refptr<HidDeviceInfoLinux> device_info; @@ -68,67 +69,59 @@ struct HidServiceLinux::ConnectParams { base::ScopedFD fd; }; -class HidServiceLinux::FileThreadHelper : public DeviceMonitorLinux::Observer { +class HidServiceLinux::BlockingTaskHelper : public UdevWatcher::Observer { public: - FileThreadHelper(base::WeakPtr<HidServiceLinux> service, - scoped_refptr<base::SequencedTaskRunner> task_runner) - : observer_(this), service_(service), task_runner_(task_runner) { - thread_checker_.DetachFromThread(); + BlockingTaskHelper(base::WeakPtr<HidServiceLinux> service) + : service_(std::move(service)), + task_runner_(base::ThreadTaskRunnerHandle::Get()) { + DETACH_FROM_SEQUENCE(sequence_checker_); } - ~FileThreadHelper() override { - DCHECK(thread_checker_.CalledOnValidThread()); + ~BlockingTaskHelper() override { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); } void Start() { base::ThreadRestrictions::AssertIOAllowed(); - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DeviceMonitorLinux* monitor = DeviceMonitorLinux::GetInstance(); - observer_.Add(monitor); - monitor->Enumerate( - base::Bind(&FileThreadHelper::OnDeviceAdded, base::Unretained(this))); + watcher_ = UdevWatcher::StartWatching(this); + watcher_->EnumerateExistingDevices(); task_runner_->PostTask( FROM_HERE, base::Bind(&HidServiceLinux::FirstEnumerationComplete, service_)); } private: - // DeviceMonitorLinux::Observer: - void OnDeviceAdded(udev_device* device) override { - DCHECK(thread_checker_.CalledOnValidThread()); - const char* device_path = udev_device_get_syspath(device); - if (!device_path) { + // UdevWatcher::Observer + void OnDeviceAdded(ScopedUdevDevicePtr device) override { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + const char* device_path = udev_device_get_syspath(device.get()); + if (!device_path) return; - } HidDeviceId device_id = device_path; - const char* subsystem = udev_device_get_subsystem(device); - if (!subsystem || strcmp(subsystem, kHidrawSubsystem) != 0) { + const char* subsystem = udev_device_get_subsystem(device.get()); + if (!subsystem || strcmp(subsystem, kHidrawSubsystem) != 0) return; - } - const char* str_property = udev_device_get_devnode(device); - if (!str_property) { + const char* str_property = udev_device_get_devnode(device.get()); + if (!str_property) return; - } std::string device_node = str_property; - udev_device* parent = udev_device_get_parent(device); - if (!parent) { + udev_device* parent = udev_device_get_parent(device.get()); + if (!parent) return; - } const char* hid_id = udev_device_get_property_value(parent, kHIDID); - if (!hid_id) { + if (!hid_id) return; - } std::vector<std::string> parts = base::SplitString( hid_id, ":", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); - if (parts.size() != 3) { + if (parts.size() != 3) return; - } uint32_t int_property = 0; if (!HexStringToUInt(base::StringPiece(parts[1]), &int_property) || @@ -145,27 +138,22 @@ class HidServiceLinux::FileThreadHelper : public DeviceMonitorLinux::Observer { std::string serial_number; str_property = udev_device_get_property_value(parent, kHIDUnique); - if (str_property != NULL) { + if (str_property) serial_number = str_property; - } std::string product_name; str_property = udev_device_get_property_value(parent, kHIDName); - if (str_property != NULL) { + if (str_property) product_name = str_property; - } const char* parent_sysfs_path = udev_device_get_syspath(parent); - if (!parent_sysfs_path) { + if (!parent_sysfs_path) return; - } base::FilePath report_descriptor_path = base::FilePath(parent_sysfs_path).Append(kSysfsReportDescriptorKey); std::string report_descriptor_str; - if (!base::ReadFileToString(report_descriptor_path, - &report_descriptor_str)) { + if (!base::ReadFileToString(report_descriptor_path, &report_descriptor_str)) return; - } scoped_refptr<HidDeviceInfo> device_info(new HidDeviceInfoLinux( device_id, device_node, vendor_id, product_id, product_name, @@ -178,9 +166,9 @@ class HidServiceLinux::FileThreadHelper : public DeviceMonitorLinux::Observer { service_, device_info)); } - void OnDeviceRemoved(udev_device* device) override { - DCHECK(thread_checker_.CalledOnValidThread()); - const char* device_path = udev_device_get_syspath(device); + void OnDeviceRemoved(ScopedUdevDevicePtr device) override { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + const char* device_path = udev_device_get_syspath(device.get()); if (device_path) { task_runner_->PostTask( FROM_HERE, base::Bind(&HidServiceLinux::RemoveDevice, service_, @@ -188,37 +176,28 @@ class HidServiceLinux::FileThreadHelper : public DeviceMonitorLinux::Observer { } } - base::ThreadChecker thread_checker_; - ScopedObserver<DeviceMonitorLinux, DeviceMonitorLinux::Observer> observer_; + SEQUENCE_CHECKER(sequence_checker_); + std::unique_ptr<UdevWatcher> watcher_; // This weak pointer is only valid when checked on this task runner. base::WeakPtr<HidServiceLinux> service_; scoped_refptr<base::SequencedTaskRunner> task_runner_; - DISALLOW_COPY_AND_ASSIGN(FileThreadHelper); + DISALLOW_COPY_AND_ASSIGN(BlockingTaskHelper); }; -HidServiceLinux::HidServiceLinux( - scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) - : task_runner_(base::ThreadTaskRunnerHandle::Get()), - blocking_task_runner_(std::move(blocking_task_runner)), +HidServiceLinux::HidServiceLinux() + : blocking_task_runner_( + base::CreateSequencedTaskRunnerWithTraits(kBlockingTaskTraits)), weak_factory_(this) { - helper_ = base::MakeUnique<FileThreadHelper>(weak_factory_.GetWeakPtr(), - task_runner_); + helper_ = base::MakeUnique<BlockingTaskHelper>(weak_factory_.GetWeakPtr()); blocking_task_runner_->PostTask( FROM_HERE, - base::Bind(&FileThreadHelper::Start, base::Unretained(helper_.get()))); + base::Bind(&BlockingTaskHelper::Start, base::Unretained(helper_.get()))); } HidServiceLinux::~HidServiceLinux() { - DCHECK(!helper_); -} - -void HidServiceLinux::Shutdown() { - const bool did_post_task = - blocking_task_runner_->DeleteSoon(FROM_HERE, helper_.release()); - DCHECK(did_post_task); - HidService::Shutdown(); + blocking_task_runner_->DeleteSoon(FROM_HERE, helper_.release()); } void HidServiceLinux::Connect(const HidDeviceId& device_id, @@ -227,14 +206,14 @@ void HidServiceLinux::Connect(const HidDeviceId& device_id, const auto& map_entry = devices().find(device_id); if (map_entry == devices().end()) { - task_runner_->PostTask(FROM_HERE, base::Bind(callback, nullptr)); + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(callback, nullptr)); return; } scoped_refptr<HidDeviceInfoLinux> device_info = static_cast<HidDeviceInfoLinux*>(map_entry->second.get()); - std::unique_ptr<ConnectParams> params(new ConnectParams( - device_info, callback, task_runner_, blocking_task_runner_)); + auto params = base::MakeUnique<ConnectParams>(device_info, callback); #if defined(OS_CHROMEOS) chromeos::PermissionBrokerClient* client = @@ -248,7 +227,9 @@ void HidServiceLinux::Connect(const HidDeviceId& device_id, base::Bind(&HidServiceLinux::OnPathOpenComplete, base::Passed(¶ms)), error_callback); #else - blocking_task_runner_->PostTask( + scoped_refptr<base::SequencedTaskRunner> blocking_task_runner = + params->blocking_task_runner; + blocking_task_runner->PostTask( FROM_HERE, base::Bind(&HidServiceLinux::OpenOnBlockingThread, base::Passed(¶ms))); #endif // defined(OS_CHROMEOS) @@ -332,9 +313,9 @@ void HidServiceLinux::FinishOpen(std::unique_ptr<ConnectParams> params) { // static void HidServiceLinux::CreateConnection(std::unique_ptr<ConnectParams> params) { DCHECK(params->fd.is_valid()); - params->callback.Run(make_scoped_refptr(new HidConnectionLinux( + params->callback.Run(base::MakeRefCounted<HidConnectionLinux>( std::move(params->device_info), std::move(params->fd), - std::move(params->blocking_task_runner)))); + std::move(params->blocking_task_runner))); } } // namespace device diff --git a/chromium/device/hid/hid_service_linux.h b/chromium/device/hid/hid_service_linux.h index 17616ba6699..037945e6736 100644 --- a/chromium/device/hid/hid_service_linux.h +++ b/chromium/device/hid/hid_service_linux.h @@ -19,18 +19,16 @@ namespace device { class HidServiceLinux : public HidService { public: - HidServiceLinux( - scoped_refptr<base::SequencedTaskRunner> blocking_task_runner); + HidServiceLinux(); ~HidServiceLinux() override; // HidService: - void Shutdown() override; void Connect(const HidDeviceId& device_id, const ConnectCallback& callback) override; private: struct ConnectParams; - class FileThreadHelper; + class BlockingTaskHelper; // These functions implement the process of locating, requesting access to and // opening a device. Because this operation crosses multiple threads these @@ -49,12 +47,11 @@ class HidServiceLinux : public HidService { static void FinishOpen(std::unique_ptr<ConnectParams> params); static void CreateConnection(std::unique_ptr<ConnectParams> params); - const scoped_refptr<base::SequencedTaskRunner> task_runner_; const scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_; - // The helper lives on the FILE thread and holds a weak reference back to the - // service that owns it. - std::unique_ptr<FileThreadHelper> helper_; + // |helper_| lives on the sequence |blocking_task_runner_| posts to and holds + // a weak reference back to the service that owns it. + std::unique_ptr<BlockingTaskHelper> helper_; base::WeakPtrFactory<HidServiceLinux> weak_factory_; DISALLOW_COPY_AND_ASSIGN(HidServiceLinux); diff --git a/chromium/device/hid/hid_service_mac.cc b/chromium/device/hid/hid_service_mac.cc index 92d1617b9ff..056050342e7 100644 --- a/chromium/device/hid/hid_service_mac.cc +++ b/chromium/device/hid/hid_service_mac.cc @@ -19,6 +19,7 @@ #include "base/stl_util.h" #include "base/strings/stringprintf.h" #include "base/strings/sys_string_conversions.h" +#include "base/task_scheduler/post_task.h" #include "base/threading/thread_restrictions.h" #include "base/threading/thread_task_runner_handle.h" #include "components/device_event_log/device_event_log.h" @@ -90,12 +91,7 @@ scoped_refptr<HidDeviceInfo> CreateDeviceInfo( } // namespace -HidServiceMac::HidServiceMac( - scoped_refptr<base::SingleThreadTaskRunner> file_task_runner) - : file_task_runner_(file_task_runner), weak_factory_(this) { - task_runner_ = base::ThreadTaskRunnerHandle::Get(); - DCHECK(task_runner_.get()); - +HidServiceMac::HidServiceMac() : weak_factory_(this) { notify_port_.reset(IONotificationPortCreate(kIOMasterPortDefault)); CFRunLoopAddSource(CFRunLoopGetMain(), IONotificationPortGetRunLoopSource(notify_port_.get()), @@ -137,29 +133,27 @@ void HidServiceMac::Connect(const HidDeviceId& device_id, const auto& map_entry = devices().find(device_id); if (map_entry == devices().end()) { - task_runner_->PostTask(FROM_HERE, base::Bind(callback, nullptr)); + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(callback, nullptr)); return; } - file_task_runner_->PostTask( - FROM_HERE, - base::Bind(&HidServiceMac::OpenOnBlockingThread, map_entry->second, - task_runner_, weak_factory_.GetWeakPtr(), callback)); + base::PostTaskWithTraitsAndReplyWithResult( + FROM_HERE, kBlockingTaskTraits, + base::Bind(&HidServiceMac::OpenOnBlockingThread, map_entry->second), + base::Bind(&HidServiceMac::DeviceOpened, weak_factory_.GetWeakPtr(), + map_entry->second, callback)); } // static -void HidServiceMac::OpenOnBlockingThread( - scoped_refptr<HidDeviceInfo> device_info, - scoped_refptr<base::SingleThreadTaskRunner> task_runner, - base::WeakPtr<HidServiceMac> hid_service, - const ConnectCallback& callback) { +base::ScopedCFTypeRef<IOHIDDeviceRef> HidServiceMac::OpenOnBlockingThread( + scoped_refptr<HidDeviceInfo> device_info) { base::ScopedCFTypeRef<CFDictionaryRef> matching_dict( IORegistryEntryIDMatching(device_info->device_id())); if (!matching_dict.get()) { HID_LOG(EVENT) << "Failed to create matching dictionary for ID: " << device_info->device_id(); - task_runner->PostTask(FROM_HERE, base::Bind(callback, nullptr)); - return; + return base::ScopedCFTypeRef<IOHIDDeviceRef>(); } // IOServiceGetMatchingService consumes a reference to the matching dictionary @@ -169,36 +163,35 @@ void HidServiceMac::OpenOnBlockingThread( if (!service.get()) { HID_LOG(EVENT) << "IOService not found for ID: " << device_info->device_id(); - task_runner->PostTask(FROM_HERE, base::Bind(callback, nullptr)); - return; + return base::ScopedCFTypeRef<IOHIDDeviceRef>(); } base::ScopedCFTypeRef<IOHIDDeviceRef> hid_device( IOHIDDeviceCreate(kCFAllocatorDefault, service)); if (!hid_device) { HID_LOG(EVENT) << "Unable to create IOHIDDevice object."; - task_runner->PostTask(FROM_HERE, base::Bind(callback, nullptr)); - return; + return base::ScopedCFTypeRef<IOHIDDeviceRef>(); } IOReturn result = IOHIDDeviceOpen(hid_device, kIOHIDOptionsTypeNone); if (result != kIOReturnSuccess) { HID_LOG(EVENT) << "Failed to open device: " << HexErrorCode(result); - task_runner->PostTask(FROM_HERE, base::Bind(callback, nullptr)); - return; + return base::ScopedCFTypeRef<IOHIDDeviceRef>(); } - task_runner->PostTask( - FROM_HERE, base::Bind(&HidServiceMac::DeviceOpened, hid_service, - device_info, base::Passed(&hid_device), callback)); + return hid_device; } void HidServiceMac::DeviceOpened( scoped_refptr<HidDeviceInfo> device_info, - base::ScopedCFTypeRef<IOHIDDeviceRef> hid_device, - const ConnectCallback& callback) { - callback.Run(make_scoped_refptr(new HidConnectionMac( - std::move(hid_device), std::move(device_info), file_task_runner_))); + const ConnectCallback& callback, + base::ScopedCFTypeRef<IOHIDDeviceRef> hid_device) { + if (hid_device) { + callback.Run(base::MakeRefCounted<HidConnectionMac>( + std::move(hid_device), std::move(device_info))); + } else { + callback.Run(nullptr); + } } // static diff --git a/chromium/device/hid/hid_service_mac.h b/chromium/device/hid/hid_service_mac.h index 7d6c0531d50..7e238f3fb96 100644 --- a/chromium/device/hid/hid_service_mac.h +++ b/chromium/device/hid/hid_service_mac.h @@ -19,29 +19,22 @@ #include "base/memory/weak_ptr.h" #include "device/hid/hid_service.h" -namespace base { -class SingleThreadTaskRunner; -} - namespace device { class HidServiceMac : public HidService { public: - HidServiceMac(scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner); + HidServiceMac(); ~HidServiceMac() override; void Connect(const HidDeviceId& device_id, const ConnectCallback& connect) override; private: - static void OpenOnBlockingThread( - scoped_refptr<HidDeviceInfo> device_info, - scoped_refptr<base::SingleThreadTaskRunner> task_runner, - base::WeakPtr<HidServiceMac> hid_service, - const ConnectCallback& callback); + static base::ScopedCFTypeRef<IOHIDDeviceRef> OpenOnBlockingThread( + scoped_refptr<HidDeviceInfo> device_info); void DeviceOpened(scoped_refptr<HidDeviceInfo> device_info, - base::ScopedCFTypeRef<IOHIDDeviceRef> hid_device, - const ConnectCallback& callback); + const ConnectCallback& callback, + base::ScopedCFTypeRef<IOHIDDeviceRef> hid_device); // IOService matching callbacks. static void FirstMatchCallback(void* context, io_iterator_t iterator); @@ -55,13 +48,6 @@ class HidServiceMac : public HidService { base::mac::ScopedIOObject<io_iterator_t> devices_added_iterator_; base::mac::ScopedIOObject<io_iterator_t> devices_removed_iterator_; - // The task runner for the thread on which this service was created. - scoped_refptr<base::SingleThreadTaskRunner> task_runner_; - - // The task runner for the FILE thread of the application using this service - // on which slow running I/O operations can be performed. - scoped_refptr<base::SingleThreadTaskRunner> file_task_runner_; - base::WeakPtrFactory<HidServiceMac> weak_factory_; DISALLOW_COPY_AND_ASSIGN(HidServiceMac); diff --git a/chromium/device/hid/hid_service_unittest.cc b/chromium/device/hid/hid_service_unittest.cc new file mode 100644 index 00000000000..4da84d480cf --- /dev/null +++ b/chromium/device/hid/hid_service_unittest.cc @@ -0,0 +1,47 @@ +// Copyright 2017 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 "device/hid/hid_service.h" +#include "base/bind.h" +#include "base/run_loop.h" +#include "base/test/scoped_task_environment.h" +#include "device/test/test_device_client.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace device { + +namespace { + +class HidServiceTest : public ::testing::Test { + public: + HidServiceTest() + : scoped_task_environment_( + base::test::ScopedTaskEnvironment::MainThreadType::UI) {} + + private: + base::test::ScopedTaskEnvironment scoped_task_environment_; + TestDeviceClient device_client_; +}; + +void OnGetDevices(const base::Closure& quit_closure, + const std::vector<scoped_refptr<HidDeviceInfo>>& devices) { + // Since there's no guarantee that any devices are connected at the moment + // this test doesn't assume anything about the result but it at least verifies + // that devices can be enumerated without the application crashing. + quit_closure.Run(); +} + +} // namespace + +TEST_F(HidServiceTest, GetDevices) { + // The HID service is not available on all platforms. + HidService* service = DeviceClient::Get()->GetHidService(); + if (service) { + base::RunLoop loop; + service->GetDevices(base::Bind(&OnGetDevices, loop.QuitClosure())); + loop.Run(); + } +} + +} // namespace device diff --git a/chromium/device/hid/hid_service_win.cc b/chromium/device/hid/hid_service_win.cc index a7f252eefd4..0fc0c06ccd5 100644 --- a/chromium/device/hid/hid_service_win.cc +++ b/chromium/device/hid/hid_service_win.cc @@ -22,6 +22,7 @@ #include "base/sequenced_task_runner.h" #include "base/strings/string_util.h" #include "base/strings/sys_string_conversions.h" +#include "base/task_scheduler/post_task.h" #include "base/threading/sequenced_task_runner_handle.h" #include "components/device_event_log/device_event_log.h" #include "device/hid/hid_connection_win.h" @@ -30,10 +31,10 @@ namespace device { -HidServiceWin::HidServiceWin( - scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) +HidServiceWin::HidServiceWin() : task_runner_(base::SequencedTaskRunnerHandle::Get()), - blocking_task_runner_(std::move(blocking_task_runner)), + blocking_task_runner_( + base::CreateSequencedTaskRunnerWithTraits(kBlockingTaskTraits)), device_observer_(this), weak_factory_(this) { DeviceMonitorWin* device_monitor = @@ -66,9 +67,8 @@ void HidServiceWin::Connect(const HidDeviceId& device_id, } task_runner_->PostTask( - FROM_HERE, - base::Bind(callback, make_scoped_refptr( - new HidConnectionWin(device_info, std::move(file))))); + FROM_HERE, base::Bind(callback, base::MakeRefCounted<HidConnectionWin>( + device_info, std::move(file)))); } // static diff --git a/chromium/device/hid/hid_service_win.h b/chromium/device/hid/hid_service_win.h index 519f8ed5b39..d544862d0e6 100644 --- a/chromium/device/hid/hid_service_win.h +++ b/chromium/device/hid/hid_service_win.h @@ -31,7 +31,7 @@ namespace device { class HidServiceWin : public HidService, public DeviceMonitorWin::Observer { public: - HidServiceWin(scoped_refptr<base::SequencedTaskRunner> blocking_task_runner); + HidServiceWin(); ~HidServiceWin() override; void Connect(const HidDeviceId& device_id, diff --git a/chromium/device/hid/mock_hid_service.cc b/chromium/device/hid/mock_hid_service.cc index 3b913cf696d..238e4165f1a 100644 --- a/chromium/device/hid/mock_hid_service.cc +++ b/chromium/device/hid/mock_hid_service.cc @@ -6,12 +6,9 @@ namespace device { -MockHidService::MockHidService() {} +MockHidService::MockHidService() = default; -MockHidService::~MockHidService() { - // Shutdown() must be called before the base class destructor. - Shutdown(); -} +MockHidService::~MockHidService() = default; void MockHidService::AddDevice(scoped_refptr<HidDeviceInfo> info) { HidService::AddDevice(info); diff --git a/chromium/device/media_transfer_protocol/OWNERS b/chromium/device/media_transfer_protocol/OWNERS index 9c18d8cf566..7f803eb8544 100644 --- a/chromium/device/media_transfer_protocol/OWNERS +++ b/chromium/device/media_transfer_protocol/OWNERS @@ -1,4 +1,4 @@ satorux@chromium.org thestig@chromium.org -# COMPONENT: Internals>Media +# COMPONENT: Platform>Apps>FileManager diff --git a/chromium/device/nfc/BUILD.gn b/chromium/device/nfc/BUILD.gn deleted file mode 100644 index 45dd3691bc6..00000000000 --- a/chromium/device/nfc/BUILD.gn +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -import("//build/config/features.gni") -import("//mojo/public/tools/bindings/mojom.gni") - -mojom("mojo_bindings") { - sources = [ - "nfc.mojom", - ] -} diff --git a/chromium/device/nfc/OWNERS b/chromium/device/nfc/OWNERS deleted file mode 100644 index 08850f42120..00000000000 --- a/chromium/device/nfc/OWNERS +++ /dev/null @@ -1,2 +0,0 @@ -per-file *.mojom=set noparent -per-file *.mojom=file://ipc/SECURITY_OWNERS diff --git a/chromium/device/nfc/android/BUILD.gn b/chromium/device/nfc/android/BUILD.gn deleted file mode 100644 index ed1f51d103a..00000000000 --- a/chromium/device/nfc/android/BUILD.gn +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright 2016 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. - -import("//build/config/android/config.gni") -import("//build/config/android/rules.gni") - -android_library("java") { - java_files = [ - "java/src/org/chromium/device/nfc/InvalidNfcMessageException.java", - "java/src/org/chromium/device/nfc/NfcImpl.java", - "java/src/org/chromium/device/nfc/NfcMessageValidator.java", - "java/src/org/chromium/device/nfc/NfcTagHandler.java", - "java/src/org/chromium/device/nfc/NfcTypeConverter.java", - ] - - deps = [ - "//base:base_java", - "//device/nfc:mojo_bindings_java", - "//mojo/public/java:bindings_java", - "//mojo/public/java:system_java", - ] -} diff --git a/chromium/device/nfc/android/java/src/org/chromium/device/nfc/OWNERS b/chromium/device/nfc/android/java/src/org/chromium/device/nfc/OWNERS deleted file mode 100644 index 44273291642..00000000000 --- a/chromium/device/nfc/android/java/src/org/chromium/device/nfc/OWNERS +++ /dev/null @@ -1,2 +0,0 @@ -per-file *TypeConverter*.*=set noparent -per-file *TypeConverter*.*=file://ipc/SECURITY_OWNERS
\ No newline at end of file diff --git a/chromium/device/nfc/nfc.mojom b/chromium/device/nfc/nfc.mojom deleted file mode 100644 index 3f344a15788..00000000000 --- a/chromium/device/nfc/nfc.mojom +++ /dev/null @@ -1,138 +0,0 @@ -// Copyright 2015 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. - -// TODO(rockot): This should probably be moved to nfc.mojom. -module device.nfc.mojom; - -enum NFCErrorType { - SECURITY, - NOT_SUPPORTED, - DEVICE_DISABLED, - NOT_FOUND, - INVALID_MESSAGE, - OPERATION_CANCELLED, - TIMER_EXPIRED, - CANNOT_CANCEL, - IO_ERROR -}; - -enum NFCRecordType { - EMPTY, - TEXT, - URL, - JSON, - OPAQUE_RECORD -}; - -enum NFCPushTarget { - // The target of a push operation must be the NFC tag. - TAG, - // The target of a push operation must be the NFC peer (device to device). - PEER, - // The target of a push operation must be either NFC tag or peer. - ANY -}; - -enum NFCWatchMode { - // Restricts scope of the watch operation. Only Web NFC messages must be - // used by matching algorithm. - WEBNFC_ONLY, - // Allows performing watch operation for all NFC messages. For example, NFC - // tags with valid NDEF messages. - ANY -}; - -struct NFCError { - NFCErrorType error_type; -}; - -struct NFCRecord { - // The type of NFCRecord. - NFCRecordType record_type; - - // Represents the IANA media type of the NFCRecord data field. - string? media_type; - - // Payload of the NFCRecord. - array<uint8> data; -}; - -struct NFCMessage { - // The body of the NFCMessage is a collection of NFCRecord objects. - array<NFCRecord> data; - - // The |url| field is an ASCII serialized origin, optionally followed by a URL - // path. It represents Web NFC id, that can be used for matching Web NFC - // content with the filter specified by |url| field in NFCWatchOptions. - string? url; - - // Maximum size of NFC message that can be sent over IPC is 32KB. - const uint32 kMaxSize = 32768; -}; - -struct NFCPushOptions { - // The target of the push operation. - NFCPushTarget target; - - // The timeout for the push operation, in milliseconds. - double timeout; - - // If the property is true, the push operation will suspend active watchers - // until its completion. - bool ignore_read; -}; - -struct NFCRecordTypeFilter { - NFCRecordType record_type; -}; - -struct NFCWatchOptions { - // Defines filtering constraint for NFC messages with specified |url|. - string? url; - - // Defines filtering constraint for NFC records with specified record type. - NFCRecordTypeFilter? record_filter; - - // Defines media type filtering constraint. - string? media_type; - - // Defines mode of watch operation. - NFCWatchMode mode; -}; - -interface NFC { - // NFCClient interface is used to notify |client| when NFCMessage matches one - // or more pending watch operations. - SetClient(NFCClient client); - - // Pushes data to NFC device. - // NFCPushOptions specify timeout and type of device where data should be - // pushed. If timeout is defined and data is not pushed before timeout is - // expired, callback with corresponding error is called. - Push(NFCMessage message, NFCPushOptions? options) => (NFCError? error); - - // Cancels pending push request. - CancelPush(NFCPushTarget target) => (NFCError? error); - - // Starts watching for nearby NFC devices with data that matches - // NFCWatchOptions filtering criteria. On success, watch id is returned. - Watch(NFCWatchOptions options) => (uint32 id, NFCError? error); - - // Cancels watch operation with provided id. - CancelWatch (uint32 id) => (NFCError? error); - - // Cancels all watch operations. - CancelAllWatches () => (NFCError? error); - - // Suspends all pending NFC operations. Could be used when web page - // visibility or focus is lost. - SuspendNFCOperations(); - - // Resumes all suspended NFC operations. - ResumeNFCOperations(); -}; - -interface NFCClient { - OnWatch(array<uint32> watch_ids, NFCMessage message); -}; diff --git a/chromium/device/power_save_blocker/BUILD.gn b/chromium/device/power_save_blocker/BUILD.gn index 93e01d4a72e..3d5a1273e00 100644 --- a/chromium/device/power_save_blocker/BUILD.gn +++ b/chromium/device/power_save_blocker/BUILD.gn @@ -54,8 +54,8 @@ component("power_save_blocker") { } if (is_android) { - deps += [ - ":jni_headers", + deps += [ ":jni_headers" ] + public_deps = [ "//ui/android", ] } diff --git a/chromium/device/power_save_blocker/power_save_blocker_android.cc b/chromium/device/power_save_blocker/power_save_blocker_android.cc index c58903548de..3aa53467072 100644 --- a/chromium/device/power_save_blocker/power_save_blocker_android.cc +++ b/chromium/device/power_save_blocker/power_save_blocker_android.cc @@ -9,6 +9,7 @@ #include "base/location.h" #include "base/logging.h" #include "base/macros.h" +#include "base/sequenced_task_runner.h" #include "jni/PowerSaveBlocker_jni.h" #include "ui/android/view_android.h" @@ -47,7 +48,7 @@ PowerSaveBlocker::Delegate::Delegate( PowerSaveBlocker::Delegate::~Delegate() {} void PowerSaveBlocker::Delegate::ApplyBlock(ui::ViewAndroid* view_android) { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); DCHECK(view_android); ScopedJavaLocalRef<jobject> obj(java_power_save_blocker_); @@ -59,7 +60,7 @@ void PowerSaveBlocker::Delegate::ApplyBlock(ui::ViewAndroid* view_android) { } void PowerSaveBlocker::Delegate::RemoveBlock() { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); ScopedJavaLocalRef<jobject> obj(java_power_save_blocker_); Java_PowerSaveBlocker_removeBlock(AttachCurrentThread(), obj); @@ -84,7 +85,7 @@ PowerSaveBlocker::~PowerSaveBlocker() { } void PowerSaveBlocker::InitDisplaySleepBlocker(ui::ViewAndroid* view_android) { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); DCHECK(view_android); delegate_ = new Delegate(ui_task_runner_); diff --git a/chromium/device/power_save_blocker/power_save_blocker_chromeos.cc b/chromium/device/power_save_blocker/power_save_blocker_chromeos.cc index f24a0fea7c9..f3390147046 100644 --- a/chromium/device/power_save_blocker/power_save_blocker_chromeos.cc +++ b/chromium/device/power_save_blocker/power_save_blocker_chromeos.cc @@ -11,6 +11,7 @@ #include "base/logging.h" #include "base/macros.h" #include "base/memory/ref_counted.h" +#include "base/sequenced_task_runner.h" #include "chromeos/dbus/power_policy_controller.h" namespace device { @@ -48,7 +49,7 @@ class PowerSaveBlocker::Delegate ui_task_runner_(ui_task_runner) {} void ApplyBlock() { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); if (!chromeos::PowerPolicyController::IsInitialized()) return; @@ -68,7 +69,7 @@ class PowerSaveBlocker::Delegate } void RemoveBlock() { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); if (!chromeos::PowerPolicyController::IsInitialized()) return; diff --git a/chromium/device/power_save_blocker/power_save_blocker_win.cc b/chromium/device/power_save_blocker/power_save_blocker_win.cc index 7b0166bd11e..2d257224def 100644 --- a/chromium/device/power_save_blocker/power_save_blocker_win.cc +++ b/chromium/device/power_save_blocker/power_save_blocker_win.cc @@ -9,6 +9,7 @@ #include "base/bind.h" #include "base/logging.h" #include "base/macros.h" +#include "base/sequenced_task_runner.h" #include "base/strings/utf_string_conversions.h" #include "base/win/scoped_handle.h" #include "base/win/windows_version.h" @@ -114,7 +115,7 @@ class PowerSaveBlocker::Delegate }; void PowerSaveBlocker::Delegate::ApplyBlock() { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); if (base::win::GetVersion() < base::win::VERSION_WIN7) return ApplySimpleBlock(type_, 1); @@ -122,7 +123,7 @@ void PowerSaveBlocker::Delegate::ApplyBlock() { } void PowerSaveBlocker::Delegate::RemoveBlock() { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); if (base::win::GetVersion() < base::win::VERSION_WIN7) return ApplySimpleBlock(type_, -1); diff --git a/chromium/device/power_save_blocker/power_save_blocker_x11.cc b/chromium/device/power_save_blocker/power_save_blocker_x11.cc index 8c96590eaab..56e6584bcd5 100644 --- a/chromium/device/power_save_blocker/power_save_blocker_x11.cc +++ b/chromium/device/power_save_blocker/power_save_blocker_x11.cc @@ -27,6 +27,7 @@ #include "base/memory/ref_counted.h" #include "base/memory/singleton.h" #include "base/nix/xdg_util.h" +#include "base/single_thread_task_runner.h" #include "base/synchronization/lock.h" #include "dbus/bus.h" #include "dbus/message.h" @@ -216,7 +217,7 @@ void PowerSaveBlocker::Delegate::CleanUp() { } void PowerSaveBlocker::Delegate::InitOnUIThread() { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); base::AutoLock lock(lock_); api_ = SelectAPI(); @@ -239,7 +240,7 @@ bool PowerSaveBlocker::Delegate::ShouldBlock() const { } void PowerSaveBlocker::Delegate::ApplyBlock() { - DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(blocking_task_runner_->RunsTasksInCurrentSequence()); DCHECK(!bus_); // ApplyBlock() should only be called once. DCHECK(!block_inflight_); @@ -319,7 +320,7 @@ void PowerSaveBlocker::Delegate::ApplyBlock() { } void PowerSaveBlocker::Delegate::ApplyBlockFinished(dbus::Response* response) { - DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(blocking_task_runner_->RunsTasksInCurrentSequence()); DCHECK(bus_); DCHECK(block_inflight_); block_inflight_ = false; @@ -345,7 +346,7 @@ void PowerSaveBlocker::Delegate::ApplyBlockFinished(dbus::Response* response) { } void PowerSaveBlocker::Delegate::RemoveBlock() { - DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(blocking_task_runner_->RunsTasksInCurrentSequence()); DCHECK(bus_); // RemoveBlock() should only be called once. DCHECK(!unblock_inflight_); @@ -399,7 +400,7 @@ void PowerSaveBlocker::Delegate::RemoveBlock() { } void PowerSaveBlocker::Delegate::RemoveBlockFinished(dbus::Response* response) { - DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(blocking_task_runner_->RunsTasksInCurrentSequence()); DCHECK(bus_); unblock_inflight_ = false; @@ -414,7 +415,7 @@ void PowerSaveBlocker::Delegate::RemoveBlockFinished(dbus::Response* response) { } void PowerSaveBlocker::Delegate::XSSSuspendSet(bool suspend) { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); if (!XSSAvailable()) return; @@ -424,7 +425,7 @@ void PowerSaveBlocker::Delegate::XSSSuspendSet(bool suspend) { } bool PowerSaveBlocker::Delegate::DPMSEnabled() { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); XDisplay* display = gfx::GetXDisplay(); BOOL enabled = false; int dummy; @@ -436,7 +437,7 @@ bool PowerSaveBlocker::Delegate::DPMSEnabled() { } bool PowerSaveBlocker::Delegate::XSSAvailable() { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); // X Screen Saver isn't accessible in headless mode. if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kHeadless)) return false; @@ -455,7 +456,7 @@ bool PowerSaveBlocker::Delegate::XSSAvailable() { } DBusAPI PowerSaveBlocker::Delegate::SelectAPI() { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); // Power saving APIs are not accessible in headless mode. if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kHeadless)) return NO_API; diff --git a/chromium/device/screen_orientation/public/interfaces/screen_orientation.mojom b/chromium/device/screen_orientation/public/interfaces/screen_orientation.mojom index c5421884337..074adbed3f7 100644 --- a/chromium/device/screen_orientation/public/interfaces/screen_orientation.mojom +++ b/chromium/device/screen_orientation/public/interfaces/screen_orientation.mojom @@ -26,4 +26,10 @@ interface ScreenOrientationListener { // informs the browser process that it can stop accurately listening to the // screen orientation if no other process cares about it. Stop(); + + // Queries whether accelerometer auto rotation of screen orientation is + // enabled, or the user has locked the screen orientation at the OS level. + // This can be called at any time, whether or not the listener is started. + // It's currently only implemented on Android. + IsAutoRotateEnabledByUser() => (bool enabled); }; diff --git a/chromium/device/sensors/BUILD.gn b/chromium/device/sensors/BUILD.gn index 659932fe2eb..4a217b68fc7 100644 --- a/chromium/device/sensors/BUILD.gn +++ b/chromium/device/sensors/BUILD.gn @@ -10,8 +10,6 @@ if (is_android) { component("sensors") { sources = [ - "ambient_light_mac.cc", - "ambient_light_mac.h", "android/device_sensor_jni_registrar.cc", "android/device_sensor_jni_registrar.h", "data_fetcher_shared_memory.h", diff --git a/chromium/device/sensors/OWNERS b/chromium/device/sensors/OWNERS index f68d5d4216f..7b1e4f284f7 100644 --- a/chromium/device/sensors/OWNERS +++ b/chromium/device/sensors/OWNERS @@ -1,3 +1,4 @@ timvolodine@chromium.org -# COMPONENT: IO>DeviceOrientation +# COMPONENT: Blink>Sensor>DeviceOrientation +# TEAM: device-dev@chromium.org diff --git a/chromium/device/sensors/README.md b/chromium/device/sensors/README.md new file mode 100644 index 00000000000..58793c19f2d --- /dev/null +++ b/chromium/device/sensors/README.md @@ -0,0 +1,20 @@ +# Sensors + +`device/sensors` contains the platform-specific parts of the [DeviceOrientation +Events](https://www.w3.org/TR/orientation-event/) implementation. + +* Sensor [Mojo](../../mojo/README.md) interfaces are defined in the + `public/interfaces` subdirectory. +* The content renderer layer is located in `content/renderer/device_sensors`. +* The web exposed API is implemented in + `third_party/WebKit/Source/modules/device_orientation`. + +## Testing + +* Browser tests are located in `content/browser/device_sensors`. +* Layout tests are located in + `third_party/WebKit/LayoutTests/device_orientation`. +* Web platform tests are located in + `third_party/WebKit/LayoutTests/external/wpt/orientation-event` and are a + mirror of the [web-platform-tests GitHub + repository](https://github.com/w3c/web-platform-tests). diff --git a/chromium/device/sensors/ambient_light_mac.cc b/chromium/device/sensors/ambient_light_mac.cc deleted file mode 100644 index c9f36f5de17..00000000000 --- a/chromium/device/sensors/ambient_light_mac.cc +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright 2015 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. - -// This file is based on http://osxbook.com/book/bonus/chapter10/light/ - -#include "device/sensors/ambient_light_mac.h" - -#include <utility> - -#include "base/mac/scoped_cftyperef.h" -#include "base/mac/scoped_ioobject.h" - -namespace device { - -namespace { -enum LmuFunctionIndex { - kGetSensorReadingID = 0, // getSensorReading(int *, int *) - kGetLEDBrightnessID = 1, // getLEDBrightness(int, int *) - kSetLEDBrightnessID = 2, // setLEDBrightness(int, int, int *) - kSetLEDFadeID = 3, // setLEDFade(int, int, int, int *) -}; -} // namespace - -// static -std::unique_ptr<AmbientLightSensor> AmbientLightSensor::Create() { - std::unique_ptr<AmbientLightSensor> light_sensor(new AmbientLightSensor); - return light_sensor->Init() ? std::move(light_sensor) : nullptr; -} - -AmbientLightSensor::~AmbientLightSensor() { - if (!io_connection_) - IOServiceClose(io_connection_); -} - -AmbientLightSensor::AmbientLightSensor() : io_connection_(IO_OBJECT_NULL) {} - -bool AmbientLightSensor::Init() { - // Tested and verified by riju that the following call works on - // MacBookPro9,1 : Macbook Pro 15" (Mid 2012 model) - // MacBookPro10,1 : Macbook Pro 15" (Retina Display, Early 2013 model). - // MacBookPro10,2 : Macbook Pro 13" (Retina Display, Early 2013 model). - // MacBookAir5,2 : Macbook Air 13" (Mid 2012 model) (by François Beaufort). - // MacBookAir6,2 : Macbook Air 13" (Mid 2013 model). - // Testing plans : please download the code and follow the comments :- - // https://gist.github.com/riju/74af8c81a665e412d122/ - // and add an entry here about the model and the status returned by the code. - - // Look up a registered IOService object whose class is AppleLMUController. - base::mac::ScopedIOObject<io_service_t> service_object( - IOServiceGetMatchingService(kIOMasterPortDefault, - IOServiceMatching("AppleLMUController"))); - - // Return early if the ambient light sensor is not present. - if (!service_object) - return false; - - // Create a connection to the IOService object. - kern_return_t kr = - IOServiceOpen(service_object, mach_task_self(), 0, &io_connection_); - - // IOServiceOpen error. - if (kr != KERN_SUCCESS || io_connection_ == IO_OBJECT_NULL) - return false; - - uint64_t lux_values[2]; - return ReadSensorValue(lux_values); -} - -bool AmbientLightSensor::ReadSensorValue(uint64_t lux_values[2]) { - uint32_t scalar_output_count = 2; - kern_return_t kr = IOConnectCallMethod( - io_connection_, LmuFunctionIndex::kGetSensorReadingID, nullptr, 0, - nullptr, 0, lux_values, &scalar_output_count, nullptr, 0); - - return kr == KERN_SUCCESS; -} - -} // namespace device diff --git a/chromium/device/sensors/ambient_light_mac.h b/chromium/device/sensors/ambient_light_mac.h deleted file mode 100644 index f777dbc743e..00000000000 --- a/chromium/device/sensors/ambient_light_mac.h +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2015 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 DEVICE_SENSORS_AMBIENT_LIGHT_MAC_H_ -#define DEVICE_SENSORS_AMBIENT_LIGHT_MAC_H_ - -#include <IOKit/IOKitLib.h> -#include <stdint.h> - -#include <memory> - -#include "base/macros.h" - -namespace device { - -// Provides an interface to retrieve ambient light data from MacBooks. -class AmbientLightSensor { - public: - // Create AmbientLightSensor object, return NULL if no valid is sensor found. - static std::unique_ptr<AmbientLightSensor> Create(); - - ~AmbientLightSensor(); - - // Retrieve lux values from Ambient Light Sensor. - bool ReadSensorValue(uint64_t lux_value[2]); - - private: - AmbientLightSensor(); - - // Probe the local hardware looking for Ambient Light sensor and - // initialize an I/O connection to it. - bool Init(); - - // IOKit connection to the local sensor. - io_connect_t io_connection_; - - DISALLOW_COPY_AND_ASSIGN(AmbientLightSensor); -}; - -} // namespace device - -#endif // DEVICE_SENSORS_AMBIENT_LIGHT_MAC_H_ diff --git a/chromium/device/sensors/data_fetcher_shared_memory.h b/chromium/device/sensors/data_fetcher_shared_memory.h index e1e22e7e936..c1a92bc5637 100644 --- a/chromium/device/sensors/data_fetcher_shared_memory.h +++ b/chromium/device/sensors/data_fetcher_shared_memory.h @@ -10,7 +10,6 @@ #include "device/sensors/data_fetcher_shared_memory_base.h" #if !defined(OS_ANDROID) -#include "device/sensors/public/cpp/device_light_hardware_buffer.h" #include "device/sensors/public/cpp/device_motion_hardware_buffer.h" #include "device/sensors/public/cpp/device_orientation_hardware_buffer.h" #endif @@ -26,8 +25,6 @@ namespace device { #if defined(OS_CHROMEOS) class SensorManagerChromeOS; -#elif defined(OS_MACOSX) -class AmbientLightSensor; #endif class DEVICE_SENSOR_EXPORT DataFetcherSharedMemory @@ -48,7 +45,6 @@ class DEVICE_SENSOR_EXPORT DataFetcherSharedMemory #if !defined(OS_CHROMEOS) DeviceMotionHardwareBuffer* motion_buffer_ = nullptr; DeviceOrientationHardwareBuffer* orientation_buffer_ = nullptr; - DeviceLightHardwareBuffer* light_buffer_ = nullptr; #endif DeviceOrientationHardwareBuffer* orientation_absolute_buffer_ = nullptr; #endif @@ -59,13 +55,11 @@ class DEVICE_SENSOR_EXPORT DataFetcherSharedMemory void Fetch(unsigned consumer_bitmask) override; FetcherType GetType() const override; - std::unique_ptr<AmbientLightSensor> ambient_light_sensor_; std::unique_ptr<SuddenMotionSensor> sudden_motion_sensor_; #elif defined(OS_WIN) class SensorEventSink; class SensorEventSinkMotion; class SensorEventSinkOrientation; - class SensorEventSinkLight; FetcherType GetType() const override; @@ -79,7 +73,6 @@ class DEVICE_SENSOR_EXPORT DataFetcherSharedMemory base::win::ScopedComPtr<ISensor> sensor_inclinometer_absolute_; base::win::ScopedComPtr<ISensor> sensor_accelerometer_; base::win::ScopedComPtr<ISensor> sensor_gyrometer_; - base::win::ScopedComPtr<ISensor> sensor_light_; #endif DISALLOW_COPY_AND_ASSIGN(DataFetcherSharedMemory); diff --git a/chromium/device/sensors/data_fetcher_shared_memory_android.cc b/chromium/device/sensors/data_fetcher_shared_memory_android.cc index 5dec86a1ab0..3e08690600c 100644 --- a/chromium/device/sensors/data_fetcher_shared_memory_android.cc +++ b/chromium/device/sensors/data_fetcher_shared_memory_android.cc @@ -5,7 +5,6 @@ #include "device/sensors/data_fetcher_shared_memory.h" #include "base/logging.h" -#include "device/sensors/public/cpp/device_light_hardware_buffer.h" #include "device/sensors/public/cpp/device_motion_hardware_buffer.h" #include "device/sensors/public/cpp/device_orientation_hardware_buffer.h" #include "device/sensors/sensor_manager_android.h" @@ -33,10 +32,6 @@ bool DataFetcherSharedMemory::Start(ConsumerType consumer_type, void* buffer) { ->StartFetchingDeviceOrientationAbsoluteData( static_cast<DeviceOrientationHardwareBuffer*>(buffer)); return true; - case CONSUMER_TYPE_LIGHT: - SensorManagerAndroid::GetInstance()->StartFetchingDeviceLightData( - static_cast<DeviceLightHardwareBuffer*>(buffer)); - return true; default: NOTREACHED(); } @@ -55,9 +50,6 @@ bool DataFetcherSharedMemory::Stop(ConsumerType consumer_type) { SensorManagerAndroid::GetInstance() ->StopFetchingDeviceOrientationAbsoluteData(); return true; - case CONSUMER_TYPE_LIGHT: - SensorManagerAndroid::GetInstance()->StopFetchingDeviceLightData(); - return true; default: NOTREACHED(); } diff --git a/chromium/device/sensors/data_fetcher_shared_memory_base.cc b/chromium/device/sensors/data_fetcher_shared_memory_base.cc index 160bddb15dc..86e515c03fb 100644 --- a/chromium/device/sensors/data_fetcher_shared_memory_base.cc +++ b/chromium/device/sensors/data_fetcher_shared_memory_base.cc @@ -15,7 +15,6 @@ #include "base/stl_util.h" #include "base/threading/thread.h" #include "base/timer/timer.h" -#include "device/sensors/public/cpp/device_light_hardware_buffer.h" #include "device/sensors/public/cpp/device_motion_hardware_buffer.h" #include "device/sensors/public/cpp/device_orientation_hardware_buffer.h" @@ -30,8 +29,6 @@ size_t GetConsumerSharedMemoryBufferSize(ConsumerType consumer_type) { case CONSUMER_TYPE_ORIENTATION: case CONSUMER_TYPE_ORIENTATION_ABSOLUTE: return sizeof(DeviceOrientationHardwareBuffer); - case CONSUMER_TYPE_LIGHT: - return sizeof(DeviceLightHardwareBuffer); default: NOTREACHED(); } @@ -174,7 +171,6 @@ void DataFetcherSharedMemoryBase::Shutdown() { StopFetchingDeviceData(CONSUMER_TYPE_MOTION); StopFetchingDeviceData(CONSUMER_TYPE_ORIENTATION); StopFetchingDeviceData(CONSUMER_TYPE_ORIENTATION_ABSOLUTE); - StopFetchingDeviceData(CONSUMER_TYPE_LIGHT); // Ensure that the polling thread stops before entering the destructor of the // subclass, as the stopping of the polling thread causes tasks to execute diff --git a/chromium/device/sensors/data_fetcher_shared_memory_base_unittest.cc b/chromium/device/sensors/data_fetcher_shared_memory_base_unittest.cc index 2f01f707e2f..5f35feeb55f 100644 --- a/chromium/device/sensors/data_fetcher_shared_memory_base_unittest.cc +++ b/chromium/device/sensors/data_fetcher_shared_memory_base_unittest.cc @@ -10,7 +10,6 @@ #include "base/single_thread_task_runner.h" #include "base/synchronization/waitable_event.h" #include "base/threading/thread.h" -#include "device/sensors/public/cpp/device_light_hardware_buffer.h" #include "device/sensors/public/cpp/device_motion_hardware_buffer.h" #include "device/sensors/public/cpp/device_orientation_hardware_buffer.h" #include "testing/gtest/include/gtest/gtest.h" @@ -22,17 +21,13 @@ namespace { class FakeDataFetcher : public DataFetcherSharedMemoryBase { public: FakeDataFetcher() - : start_light_(base::WaitableEvent::ResetPolicy::AUTOMATIC, - base::WaitableEvent::InitialState::NOT_SIGNALED), - start_motion_(base::WaitableEvent::ResetPolicy::AUTOMATIC, + : start_motion_(base::WaitableEvent::ResetPolicy::AUTOMATIC, base::WaitableEvent::InitialState::NOT_SIGNALED), start_orientation_(base::WaitableEvent::ResetPolicy::AUTOMATIC, base::WaitableEvent::InitialState::NOT_SIGNALED), start_orientation_absolute_( base::WaitableEvent::ResetPolicy::AUTOMATIC, base::WaitableEvent::InitialState::NOT_SIGNALED), - stop_light_(base::WaitableEvent::ResetPolicy::AUTOMATIC, - base::WaitableEvent::InitialState::NOT_SIGNALED), stop_motion_(base::WaitableEvent::ResetPolicy::AUTOMATIC, base::WaitableEvent::InitialState::NOT_SIGNALED), stop_orientation_(base::WaitableEvent::ResetPolicy::AUTOMATIC, @@ -40,8 +35,6 @@ class FakeDataFetcher : public DataFetcherSharedMemoryBase { stop_orientation_absolute_( base::WaitableEvent::ResetPolicy::AUTOMATIC, base::WaitableEvent::InitialState::NOT_SIGNALED), - updated_light_(base::WaitableEvent::ResetPolicy::AUTOMATIC, - base::WaitableEvent::InitialState::NOT_SIGNALED), updated_motion_(base::WaitableEvent::ResetPolicy::AUTOMATIC, base::WaitableEvent::InitialState::NOT_SIGNALED), updated_orientation_(base::WaitableEvent::ResetPolicy::AUTOMATIC, @@ -49,7 +42,6 @@ class FakeDataFetcher : public DataFetcherSharedMemoryBase { updated_orientation_absolute_( base::WaitableEvent::ResetPolicy::AUTOMATIC, base::WaitableEvent::InitialState::NOT_SIGNALED), - light_buffer_(nullptr), motion_buffer_(nullptr), orientation_buffer_(nullptr), orientation_absolute_buffer_(nullptr) {} @@ -70,24 +62,12 @@ class FakeDataFetcher : public DataFetcherSharedMemoryBase { orientation_absolute_buffer_ = static_cast<DeviceOrientationHardwareBuffer*>(buffer); break; - case CONSUMER_TYPE_LIGHT: - light_buffer_ = static_cast<DeviceLightHardwareBuffer*>(buffer); - break; default: return false; } return true; } - void UpdateLight() { - DeviceLightHardwareBuffer* buffer = GetLightBuffer(); - ASSERT_TRUE(buffer); - buffer->seqlock.WriteBegin(); - buffer->data.value = 100; - buffer->seqlock.WriteEnd(); - updated_light_.Signal(); - } - void UpdateMotion() { DeviceMotionHardwareBuffer* buffer = GetMotionBuffer(); ASSERT_TRUE(buffer); @@ -116,8 +96,6 @@ class FakeDataFetcher : public DataFetcherSharedMemoryBase { updated_orientation_absolute_.Signal(); } - DeviceLightHardwareBuffer* GetLightBuffer() const { return light_buffer_; } - DeviceMotionHardwareBuffer* GetMotionBuffer() const { return motion_buffer_; } DeviceOrientationHardwareBuffer* GetOrientationBuffer() const { @@ -139,9 +117,6 @@ class FakeDataFetcher : public DataFetcherSharedMemoryBase { case CONSUMER_TYPE_ORIENTATION_ABSOLUTE: start_orientation_absolute_.Wait(); break; - case CONSUMER_TYPE_LIGHT: - start_light_.Wait(); - break; } } @@ -156,9 +131,6 @@ class FakeDataFetcher : public DataFetcherSharedMemoryBase { case CONSUMER_TYPE_ORIENTATION_ABSOLUTE: stop_orientation_absolute_.Wait(); break; - case CONSUMER_TYPE_LIGHT: - stop_light_.Wait(); - break; } } @@ -173,28 +145,21 @@ class FakeDataFetcher : public DataFetcherSharedMemoryBase { case CONSUMER_TYPE_ORIENTATION_ABSOLUTE: updated_orientation_absolute_.Wait(); break; - case CONSUMER_TYPE_LIGHT: - updated_light_.Wait(); - break; } } protected: - base::WaitableEvent start_light_; base::WaitableEvent start_motion_; base::WaitableEvent start_orientation_; base::WaitableEvent start_orientation_absolute_; - base::WaitableEvent stop_light_; base::WaitableEvent stop_motion_; base::WaitableEvent stop_orientation_; base::WaitableEvent stop_orientation_absolute_; - base::WaitableEvent updated_light_; base::WaitableEvent updated_motion_; base::WaitableEvent updated_orientation_; base::WaitableEvent updated_orientation_absolute_; private: - DeviceLightHardwareBuffer* light_buffer_; DeviceMotionHardwareBuffer* motion_buffer_; DeviceOrientationHardwareBuffer* orientation_buffer_; DeviceOrientationHardwareBuffer* orientation_absolute_buffer_; @@ -225,11 +190,6 @@ class FakeNonPollingDataFetcher : public FakeDataFetcher { UpdateOrientationAbsolute(); start_orientation_absolute_.Signal(); break; - case CONSUMER_TYPE_LIGHT: - if (update_) - UpdateLight(); - start_light_.Signal(); - break; default: return false; } @@ -247,9 +207,6 @@ class FakeNonPollingDataFetcher : public FakeDataFetcher { case CONSUMER_TYPE_ORIENTATION_ABSOLUTE: stop_orientation_absolute_.Signal(); break; - case CONSUMER_TYPE_LIGHT: - stop_light_.Signal(); - break; default: return false; } @@ -290,9 +247,6 @@ class FakePollingDataFetcher : public FakeDataFetcher { case CONSUMER_TYPE_ORIENTATION_ABSOLUTE: start_orientation_absolute_.Signal(); break; - case CONSUMER_TYPE_LIGHT: - start_light_.Signal(); - break; default: return false; } @@ -313,9 +267,6 @@ class FakePollingDataFetcher : public FakeDataFetcher { case CONSUMER_TYPE_ORIENTATION_ABSOLUTE: stop_orientation_absolute_.Signal(); break; - case CONSUMER_TYPE_LIGHT: - stop_light_.Signal(); - break; default: return false; } @@ -327,8 +278,7 @@ class FakePollingDataFetcher : public FakeDataFetcher { GetPollingMessageLoop()->task_runner()->BelongsToCurrentThread()); EXPECT_TRUE(consumer_bitmask & CONSUMER_TYPE_ORIENTATION || consumer_bitmask & CONSUMER_TYPE_ORIENTATION_ABSOLUTE || - consumer_bitmask & CONSUMER_TYPE_MOTION || - consumer_bitmask & CONSUMER_TYPE_LIGHT); + consumer_bitmask & CONSUMER_TYPE_MOTION); if (consumer_bitmask & CONSUMER_TYPE_ORIENTATION) UpdateOrientation(); @@ -336,8 +286,6 @@ class FakePollingDataFetcher : public FakeDataFetcher { UpdateOrientationAbsolute(); if (consumer_bitmask & CONSUMER_TYPE_MOTION) UpdateMotion(); - if (consumer_bitmask & CONSUMER_TYPE_LIGHT) - UpdateLight(); } FetcherType GetType() const override { return FETCHER_TYPE_POLLING_CALLBACK; } @@ -366,9 +314,6 @@ class FakeZeroDelayPollingDataFetcher : public FakeDataFetcher { case CONSUMER_TYPE_ORIENTATION_ABSOLUTE: start_orientation_absolute_.Signal(); break; - case CONSUMER_TYPE_LIGHT: - start_light_.Signal(); - break; default: return false; } @@ -389,9 +334,6 @@ class FakeZeroDelayPollingDataFetcher : public FakeDataFetcher { case CONSUMER_TYPE_ORIENTATION_ABSOLUTE: stop_orientation_absolute_.Signal(); break; - case CONSUMER_TYPE_LIGHT: - stop_light_.Signal(); - break; default: return false; } @@ -458,20 +400,6 @@ TEST(DataFetcherSharedMemoryBaseTest, DoesStartOrientationAbsolute) { fake_data_fetcher.WaitForStop(CONSUMER_TYPE_ORIENTATION_ABSOLUTE); } -TEST(DataFetcherSharedMemoryBaseTest, DoesStartLight) { - FakeNonPollingDataFetcher fake_data_fetcher; - EXPECT_EQ(DataFetcherSharedMemoryBase::FETCHER_TYPE_DEFAULT, - fake_data_fetcher.GetType()); - - EXPECT_TRUE(fake_data_fetcher.StartFetchingDeviceData(CONSUMER_TYPE_LIGHT)); - fake_data_fetcher.WaitForStart(CONSUMER_TYPE_LIGHT); - - EXPECT_EQ(100, fake_data_fetcher.GetLightBuffer()->data.value); - - fake_data_fetcher.StopFetchingDeviceData(CONSUMER_TYPE_LIGHT); - fake_data_fetcher.WaitForStop(CONSUMER_TYPE_LIGHT); -} - TEST(DataFetcherSharedMemoryBaseTest, DoesPollMotion) { FakePollingDataFetcher fake_data_fetcher; EXPECT_EQ(DataFetcherSharedMemoryBase::FETCHER_TYPE_POLLING_CALLBACK, @@ -521,21 +449,6 @@ TEST(DataFetcherSharedMemoryBaseTest, DoesPollOrientationAbsolute) { fake_data_fetcher.WaitForStop(CONSUMER_TYPE_ORIENTATION_ABSOLUTE); } -TEST(DataFetcherSharedMemoryBaseTest, DoesPollLight) { - FakePollingDataFetcher fake_data_fetcher; - EXPECT_EQ(DataFetcherSharedMemoryBase::FETCHER_TYPE_POLLING_CALLBACK, - fake_data_fetcher.GetType()); - - EXPECT_TRUE(fake_data_fetcher.StartFetchingDeviceData(CONSUMER_TYPE_LIGHT)); - fake_data_fetcher.WaitForStart(CONSUMER_TYPE_LIGHT); - fake_data_fetcher.WaitForUpdate(CONSUMER_TYPE_LIGHT); - - EXPECT_EQ(100, fake_data_fetcher.GetLightBuffer()->data.value); - - fake_data_fetcher.StopFetchingDeviceData(CONSUMER_TYPE_LIGHT); - fake_data_fetcher.WaitForStop(CONSUMER_TYPE_LIGHT); -} - TEST(DataFetcherSharedMemoryBaseTest, DoesPollMotionAndOrientation) { FakePollingDataFetcher fake_data_fetcher; EXPECT_EQ(DataFetcherSharedMemoryBase::FETCHER_TYPE_POLLING_CALLBACK, diff --git a/chromium/device/sensors/data_fetcher_shared_memory_chromeos.cc b/chromium/device/sensors/data_fetcher_shared_memory_chromeos.cc index ee12c57255a..1e63fe62a82 100644 --- a/chromium/device/sensors/data_fetcher_shared_memory_chromeos.cc +++ b/chromium/device/sensors/data_fetcher_shared_memory_chromeos.cc @@ -38,9 +38,6 @@ bool DataFetcherSharedMemory::Start(ConsumerType consumer_type, void* buffer) { orientation_absolute_buffer_->seqlock.WriteEnd(); return false; } - case CONSUMER_TYPE_LIGHT: - NOTIMPLEMENTED(); - return false; } NOTREACHED(); return false; @@ -61,9 +58,6 @@ bool DataFetcherSharedMemory::Stop(ConsumerType consumer_type) { orientation_absolute_buffer_ = nullptr; } return true; - case CONSUMER_TYPE_LIGHT: - NOTIMPLEMENTED(); - return false; } NOTREACHED(); return false; diff --git a/chromium/device/sensors/data_fetcher_shared_memory_default.cc b/chromium/device/sensors/data_fetcher_shared_memory_default.cc index 31bbd7a1901..12eeaaf9d02 100644 --- a/chromium/device/sensors/data_fetcher_shared_memory_default.cc +++ b/chromium/device/sensors/data_fetcher_shared_memory_default.cc @@ -28,15 +28,6 @@ bool SetOrientationBuffer(device::DeviceOrientationHardwareBuffer* buffer, return true; } -bool SetLightBuffer(device::DeviceLightHardwareBuffer* buffer, double lux) { - if (!buffer) - return false; - buffer->seqlock.WriteBegin(); - buffer->data.value = lux; - buffer->seqlock.WriteEnd(); - return true; -} - } // namespace namespace device { @@ -63,10 +54,6 @@ bool DataFetcherSharedMemory::Start(ConsumerType consumer_type, void* buffer) { orientation_absolute_buffer_ = static_cast<DeviceOrientationHardwareBuffer*>(buffer); return SetOrientationBuffer(orientation_absolute_buffer_, true); - case CONSUMER_TYPE_LIGHT: - light_buffer_ = static_cast<DeviceLightHardwareBuffer*>(buffer); - return SetLightBuffer(light_buffer_, - std::numeric_limits<double>::infinity()); default: NOTREACHED(); } @@ -81,8 +68,6 @@ bool DataFetcherSharedMemory::Stop(ConsumerType consumer_type) { return SetOrientationBuffer(orientation_buffer_, false); case CONSUMER_TYPE_ORIENTATION_ABSOLUTE: return SetOrientationBuffer(orientation_absolute_buffer_, false); - case CONSUMER_TYPE_LIGHT: - return SetLightBuffer(light_buffer_, -1); default: NOTREACHED(); } diff --git a/chromium/device/sensors/data_fetcher_shared_memory_mac.cc b/chromium/device/sensors/data_fetcher_shared_memory_mac.cc index b06c850ca48..b3aa760c055 100644 --- a/chromium/device/sensors/data_fetcher_shared_memory_mac.cc +++ b/chromium/device/sensors/data_fetcher_shared_memory_mac.cc @@ -9,30 +9,12 @@ #include "base/logging.h" #include "base/metrics/histogram_macros.h" #include "base/single_thread_task_runner.h" -#include "device/sensors/ambient_light_mac.h" -#include "device/sensors/public/cpp/device_util_mac.h" #include "third_party/sudden_motion_sensor/sudden_motion_sensor_mac.h" namespace device { const double kMeanGravity = 9.80665; -void FetchLight(AmbientLightSensor* sensor, DeviceLightHardwareBuffer* buffer) { - DCHECK(sensor); - DCHECK(buffer); - // Macbook pro has 2 lux values, left and right, we take the average. - // The raw sensor values are converted to lux using LMUvalueToLux(raw_value) - // similar to how it is done in Firefox. - uint64_t lux_value[2]; - if (!sensor->ReadSensorValue(lux_value)) - return; - uint64_t mean = (lux_value[0] + lux_value[1]) / 2; - double lux = LMUvalueToLux(mean); - buffer->seqlock.WriteBegin(); - buffer->data.value = lux; - buffer->seqlock.WriteEnd(); -} - void FetchMotion(SuddenMotionSensor* sensor, DeviceMotionHardwareBuffer* buffer) { DCHECK(sensor); @@ -117,15 +99,12 @@ DataFetcherSharedMemory::~DataFetcherSharedMemory() {} void DataFetcherSharedMemory::Fetch(unsigned consumer_bitmask) { DCHECK(GetPollingMessageLoop()->task_runner()->BelongsToCurrentThread()); DCHECK(consumer_bitmask & CONSUMER_TYPE_ORIENTATION || - consumer_bitmask & CONSUMER_TYPE_MOTION || - consumer_bitmask & CONSUMER_TYPE_LIGHT); + consumer_bitmask & CONSUMER_TYPE_MOTION); if (consumer_bitmask & CONSUMER_TYPE_ORIENTATION) FetchOrientation(sudden_motion_sensor_.get(), orientation_buffer_); if (consumer_bitmask & CONSUMER_TYPE_MOTION) FetchMotion(sudden_motion_sensor_.get(), motion_buffer_); - if (consumer_bitmask & CONSUMER_TYPE_LIGHT) - FetchLight(ambient_light_sensor_.get(), light_buffer_); } DataFetcherSharedMemory::FetcherType DataFetcherSharedMemory::GetType() const { @@ -189,20 +168,6 @@ bool DataFetcherSharedMemory::Start(ConsumerType consumer_type, void* buffer) { orientation_absolute_buffer_->seqlock.WriteEnd(); return false; } - case CONSUMER_TYPE_LIGHT: { - if (!ambient_light_sensor_) - ambient_light_sensor_ = AmbientLightSensor::Create(); - bool ambient_light_sensor_available = - ambient_light_sensor_.get() != nullptr; - - light_buffer_ = static_cast<DeviceLightHardwareBuffer*>(buffer); - if (!ambient_light_sensor_available) { - light_buffer_->seqlock.WriteBegin(); - light_buffer_->data.value = std::numeric_limits<double>::infinity(); - light_buffer_->seqlock.WriteEnd(); - } - return ambient_light_sensor_available; - } default: NOTREACHED(); } @@ -238,14 +203,6 @@ bool DataFetcherSharedMemory::Stop(ConsumerType consumer_type) { orientation_absolute_buffer_ = nullptr; } return true; - case CONSUMER_TYPE_LIGHT: - if (light_buffer_) { - light_buffer_->seqlock.WriteBegin(); - light_buffer_->data.value = -1; - light_buffer_->seqlock.WriteEnd(); - light_buffer_ = nullptr; - } - return true; default: NOTREACHED(); } diff --git a/chromium/device/sensors/data_fetcher_shared_memory_win.cc b/chromium/device/sensors/data_fetcher_shared_memory_win.cc index f2fa6c852f6..4ec59fa4641 100644 --- a/chromium/device/sensors/data_fetcher_shared_memory_win.cc +++ b/chromium/device/sensors/data_fetcher_shared_memory_win.cc @@ -8,6 +8,7 @@ #include <InitGuid.h> #include <PortableDeviceTypes.h> #include <Sensors.h> +#include <objbase.h> #include "base/logging.h" #include "base/macros.h" @@ -19,13 +20,6 @@ namespace { const double kMeanGravity = 9.80665; -void SetLightBuffer(device::DeviceLightHardwareBuffer* buffer, double lux) { - DCHECK(buffer); - buffer->seqlock.WriteBegin(); - buffer->data.value = lux; - buffer->seqlock.WriteEnd(); -} - } // namespace namespace device { @@ -223,37 +217,6 @@ class DataFetcherSharedMemory::SensorEventSinkMotion DISALLOW_COPY_AND_ASSIGN(SensorEventSinkMotion); }; -class DataFetcherSharedMemory::SensorEventSinkLight - : public DataFetcherSharedMemory::SensorEventSink { - public: - explicit SensorEventSinkLight(DeviceLightHardwareBuffer* const buffer) - : buffer_(buffer) {} - ~SensorEventSinkLight() override {} - - protected: - bool UpdateSharedMemoryBuffer(ISensor* sensor, - ISensorDataReport* new_data) override { - double lux; - bool has_lux; - - GetSensorValue(SENSOR_DATA_TYPE_LIGHT_LEVEL_LUX, new_data, &lux, &has_lux); - - if (!has_lux) { - // Could not get lux value. - return false; - } - - SetLightBuffer(buffer_, lux); - - return true; - } - - private: - DeviceLightHardwareBuffer* const buffer_; - - DISALLOW_COPY_AND_ASSIGN(SensorEventSinkLight); -}; - DataFetcherSharedMemory::DataFetcherSharedMemory() {} DataFetcherSharedMemory::~DataFetcherSharedMemory() {} @@ -271,8 +234,9 @@ bool DataFetcherSharedMemory::Start(ConsumerType consumer_type, void* buffer) { static_cast<DeviceOrientationHardwareBuffer*>(buffer); scoped_refptr<SensorEventSink> sink( new SensorEventSinkOrientation(orientation_buffer_)); - bool inclinometer_available = RegisterForSensor( - SENSOR_TYPE_INCLINOMETER_3D, sensor_inclinometer_.Receive(), sink); + bool inclinometer_available = + RegisterForSensor(SENSOR_TYPE_INCLINOMETER_3D, + sensor_inclinometer_.GetAddressOf(), sink); UMA_HISTOGRAM_BOOLEAN("InertialSensor.InclinometerWindowsAvailable", inclinometer_available); if (inclinometer_available) @@ -289,7 +253,7 @@ bool DataFetcherSharedMemory::Start(ConsumerType consumer_type, void* buffer) { // absolute angles. bool inclinometer_available = RegisterForSensor(SENSOR_TYPE_INCLINOMETER_3D, - sensor_inclinometer_absolute_.Receive(), sink); + sensor_inclinometer_absolute_.GetAddressOf(), sink); // TODO(timvolodine): consider adding UMA. if (inclinometer_available) return true; @@ -300,10 +264,11 @@ bool DataFetcherSharedMemory::Start(ConsumerType consumer_type, void* buffer) { motion_buffer_ = static_cast<DeviceMotionHardwareBuffer*>(buffer); scoped_refptr<SensorEventSink> sink( new SensorEventSinkMotion(motion_buffer_)); - bool accelerometer_available = RegisterForSensor( - SENSOR_TYPE_ACCELEROMETER_3D, sensor_accelerometer_.Receive(), sink); + bool accelerometer_available = + RegisterForSensor(SENSOR_TYPE_ACCELEROMETER_3D, + sensor_accelerometer_.GetAddressOf(), sink); bool gyrometer_available = RegisterForSensor( - SENSOR_TYPE_GYROMETER_3D, sensor_gyrometer_.Receive(), sink); + SENSOR_TYPE_GYROMETER_3D, sensor_gyrometer_.GetAddressOf(), sink); UMA_HISTOGRAM_BOOLEAN("InertialSensor.AccelerometerWindowsAvailable", accelerometer_available); UMA_HISTOGRAM_BOOLEAN("InertialSensor.GyrometerWindowsAvailable", @@ -317,20 +282,6 @@ bool DataFetcherSharedMemory::Start(ConsumerType consumer_type, void* buffer) { // if no sensors are available set buffer to ready, to fire null-events. SetBufferAvailableState(consumer_type, true); } break; - case CONSUMER_TYPE_LIGHT: { - light_buffer_ = static_cast<DeviceLightHardwareBuffer*>(buffer); - scoped_refptr<SensorEventSink> sink( - new SensorEventSinkLight(light_buffer_)); - bool sensor_light_available = RegisterForSensor( - SENSOR_TYPE_AMBIENT_LIGHT, sensor_light_.Receive(), sink); - if (sensor_light_available) { - SetLightBuffer(light_buffer_, -1); - return true; - } - - // if no sensors are available, fire an Infinity event. - SetLightBuffer(light_buffer_, std::numeric_limits<double>::infinity()); - } break; default: NOTREACHED(); } @@ -352,10 +303,6 @@ bool DataFetcherSharedMemory::Stop(ConsumerType consumer_type) { SetBufferAvailableState(consumer_type, false); motion_buffer_ = nullptr; return true; - case CONSUMER_TYPE_LIGHT: - SetLightBuffer(light_buffer_, -1); - light_buffer_ = nullptr; - return true; default: NOTREACHED(); } @@ -370,15 +317,16 @@ bool DataFetcherSharedMemory::RegisterForSensor( return false; base::win::ScopedComPtr<ISensorManager> sensor_manager; - HRESULT hr = sensor_manager.CreateInstance(CLSID_SensorManager); - if (FAILED(hr) || !sensor_manager.get()) + HRESULT hr = ::CoCreateInstance(CLSID_SensorManager, nullptr, CLSCTX_ALL, + IID_PPV_ARGS(&sensor_manager)); + if (FAILED(hr) || !sensor_manager.Get()) return false; base::win::ScopedComPtr<ISensorCollection> sensor_collection; hr = sensor_manager->GetSensorsByType(sensor_type, - sensor_collection.Receive()); + sensor_collection.GetAddressOf()); - if (FAILED(hr) || !sensor_collection.get()) + if (FAILED(hr) || !sensor_collection.Get()) return false; ULONG count = 0; @@ -391,22 +339,23 @@ bool DataFetcherSharedMemory::RegisterForSensor( return false; base::win::ScopedComPtr<IPortableDeviceValues> device_values; - if (SUCCEEDED(device_values.CreateInstance(CLSID_PortableDeviceValues))) { + if (SUCCEEDED(::CoCreateInstance(CLSID_PortableDeviceValues, nullptr, + CLSCTX_ALL, IID_PPV_ARGS(&device_values)))) { if (SUCCEEDED(device_values->SetUnsignedIntegerValue( SENSOR_PROPERTY_CURRENT_REPORT_INTERVAL, GetInterval().InMilliseconds()))) { base::win::ScopedComPtr<IPortableDeviceValues> return_values; - (*sensor)->SetProperties(device_values.get(), return_values.Receive()); + (*sensor)->SetProperties(device_values.Get(), + return_values.GetAddressOf()); } } base::win::ScopedComPtr<ISensorEvents> sensor_events; - hr = event_sink->QueryInterface(__uuidof(ISensorEvents), - sensor_events.ReceiveVoid()); - if (FAILED(hr) || !sensor_events.get()) + hr = event_sink->QueryInterface(IID_PPV_ARGS(&sensor_events)); + if (FAILED(hr) || !sensor_events.Get()) return false; - hr = (*sensor)->SetEventSink(sensor_events.get()); + hr = (*sensor)->SetEventSink(sensor_events.Get()); if (FAILED(hr)) return false; @@ -416,33 +365,27 @@ bool DataFetcherSharedMemory::RegisterForSensor( void DataFetcherSharedMemory::DisableSensors(ConsumerType consumer_type) { switch (consumer_type) { case CONSUMER_TYPE_ORIENTATION: - if (sensor_inclinometer_.get()) { + if (sensor_inclinometer_.Get()) { sensor_inclinometer_->SetEventSink(nullptr); sensor_inclinometer_.Reset(); } break; case CONSUMER_TYPE_ORIENTATION_ABSOLUTE: - if (sensor_inclinometer_absolute_.get()) { + if (sensor_inclinometer_absolute_.Get()) { sensor_inclinometer_absolute_->SetEventSink(nullptr); sensor_inclinometer_absolute_.Reset(); } break; case CONSUMER_TYPE_MOTION: - if (sensor_accelerometer_.get()) { + if (sensor_accelerometer_.Get()) { sensor_accelerometer_->SetEventSink(nullptr); sensor_accelerometer_.Reset(); } - if (sensor_gyrometer_.get()) { + if (sensor_gyrometer_.Get()) { sensor_gyrometer_->SetEventSink(nullptr); sensor_gyrometer_.Reset(); } break; - case CONSUMER_TYPE_LIGHT: - if (sensor_light_.get()) { - sensor_light_->SetEventSink(nullptr); - sensor_light_.Reset(); - } - break; default: NOTREACHED(); } diff --git a/chromium/device/sensors/device_sensor_host.cc b/chromium/device/sensors/device_sensor_host.cc index c0260f4e310..cd37326ca52 100644 --- a/chromium/device/sensors/device_sensor_host.cc +++ b/chromium/device/sensors/device_sensor_host.cc @@ -4,6 +4,8 @@ #include "device/sensors/device_sensor_host.h" +#include <utility> + #include "base/memory/ptr_util.h" #include "base/message_loop/message_loop.h" #include "device/sensors/device_sensor_export.h" @@ -39,14 +41,14 @@ DeviceSensorHost<MojoInterface, consumer_type>::~DeviceSensorHost() { template <typename MojoInterface, ConsumerType consumer_type> void DeviceSensorHost<MojoInterface, consumer_type>::DeviceSensorHost:: - StartPolling(const typename MojoInterface::StartPollingCallback& callback) { + StartPolling(typename MojoInterface::StartPollingCallback callback) { DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(!is_started_); if (is_started_) return; is_started_ = true; DeviceSensorService::GetInstance()->AddConsumer(consumer_type); - callback.Run( + std::move(callback).Run( DeviceSensorService::GetInstance()->GetSharedMemoryHandle(consumer_type)); } @@ -62,8 +64,6 @@ void DeviceSensorHost<MojoInterface, } template class DEVICE_SENSOR_EXPORT - DeviceSensorHost<device::mojom::LightSensor, CONSUMER_TYPE_LIGHT>; -template class DEVICE_SENSOR_EXPORT DeviceSensorHost<device::mojom::MotionSensor, CONSUMER_TYPE_MOTION>; template class DEVICE_SENSOR_EXPORT DeviceSensorHost<device::mojom::OrientationSensor, diff --git a/chromium/device/sensors/device_sensor_host.h b/chromium/device/sensors/device_sensor_host.h index be9ff72163e..b6aad4edc95 100644 --- a/chromium/device/sensors/device_sensor_host.h +++ b/chromium/device/sensors/device_sensor_host.h @@ -8,7 +8,6 @@ #include "base/macros.h" #include "base/memory/shared_memory.h" #include "device/sensors/device_sensors_consts.h" -#include "device/sensors/public/interfaces/light.mojom.h" #include "device/sensors/public/interfaces/motion.mojom.h" #include "device/sensors/public/interfaces/orientation.mojom.h" #include "mojo/public/cpp/bindings/interface_request.h" @@ -28,7 +27,7 @@ class DeviceSensorHost : NON_EXPORTED_BASE(public MojoInterface) { DeviceSensorHost(); void StartPolling( - const typename MojoInterface::StartPollingCallback& callback) override; + typename MojoInterface::StartPollingCallback callback) override; void StopPolling() override; bool is_started_; @@ -38,8 +37,6 @@ class DeviceSensorHost : NON_EXPORTED_BASE(public MojoInterface) { DISALLOW_COPY_AND_ASSIGN(DeviceSensorHost); }; -using DeviceLightHost = - DeviceSensorHost<device::mojom::LightSensor, CONSUMER_TYPE_LIGHT>; using DeviceMotionHost = DeviceSensorHost<device::mojom::MotionSensor, CONSUMER_TYPE_MOTION>; using DeviceOrientationHost = DeviceSensorHost<device::mojom::OrientationSensor, diff --git a/chromium/device/sensors/device_sensor_service.cc b/chromium/device/sensors/device_sensor_service.cc index 44693185eb8..6f1c21fb547 100644 --- a/chromium/device/sensors/device_sensor_service.cc +++ b/chromium/device/sensors/device_sensor_service.cc @@ -13,8 +13,7 @@ namespace device { DeviceSensorService::DeviceSensorService() - : num_light_readers_(0), - num_motion_readers_(0), + : num_motion_readers_(0), num_orientation_readers_(0), num_orientation_absolute_readers_(0), is_shutdown_(false) { @@ -66,10 +65,6 @@ bool DeviceSensorService::ChangeNumberConsumers(ConsumerType consumer_type, num_orientation_absolute_readers_ += delta; DCHECK_GE(num_orientation_absolute_readers_, 0); return true; - case CONSUMER_TYPE_LIGHT: - num_light_readers_ += delta; - DCHECK_GE(num_light_readers_, 0); - return true; default: NOTREACHED(); } @@ -84,8 +79,6 @@ int DeviceSensorService::GetNumberConsumers(ConsumerType consumer_type) const { return num_orientation_readers_; case CONSUMER_TYPE_ORIENTATION_ABSOLUTE: return num_orientation_absolute_readers_; - case CONSUMER_TYPE_LIGHT: - return num_light_readers_; default: NOTREACHED(); } diff --git a/chromium/device/sensors/device_sensor_service.h b/chromium/device/sensors/device_sensor_service.h index 413d85880f6..17b356c8650 100644 --- a/chromium/device/sensors/device_sensor_service.h +++ b/chromium/device/sensors/device_sensor_service.h @@ -62,7 +62,6 @@ class DEVICE_SENSOR_EXPORT DeviceSensorService bool ChangeNumberConsumers(ConsumerType consumer_type, int delta); int GetNumberConsumers(ConsumerType consumer_type) const; - int num_light_readers_; int num_motion_readers_; int num_orientation_readers_; int num_orientation_absolute_readers_; diff --git a/chromium/device/sensors/device_sensors_consts.h b/chromium/device/sensors/device_sensors_consts.h index 0c7f411de42..b128222bcdd 100644 --- a/chromium/device/sensors/device_sensors_consts.h +++ b/chromium/device/sensors/device_sensors_consts.h @@ -9,7 +9,7 @@ namespace device { -// Constants related to the Device {Motion|Orientation|Light} APIs. +// Constants related to the Device {Motion|Orientation} APIs. // A Java counterpart will be generated for this enum. // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.device.sensors @@ -17,7 +17,6 @@ enum ConsumerType { CONSUMER_TYPE_MOTION = 1 << 0, CONSUMER_TYPE_ORIENTATION = 1 << 1, CONSUMER_TYPE_ORIENTATION_ABSOLUTE = 1 << 2, - CONSUMER_TYPE_LIGHT = 1 << 3, }; // Specifies the sampling rate for sensor data updates. @@ -28,12 +27,6 @@ const int kDeviceSensorSamplingRateHz = 60; const int kDeviceSensorIntervalMicroseconds = base::Time::kMicrosecondsPerSecond / kDeviceSensorSamplingRateHz; -// Corresponding |kDefaultLightPumpFrequencyHz| is in -// content/renderer/device_sensors/device_light_event_pump.cc. -const int kLightSensorSamplingRateHz = 5; -const int kLightSensorIntervalMicroseconds = - base::Time::kMicrosecondsPerSecond / kLightSensorSamplingRateHz; - } // namespace device #endif // DEVICE_SENSORS_DEVICE_SENSORS_CONSTS_H_ diff --git a/chromium/device/sensors/public/cpp/BUILD.gn b/chromium/device/sensors/public/cpp/BUILD.gn index a6d0ed87ed6..b0608af0092 100644 --- a/chromium/device/sensors/public/cpp/BUILD.gn +++ b/chromium/device/sensors/public/cpp/BUILD.gn @@ -32,13 +32,8 @@ source_set("shared_with_blink") { # dependencies on the STL and Chromium code. source_set("full") { sources = [ - "device_light_data.h", - "device_light_hardware_buffer.h", "device_motion_hardware_buffer.h", "device_orientation_hardware_buffer.h", - "device_sensors_consts.h", - "device_util_mac.cc", - "device_util_mac.h", ] public_deps = [ diff --git a/chromium/device/sensors/public/cpp/device_light_data.h b/chromium/device/sensors/public/cpp/device_light_data.h deleted file mode 100644 index 71a4bcc21bf..00000000000 --- a/chromium/device/sensors/public/cpp/device_light_data.h +++ /dev/null @@ -1,21 +0,0 @@ -// 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 DEVICE_SENSORS_PUBLIC_CPP_DEVICE_LIGHT_DATA_H_ -#define DEVICE_SENSORS_PUBLIC_CPP_DEVICE_LIGHT_DATA_H_ - -namespace device { - -// This struct is intentionally POD and fixed size so that it can be stored -// in shared memory between the sensor interface impl and its clients. -// POD class should be a struct, should have an inline cstor that uses -// initializer lists and no dstor. -struct DeviceLightData { - DeviceLightData() : value(-1) {} - double value; -}; - -} // namespace device - -#endif // DEVICE_SENSORS_PUBLIC_CPP_DEVICE_LIGHT_DATA_H_ diff --git a/chromium/device/sensors/public/cpp/device_light_hardware_buffer.h b/chromium/device/sensors/public/cpp/device_light_hardware_buffer.h deleted file mode 100644 index 039d22ad9be..00000000000 --- a/chromium/device/sensors/public/cpp/device_light_hardware_buffer.h +++ /dev/null @@ -1,17 +0,0 @@ -// 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 DEVICE_SENSORS_PUBLIC_CPP_DEVICE_LIGHT_HARDWARE_BUFFER_H_ -#define DEVICE_SENSORS_PUBLIC_CPP_DEVICE_LIGHT_HARDWARE_BUFFER_H_ - -#include "device/base/synchronization/shared_memory_seqlock_buffer.h" -#include "device/sensors/public/cpp/device_light_data.h" - -namespace device { - -typedef SharedMemorySeqLockBuffer<DeviceLightData> DeviceLightHardwareBuffer; - -} // namespace device - -#endif // DEVICE_SENSORS_PUBLIC_CPP_DEVICE_LIGHT_HARDWARE_BUFFER_H_ diff --git a/chromium/device/sensors/public/cpp/device_sensors_consts.h b/chromium/device/sensors/public/cpp/device_sensors_consts.h deleted file mode 100644 index 9bad667e1ad..00000000000 --- a/chromium/device/sensors/public/cpp/device_sensors_consts.h +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2016 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 DEVICE_SENSORS_PUBLIC_CPP_DEVICE_SENSORS_CONSTS_H_ -#define DEVICE_SENSORS_PUBLIC_CPP_DEVICE_SENSORS_CONSTS_H_ - -namespace device { - -// Default rate for returning value of the ambient light sensor. -const int kDefaultAmbientLightFrequencyHz = 5; - -} // namespace device - -#endif // DEVICE_SENSORS_PUBLIC_CPP_DEVICE_SENSORS_CONSTS_H_ diff --git a/chromium/device/sensors/public/cpp/device_util_mac.cc b/chromium/device/sensors/public/cpp/device_util_mac.cc deleted file mode 100644 index 91325ef0e1f..00000000000 --- a/chromium/device/sensors/public/cpp/device_util_mac.cc +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2016 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 "device/sensors/public/cpp/device_util_mac.h" - -#include <math.h> - -namespace device { - -double LMUvalueToLux(uint64_t raw_value) { - // Conversion formula from regression. - // https://bugzilla.mozilla.org/show_bug.cgi?id=793728 - // Let x = raw_value, then - // lux = -2.978303814*(10^-27)*x^4 + 2.635687683*(10^-19)*x^3 - - // 3.459747434*(10^-12)*x^2 + 3.905829689*(10^-5)*x - 0.1932594532 - - static const long double k4 = pow(10.L, -7); - static const long double k3 = pow(10.L, -4); - static const long double k2 = pow(10.L, -2); - static const long double k1 = pow(10.L, 5); - long double scaled_value = raw_value / k1; - - long double lux_value = - (-3 * k4 * pow(scaled_value, 4)) + (2.6 * k3 * pow(scaled_value, 3)) + - (-3.4 * k2 * pow(scaled_value, 2)) + (3.9 * scaled_value) - 0.19; - - double lux = ceil(static_cast<double>(lux_value)); - return lux > 0 ? lux : 0; -} - -} // namespace device diff --git a/chromium/device/sensors/public/cpp/device_util_mac.h b/chromium/device/sensors/public/cpp/device_util_mac.h deleted file mode 100644 index 82c728af5d4..00000000000 --- a/chromium/device/sensors/public/cpp/device_util_mac.h +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2016 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 DEVICE_SENSORS_PUBLIC_CPP_DEVICE_UTIL_MAC_H_ -#define DEVICE_SENSORS_PUBLIC_CPP_DEVICE_UTIL_MAC_H_ - -#include <stdint.h> - -namespace device { - -// Convert the value returned by the ambient light LMU sensor on Mac -// hardware to a lux value. -double LMUvalueToLux(uint64_t raw_value); - -} // namespace device - -#endif // DEVICE_SENSORS_PUBLIC_CPP_DEVICE_UTIL_MAC_H_ diff --git a/chromium/device/sensors/public/interfaces/BUILD.gn b/chromium/device/sensors/public/interfaces/BUILD.gn index f697e347919..9a1d18b6826 100644 --- a/chromium/device/sensors/public/interfaces/BUILD.gn +++ b/chromium/device/sensors/public/interfaces/BUILD.gn @@ -6,7 +6,6 @@ import("//mojo/public/tools/bindings/mojom.gni") mojom("interfaces") { sources = [ - "light.mojom", "motion.mojom", "orientation.mojom", ] diff --git a/chromium/device/sensors/public/interfaces/light.mojom b/chromium/device/sensors/public/interfaces/light.mojom deleted file mode 100644 index 3c12347dd39..00000000000 --- a/chromium/device/sensors/public/interfaces/light.mojom +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2016 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. - -module device.mojom; - -interface LightSensor { - StartPolling() => (handle<shared_buffer> memory_handle); - StopPolling(); -}; diff --git a/chromium/device/sensors/sensor_manager_android.cc b/chromium/device/sensors/sensor_manager_android.cc index 7571c565242..47aeb1d0424 100644 --- a/chromium/device/sensors/sensor_manager_android.cc +++ b/chromium/device/sensors/sensor_manager_android.cc @@ -6,7 +6,6 @@ #include <string.h> -#include "base/android/context_utils.h" #include "base/android/jni_android.h" #include "base/bind.h" #include "base/memory/singleton.h" @@ -55,7 +54,6 @@ namespace device { SensorManagerAndroid::SensorManagerAndroid() : number_active_device_motion_sensors_(0), - device_light_buffer_(nullptr), device_motion_buffer_(nullptr), device_orientation_buffer_(nullptr), motion_buffer_initialized_(false), @@ -63,8 +61,7 @@ SensorManagerAndroid::SensorManagerAndroid() is_shutdown_(false) { DCHECK(thread_checker_.CalledOnValidThread()); memset(received_motion_data_, 0, sizeof(received_motion_data_)); - device_sensors_.Reset(Java_DeviceSensors_getInstance( - AttachCurrentThread(), base::android::GetApplicationContext())); + device_sensors_.Reset(Java_DeviceSensors_create(AttachCurrentThread())); } SensorManagerAndroid::~SensorManagerAndroid() {} @@ -197,28 +194,12 @@ void SensorManagerAndroid::GotRotationRate(JNIEnv*, } } -void SensorManagerAndroid::GotLight(JNIEnv*, - const JavaParamRef<jobject>&, - double value) { - base::AutoLock autolock(light_buffer_lock_); - - if (!device_light_buffer_) - return; - - device_light_buffer_->seqlock.WriteBegin(); - device_light_buffer_->data.value = value; - device_light_buffer_->seqlock.WriteEnd(); -} - bool SensorManagerAndroid::Start(ConsumerType consumer_type) { DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(!device_sensors_.is_null()); - int rate_in_microseconds = (consumer_type == CONSUMER_TYPE_LIGHT) - ? kLightSensorIntervalMicroseconds - : kDeviceSensorIntervalMicroseconds; return Java_DeviceSensors_start( AttachCurrentThread(), device_sensors_, reinterpret_cast<intptr_t>(this), - static_cast<jint>(consumer_type), rate_in_microseconds); + static_cast<jint>(consumer_type), kDeviceSensorIntervalMicroseconds); } void SensorManagerAndroid::Stop(ConsumerType consumer_type) { @@ -245,48 +226,6 @@ SensorManagerAndroid::GetOrientationSensorTypeUsed() { // ----- Shared memory API methods -// --- Device Light - -void SensorManagerAndroid::StartFetchingDeviceLightData( - DeviceLightHardwareBuffer* buffer) { - DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK(buffer); - if (is_shutdown_) - return; - - { - base::AutoLock autolock(light_buffer_lock_); - device_light_buffer_ = buffer; - SetLightBufferValue(-1); - } - bool success = Start(CONSUMER_TYPE_LIGHT); - if (!success) { - base::AutoLock autolock(light_buffer_lock_); - SetLightBufferValue(std::numeric_limits<double>::infinity()); - } -} - -void SensorManagerAndroid::StopFetchingDeviceLightData() { - DCHECK(thread_checker_.CalledOnValidThread()); - if (is_shutdown_) - return; - - Stop(CONSUMER_TYPE_LIGHT); - { - base::AutoLock autolock(light_buffer_lock_); - if (device_light_buffer_) { - SetLightBufferValue(-1); - device_light_buffer_ = nullptr; - } - } -} - -void SensorManagerAndroid::SetLightBufferValue(double lux) { - device_light_buffer_->seqlock.WriteBegin(); - device_light_buffer_->data.value = lux; - device_light_buffer_->seqlock.WriteEnd(); -} - // --- Device Motion void SensorManagerAndroid::StartFetchingDeviceMotionData( diff --git a/chromium/device/sensors/sensor_manager_android.h b/chromium/device/sensors/sensor_manager_android.h index 4d299efde3a..bf285ebfbee 100644 --- a/chromium/device/sensors/sensor_manager_android.h +++ b/chromium/device/sensors/sensor_manager_android.h @@ -13,7 +13,6 @@ #include "base/threading/thread_checker.h" #include "device/sensors/device_sensor_export.h" #include "device/sensors/device_sensors_consts.h" -#include "device/sensors/public/cpp/device_light_hardware_buffer.h" #include "device/sensors/public/cpp/device_motion_hardware_buffer.h" #include "device/sensors/public/cpp/device_orientation_hardware_buffer.h" @@ -24,7 +23,7 @@ struct DefaultSingletonTraits; namespace device { -// Android implementation of Device {Motion|Orientation|Light} API. +// Android implementation of Device {Motion|Orientation} API. // // Android's SensorManager has a push API, so when Got*() methods are called // by the system the browser process puts the received data into a shared @@ -38,9 +37,6 @@ class DEVICE_SENSOR_EXPORT SensorManagerAndroid { static SensorManagerAndroid* GetInstance(); // Called from Java via JNI. - void GotLight(JNIEnv*, - const base::android::JavaParamRef<jobject>&, - double value); void GotOrientation(JNIEnv*, const base::android::JavaParamRef<jobject>&, double alpha, @@ -69,9 +65,6 @@ class DEVICE_SENSOR_EXPORT SensorManagerAndroid { double gamma); // Shared memory related methods. - void StartFetchingDeviceLightData(DeviceLightHardwareBuffer* buffer); - void StopFetchingDeviceLightData(); - void StartFetchingDeviceMotionData(DeviceMotionHardwareBuffer* buffer); void StopFetchingDeviceMotionData(); @@ -121,8 +114,6 @@ class DEVICE_SENSOR_EXPORT SensorManagerAndroid { RECEIVED_MOTION_DATA_MAX = 3, }; - void SetLightBufferValue(double lux); - void CheckMotionBufferReadyToRead(); void SetMotionBufferReadyStatus(bool ready); void ClearInternalMotionBuffers(); @@ -133,7 +124,6 @@ class DEVICE_SENSOR_EXPORT SensorManagerAndroid { int received_motion_data_[RECEIVED_MOTION_DATA_MAX]; // Cached pointers to buffers, owned by DataFetcherSharedMemoryBase. - DeviceLightHardwareBuffer* device_light_buffer_; DeviceMotionHardwareBuffer* device_motion_buffer_; DeviceOrientationHardwareBuffer* device_orientation_buffer_; DeviceOrientationHardwareBuffer* device_orientation_absolute_buffer_; @@ -142,7 +132,6 @@ class DEVICE_SENSOR_EXPORT SensorManagerAndroid { bool orientation_buffer_initialized_; bool orientation_absolute_buffer_initialized_; - base::Lock light_buffer_lock_; base::Lock motion_buffer_lock_; base::Lock orientation_buffer_lock_; base::Lock orientation_absolute_buffer_lock_; diff --git a/chromium/device/sensors/sensor_manager_android_unittest.cc b/chromium/device/sensors/sensor_manager_android_unittest.cc index fc45d515043..620c6f9faa2 100644 --- a/chromium/device/sensors/sensor_manager_android_unittest.cc +++ b/chromium/device/sensors/sensor_manager_android_unittest.cc @@ -44,7 +44,6 @@ class FakeSensorManagerAndroid : public SensorManagerAndroid { class AndroidSensorManagerTest : public testing::Test { protected: AndroidSensorManagerTest() { - light_buffer_.reset(new DeviceLightHardwareBuffer); motion_buffer_.reset(new DeviceMotionHardwareBuffer); orientation_buffer_.reset(new DeviceOrientationHardwareBuffer); orientation_absolute_buffer_.reset(new DeviceOrientationHardwareBuffer); @@ -64,7 +63,6 @@ class AndroidSensorManagerTest : public testing::Test { ASSERT_TRUE(buffer->data.has_gamma); } - std::unique_ptr<DeviceLightHardwareBuffer> light_buffer_; std::unique_ptr<DeviceMotionHardwareBuffer> motion_buffer_; std::unique_ptr<DeviceOrientationHardwareBuffer> orientation_buffer_; std::unique_ptr<DeviceOrientationHardwareBuffer> orientation_absolute_buffer_; @@ -175,20 +173,6 @@ TEST_F(AndroidSensorManagerTest, DeviceOrientationAbsoluteSensorsActive) { ASSERT_FALSE(orientation_buffer_->data.all_available_sensors_are_active); } -// DeviceLight -TEST_F(AndroidSensorManagerTest, DeviceLightSensorsActive) { - FakeSensorManagerAndroid::Register(base::android::AttachCurrentThread()); - FakeSensorManagerAndroid sensorManager; - - sensorManager.StartFetchingDeviceLightData(light_buffer_.get()); - - sensorManager.GotLight(nullptr, nullptr, 100); - ASSERT_EQ(100, light_buffer_->data.value); - - sensorManager.StopFetchingDeviceLightData(); - ASSERT_EQ(-1, light_buffer_->data.value); -} - } // namespace } // namespace device diff --git a/chromium/device/serial/serial_io_handler.cc b/chromium/device/serial/serial_io_handler.cc index f9e3e820831..2fa0d1afdd6 100644 --- a/chromium/device/serial/serial_io_handler.cc +++ b/chromium/device/serial/serial_io_handler.cc @@ -126,7 +126,7 @@ void SerialIoHandler::StartOpen( const std::string& port, scoped_refptr<base::SingleThreadTaskRunner> io_task_runner) { DCHECK(!open_complete_.is_null()); - DCHECK(file_thread_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(file_thread_task_runner_->RunsTasksInCurrentSequence()); DCHECK(!file_.IsValid()); // It's the responsibility of the API wrapper around SerialIoHandler to // validate the supplied path against the set of valid port names, and diff --git a/chromium/device/u2f/BUILD.gn b/chromium/device/u2f/BUILD.gn index 91fd6a26afe..0fcfe4b1268 100644 --- a/chromium/device/u2f/BUILD.gn +++ b/chromium/device/u2f/BUILD.gn @@ -19,6 +19,13 @@ source_set("u2f") { "u2f_message.h", "u2f_packet.cc", "u2f_packet.h", + "u2f_register.cc", + "u2f_register.h", + "u2f_request.cc", + "u2f_request.h", + "u2f_return_code.h", + "u2f_sign.cc", + "u2f_sign.h", ] deps = [ @@ -30,6 +37,21 @@ source_set("u2f") { ] } +source_set("mocks") { + testonly = true + + sources = [ + "mock_u2f_device.cc", + "mock_u2f_device.h", + ] + + deps = [ + ":u2f", + "//base", + "//testing/gmock", + ] +} + fuzzer_test("u2f_apdu_fuzzer") { sources = [ "u2f_apdu_fuzzer.cc", diff --git a/chromium/device/u2f/mock_u2f_device.cc b/chromium/device/u2f/mock_u2f_device.cc new file mode 100644 index 00000000000..e833bbf6ef8 --- /dev/null +++ b/chromium/device/u2f/mock_u2f_device.cc @@ -0,0 +1,57 @@ +// Copyright 2017 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 "mock_u2f_device.h" + +namespace device { + +MockU2fDevice::MockU2fDevice() : weak_factory_(this) {} + +MockU2fDevice::~MockU2fDevice() {} + +void MockU2fDevice::DeviceTransact(std::unique_ptr<U2fApduCommand> command, + const DeviceCallback& cb) { + DeviceTransactPtr(command.get(), cb); +} + +// static +void MockU2fDevice::NotSatisfied(U2fApduCommand* cmd, + const DeviceCallback& cb) { + cb.Run(true, base::MakeUnique<U2fApduResponse>( + std::vector<uint8_t>(), + U2fApduResponse::Status::SW_CONDITIONS_NOT_SATISFIED)); +} + +// static +void MockU2fDevice::WrongData(U2fApduCommand* cmd, const DeviceCallback& cb) { + cb.Run(true, + base::MakeUnique<U2fApduResponse>( + std::vector<uint8_t>(), U2fApduResponse::Status::SW_WRONG_DATA)); +} + +// static +void MockU2fDevice::NoErrorSign(U2fApduCommand* cmd, const DeviceCallback& cb) { + cb.Run(true, base::MakeUnique<U2fApduResponse>( + std::vector<uint8_t>({kSign}), + U2fApduResponse::Status::SW_NO_ERROR)); +} + +// static +void MockU2fDevice::NoErrorRegister(U2fApduCommand* cmd, + const DeviceCallback& cb) { + cb.Run(true, base::MakeUnique<U2fApduResponse>( + std::vector<uint8_t>({kRegister}), + U2fApduResponse::Status::SW_NO_ERROR)); +} + +// static +void MockU2fDevice::WinkDoNothing(const WinkCallback& cb) { + cb.Run(); +} + +base::WeakPtr<U2fDevice> MockU2fDevice::GetWeakPtr() { + return weak_factory_.GetWeakPtr(); +} + +} // namespace device diff --git a/chromium/device/u2f/mock_u2f_device.h b/chromium/device/u2f/mock_u2f_device.h new file mode 100644 index 00000000000..fcd7b27af9d --- /dev/null +++ b/chromium/device/u2f/mock_u2f_device.h @@ -0,0 +1,47 @@ +// Copyright 2017 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 DEVICE_U2F_MOCK_U2F_DEVICE_H_ +#define DEVICE_U2F_MOCK_U2F_DEVICE_H_ + +#include <vector> + +#include "base/memory/ptr_util.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "u2f_apdu_command.h" +#include "u2f_device.h" + +namespace device { + +class MockU2fDevice : public U2fDevice { + public: + static constexpr uint8_t kSign = 0x1; + static constexpr uint8_t kRegister = 0x5; + + MockU2fDevice(); + ~MockU2fDevice() override; + + MOCK_METHOD1(TryWink, void(const WinkCallback& cb)); + MOCK_METHOD0(GetId, std::string(void)); + // GMock cannot mock a method taking a std::unique_ptr<T> + MOCK_METHOD2(DeviceTransactPtr, + void(U2fApduCommand* command, const DeviceCallback& cb)); + void DeviceTransact(std::unique_ptr<U2fApduCommand> command, + const DeviceCallback& cb) override; + base::WeakPtr<U2fDevice> GetWeakPtr() override; + static void TransactNoError(std::unique_ptr<U2fApduCommand> command, + const DeviceCallback& cb); + static void NotSatisfied(U2fApduCommand* cmd, const DeviceCallback& cb); + static void WrongData(U2fApduCommand* cmd, const DeviceCallback& cb); + static void NoErrorSign(U2fApduCommand* cmd, const DeviceCallback& cb); + static void NoErrorRegister(U2fApduCommand* cmd, const DeviceCallback& cb); + static void WinkDoNothing(const WinkCallback& cb); + + private: + base::WeakPtrFactory<U2fDevice> weak_factory_; +}; + +} // namespace device + +#endif // DEVICE_U2F_MOCK_U2F_DEVICE_H_ diff --git a/chromium/device/u2f/u2f_apdu_response.h b/chromium/device/u2f/u2f_apdu_response.h index 44bf7d61af1..2e5d74eb8c4 100644 --- a/chromium/device/u2f/u2f_apdu_response.h +++ b/chromium/device/u2f/u2f_apdu_response.h @@ -23,6 +23,7 @@ class U2fApduResponse { SW_NO_ERROR = 0x9000, SW_CONDITIONS_NOT_SATISFIED = 0x6985, SW_WRONG_DATA = 0x6A80, + SW_WRONG_LENGTH = 0x6700, }; U2fApduResponse(std::vector<uint8_t> message, Status response_status); diff --git a/chromium/device/u2f/u2f_device.cc b/chromium/device/u2f/u2f_device.cc index dc9e5ec127b..2545cc12f81 100644 --- a/chromium/device/u2f/u2f_device.cc +++ b/chromium/device/u2f/u2f_device.cc @@ -10,7 +10,7 @@ namespace device { -U2fDevice::U2fDevice() : weak_factory_(this) {} +U2fDevice::U2fDevice() : channel_id_(kBroadcastChannel), capabilities_(0) {} U2fDevice::~U2fDevice() {} @@ -20,12 +20,12 @@ void U2fDevice::Register(const std::vector<uint8_t>& app_param, std::unique_ptr<U2fApduCommand> register_cmd = U2fApduCommand::CreateRegister(app_param, challenge_param); if (!register_cmd) { - callback.Run(ReturnCode::INVALID_PARAMS, std::vector<uint8_t>()); + callback.Run(U2fReturnCode::INVALID_PARAMS, std::vector<uint8_t>()); return; } - DeviceTransact(std::move(register_cmd), - base::Bind(&U2fDevice::OnRegisterComplete, - weak_factory_.GetWeakPtr(), callback)); + DeviceTransact( + std::move(register_cmd), + base::Bind(&U2fDevice::OnRegisterComplete, GetWeakPtr(), callback)); } void U2fDevice::Sign(const std::vector<uint8_t>& app_param, @@ -35,12 +35,11 @@ void U2fDevice::Sign(const std::vector<uint8_t>& app_param, std::unique_ptr<U2fApduCommand> sign_cmd = U2fApduCommand::CreateSign(app_param, challenge_param, key_handle); if (!sign_cmd) { - callback.Run(ReturnCode::INVALID_PARAMS, std::vector<uint8_t>()); + callback.Run(U2fReturnCode::INVALID_PARAMS, std::vector<uint8_t>()); return; } - DeviceTransact(std::move(sign_cmd), - base::Bind(&U2fDevice::OnSignComplete, - weak_factory_.GetWeakPtr(), callback)); + DeviceTransact(std::move(sign_cmd), base::Bind(&U2fDevice::OnSignComplete, + GetWeakPtr(), callback)); } void U2fDevice::Version(const VersionCallback& callback) { @@ -49,9 +48,9 @@ void U2fDevice::Version(const VersionCallback& callback) { callback.Run(false, ProtocolVersion::UNKNOWN); return; } - DeviceTransact(std::move(version_cmd), - base::Bind(&U2fDevice::OnVersionComplete, - weak_factory_.GetWeakPtr(), callback)); + DeviceTransact( + std::move(version_cmd), + base::Bind(&U2fDevice::OnVersionComplete, GetWeakPtr(), callback)); } void U2fDevice::OnRegisterComplete( @@ -59,22 +58,22 @@ void U2fDevice::OnRegisterComplete( bool success, std::unique_ptr<U2fApduResponse> register_response) { if (!success || !register_response) { - callback.Run(ReturnCode::FAILURE, std::vector<uint8_t>()); + callback.Run(U2fReturnCode::FAILURE, std::vector<uint8_t>()); return; } switch (register_response->status()) { case U2fApduResponse::Status::SW_CONDITIONS_NOT_SATISFIED: - callback.Run(ReturnCode::CONDITIONS_NOT_SATISFIED, + callback.Run(U2fReturnCode::CONDITIONS_NOT_SATISFIED, std::vector<uint8_t>()); break; case U2fApduResponse::Status::SW_NO_ERROR: - callback.Run(ReturnCode::SUCCESS, register_response->data()); + callback.Run(U2fReturnCode::SUCCESS, register_response->data()); break; case U2fApduResponse::Status::SW_WRONG_DATA: - callback.Run(ReturnCode::INVALID_PARAMS, std::vector<uint8_t>()); + callback.Run(U2fReturnCode::INVALID_PARAMS, std::vector<uint8_t>()); break; default: - callback.Run(ReturnCode::FAILURE, std::vector<uint8_t>()); + callback.Run(U2fReturnCode::FAILURE, std::vector<uint8_t>()); break; } } @@ -83,22 +82,21 @@ void U2fDevice::OnSignComplete(const MessageCallback& callback, bool success, std::unique_ptr<U2fApduResponse> sign_response) { if (!success || !sign_response) { - callback.Run(ReturnCode::FAILURE, std::vector<uint8_t>()); + callback.Run(U2fReturnCode::FAILURE, std::vector<uint8_t>()); return; } switch (sign_response->status()) { case U2fApduResponse::Status::SW_CONDITIONS_NOT_SATISFIED: - callback.Run(ReturnCode::CONDITIONS_NOT_SATISFIED, + callback.Run(U2fReturnCode::CONDITIONS_NOT_SATISFIED, std::vector<uint8_t>()); break; case U2fApduResponse::Status::SW_NO_ERROR: - callback.Run(ReturnCode::SUCCESS, sign_response->data()); + callback.Run(U2fReturnCode::SUCCESS, sign_response->data()); break; case U2fApduResponse::Status::SW_WRONG_DATA: - callback.Run(ReturnCode::INVALID_PARAMS, std::vector<uint8_t>()); - break; + case U2fApduResponse::Status::SW_WRONG_LENGTH: default: - callback.Run(ReturnCode::FAILURE, std::vector<uint8_t>()); + callback.Run(U2fReturnCode::INVALID_PARAMS, std::vector<uint8_t>()); break; } } diff --git a/chromium/device/u2f/u2f_device.h b/chromium/device/u2f/u2f_device.h index 3a7e9161ac8..2a5323dbc4d 100644 --- a/chromium/device/u2f/u2f_device.h +++ b/chromium/device/u2f/u2f_device.h @@ -10,6 +10,7 @@ #include "base/callback.h" #include "base/memory/weak_ptr.h" #include "u2f_apdu_response.h" +#include "u2f_return_code.h" namespace device { @@ -23,15 +24,9 @@ class U2fDevice { U2F_V2, UNKNOWN, }; - enum class ReturnCode : uint8_t { - SUCCESS, - FAILURE, - INVALID_PARAMS, - CONDITIONS_NOT_SATISFIED, - }; using MessageCallback = - base::Callback<void(ReturnCode, std::vector<uint8_t>)>; + base::Callback<void(U2fReturnCode, const std::vector<uint8_t>&)>; using VersionCallback = base::Callback<void(bool success, ProtocolVersion version)>; using DeviceCallback = @@ -39,7 +34,7 @@ class U2fDevice { std::unique_ptr<U2fApduResponse> response)>; using WinkCallback = base::Callback<void()>; - ~U2fDevice(); + virtual ~U2fDevice(); // Raw messages parameters are defined by the specification at // https://fidoalliance.org/specs/fido-u2f-v1.0-nfc-bt-amendment-20150514/fido-u2f-raw-message-formats.html @@ -65,6 +60,7 @@ class U2fDevice { // the device communication transaction. virtual void DeviceTransact(std::unique_ptr<U2fApduCommand> command, const DeviceCallback& callback) = 0; + virtual base::WeakPtr<U2fDevice> GetWeakPtr() = 0; uint32_t channel_id_; uint8_t capabilities_; @@ -87,8 +83,6 @@ class U2fDevice { bool success, std::unique_ptr<U2fApduResponse> response); - base::WeakPtrFactory<U2fDevice> weak_factory_; - DISALLOW_COPY_AND_ASSIGN(U2fDevice); }; diff --git a/chromium/device/u2f/u2f_hid_device.cc b/chromium/device/u2f/u2f_hid_device.cc index c313b96e4c1..e54cf9a85d2 100644 --- a/chromium/device/u2f/u2f_hid_device.cc +++ b/chromium/device/u2f/u2f_hid_device.cc @@ -7,6 +7,7 @@ #include "base/bind.h" #include "base/bind_helpers.h" #include "base/command_line.h" +#include "base/threading/thread_task_runner_handle.h" #include "crypto/random.h" #include "device/base/device_client.h" #include "device/hid/hid_connection.h" @@ -24,12 +25,11 @@ U2fHidDevice::U2fHidDevice(scoped_refptr<HidDeviceInfo> device_info) state_(State::INIT), device_info_(device_info), weak_factory_(this) { - channel_id_ = kBroadcastChannel; } U2fHidDevice::~U2fHidDevice() { // Cleanup connection - if (connection_) + if (connection_ && !connection_->closed()) connection_->Close(); } @@ -43,17 +43,22 @@ void U2fHidDevice::Transition(std::unique_ptr<U2fApduCommand> command, switch (state_) { case State::INIT: state_ = State::BUSY; + ArmTimeout(callback); Connect(base::Bind(&U2fHidDevice::OnConnect, weak_factory_.GetWeakPtr(), base::Passed(&command), callback)); break; case State::CONNECTED: state_ = State::BUSY; + ArmTimeout(callback); AllocateChannel(std::move(command), callback); break; case State::IDLE: { state_ = State::BUSY; std::unique_ptr<U2fMessage> msg = U2fMessage::Create( channel_id_, U2fMessage::Type::CMD_MSG, command->GetEncodedCommand()); + + ArmTimeout(callback); + // Write message to the device WriteMessage(std::move(msg), true, base::Bind(&U2fHidDevice::MessageReceived, weak_factory_.GetWeakPtr(), callback)); @@ -86,6 +91,10 @@ void U2fHidDevice::Connect(const HidService::ConnectCallback& callback) { void U2fHidDevice::OnConnect(std::unique_ptr<U2fApduCommand> command, const DeviceCallback& callback, scoped_refptr<HidConnection> connection) { + if (state_ == State::DEVICE_ERROR) + return; + timeout_callback_.Cancel(); + if (connection) { connection_ = connection; state_ = State::CONNECTED; @@ -114,6 +123,10 @@ void U2fHidDevice::OnAllocateChannel(std::vector<uint8_t> nonce, const DeviceCallback& callback, bool success, std::unique_ptr<U2fMessage> message) { + if (state_ == State::DEVICE_ERROR) + return; + timeout_callback_.Cancel(); + if (!success || !message) { state_ = State::DEVICE_ERROR; Transition(nullptr, callback); @@ -254,11 +267,16 @@ void U2fHidDevice::OnReadContinuation(std::unique_ptr<U2fMessage> message, void U2fHidDevice::MessageReceived(const DeviceCallback& callback, bool success, std::unique_ptr<U2fMessage> message) { + if (state_ == State::DEVICE_ERROR) + return; + timeout_callback_.Cancel(); + if (!success) { state_ = State::DEVICE_ERROR; Transition(nullptr, callback); return; } + std::unique_ptr<U2fApduResponse> response = nullptr; if (message) response = U2fApduResponse::CreateFromMessage(message->GetMessagePayload()); @@ -297,8 +315,23 @@ void U2fHidDevice::OnWink(const WinkCallback& callback, callback.Run(); } +void U2fHidDevice::ArmTimeout(const DeviceCallback& callback) { + DCHECK(timeout_callback_.IsCancelled()); + timeout_callback_.Reset(base::Bind(&U2fHidDevice::OnTimeout, + weak_factory_.GetWeakPtr(), callback)); + // Setup timeout task for 3 seconds + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, timeout_callback_.callback(), + base::TimeDelta::FromMilliseconds(3000)); +} + +void U2fHidDevice::OnTimeout(const DeviceCallback& callback) { + state_ = State::DEVICE_ERROR; + Transition(nullptr, callback); +} + std::string U2fHidDevice::GetId() { - std::ostringstream id("hid:"); + std::ostringstream id("hid:", std::ios::ate); id << device_info_->device_id(); return id.str(); } @@ -309,4 +342,8 @@ bool U2fHidDevice::IsTestEnabled() { return command_line->HasSwitch(switches::kEnableU2fHidTest); } +base::WeakPtr<U2fDevice> U2fHidDevice::GetWeakPtr() { + return weak_factory_.GetWeakPtr(); +} + } // namespace device diff --git a/chromium/device/u2f/u2f_hid_device.h b/chromium/device/u2f/u2f_hid_device.h index 527c0b30177..64bc0f2acfd 100644 --- a/chromium/device/u2f/u2f_hid_device.h +++ b/chromium/device/u2f/u2f_hid_device.h @@ -7,6 +7,7 @@ #include <list> +#include "base/cancelable_callback.h" #include "device/hid/hid_service.h" #include "u2f_device.h" @@ -23,7 +24,7 @@ class HidDeviceInfo; class U2fHidDevice : public U2fDevice { public: U2fHidDevice(scoped_refptr<HidDeviceInfo>); - ~U2fHidDevice(); + ~U2fHidDevice() final; // Send a U2f command to this device void DeviceTransact(std::unique_ptr<U2fApduCommand> command, @@ -85,8 +86,14 @@ class U2fHidDevice : public U2fDevice { void OnWink(const WinkCallback& callback, bool success, std::unique_ptr<U2fMessage> response); + void ArmTimeout(const DeviceCallback& callback); + void OnTimeout(const DeviceCallback& callback); + void OnDeviceTransact(bool success, + std::unique_ptr<U2fApduResponse> response); + base::WeakPtr<U2fDevice> GetWeakPtr() override; State state_; + base::CancelableClosure timeout_callback_; std::list<std::pair<std::unique_ptr<U2fApduCommand>, DeviceCallback>> pending_transactions_; scoped_refptr<HidDeviceInfo> device_info_; diff --git a/chromium/device/u2f/u2f_hid_device_unittest.cc b/chromium/device/u2f/u2f_hid_device_unittest.cc index 7bc1e957f00..f1f09159bd5 100644 --- a/chromium/device/u2f/u2f_hid_device_unittest.cc +++ b/chromium/device/u2f/u2f_hid_device_unittest.cc @@ -7,8 +7,7 @@ #include "base/bind.h" #include "base/memory/ptr_util.h" #include "base/run_loop.h" -#include "base/test/test_io_thread.h" -#include "base/threading/thread_task_runner_handle.h" +#include "base/test/scoped_task_environment.h" #include "device/base/mock_device_client.h" #include "device/hid/hid_connection.h" #include "device/hid/hid_device_filter.h" @@ -164,17 +163,13 @@ class TestDeviceCallback { class U2fHidDeviceTest : public testing::Test { public: - void SetUp() override { - message_loop_.reset(new base::MessageLoopForUI()); - io_thread_.reset(new base::TestIOThread(base::TestIOThread::kAutoStart)); - device_client_.reset( - new device::TestDeviceClient(io_thread_->task_runner())); - } + U2fHidDeviceTest() + : scoped_task_environment_( + base::test::ScopedTaskEnvironment::MainThreadType::UI) {} - protected: - std::unique_ptr<base::MessageLoopForUI> message_loop_; - std::unique_ptr<base::TestIOThread> io_thread_; - std::unique_ptr<device::TestDeviceClient> device_client_; + private: + base::test::ScopedTaskEnvironment scoped_task_environment_; + TestDeviceClient device_client_; }; TEST_F(U2fHidDeviceTest, TestHidDeviceVersion) { diff --git a/chromium/device/u2f/u2f_register.cc b/chromium/device/u2f/u2f_register.cc new file mode 100644 index 00000000000..babfe9899f1 --- /dev/null +++ b/chromium/device/u2f/u2f_register.cc @@ -0,0 +1,61 @@ +// Copyright 2017 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 "u2f_register.h" + +#include "base/memory/ptr_util.h" + +namespace device { + +U2fRegister::U2fRegister(const std::vector<uint8_t>& challenge_hash, + const std::vector<uint8_t>& app_param, + const ResponseCallback& cb) + : U2fRequest(cb), + challenge_hash_(challenge_hash), + app_param_(app_param), + weak_factory_(this) {} + +U2fRegister::~U2fRegister() {} + +// static +std::unique_ptr<U2fRequest> U2fRegister::TryRegistration( + const std::vector<uint8_t>& challenge_hash, + const std::vector<uint8_t>& app_param, + const ResponseCallback& cb) { + std::unique_ptr<U2fRequest> request = + base::MakeUnique<U2fRegister>(challenge_hash, app_param, cb); + request->Start(); + return request; +} + +void U2fRegister::TryDevice() { + DCHECK(current_device_); + + current_device_->Register( + app_param_, challenge_hash_, + base::Bind(&U2fRegister::OnTryDevice, weak_factory_.GetWeakPtr())); +} + +void U2fRegister::OnTryDevice(U2fReturnCode return_code, + const std::vector<uint8_t>& response_data) { + switch (return_code) { + case U2fReturnCode::SUCCESS: + state_ = State::COMPLETE; + cb_.Run(return_code, response_data); + break; + case U2fReturnCode::CONDITIONS_NOT_SATISFIED: + // Waiting for user touch, move on and try this device later + state_ = State::IDLE; + Transition(); + break; + default: + state_ = State::IDLE; + // An error has occured, quit trying this device + current_device_ = nullptr; + Transition(); + break; + } +} + +} // namespace device diff --git a/chromium/device/u2f/u2f_register.h b/chromium/device/u2f/u2f_register.h new file mode 100644 index 00000000000..7b7769ec627 --- /dev/null +++ b/chromium/device/u2f/u2f_register.h @@ -0,0 +1,38 @@ +// Copyright 2017 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 DEVICE_U2F_U2F_REGISTER_H_ +#define DEVICE_U2F_U2F_REGISTER_H_ + +#include <vector> + +#include "u2f_request.h" + +namespace device { + +class U2fRegister : public U2fRequest { + public: + U2fRegister(const std::vector<uint8_t>& challenge_hash, + const std::vector<uint8_t>& app_param, + const ResponseCallback& cb); + ~U2fRegister() override; + + static std::unique_ptr<U2fRequest> TryRegistration( + const std::vector<uint8_t>& challenge_hash, + const std::vector<uint8_t>& app_param, + const ResponseCallback& cb); + + private: + void TryDevice() override; + void OnTryDevice(U2fReturnCode return_code, + const std::vector<uint8_t>& response_data); + + std::vector<uint8_t> challenge_hash_; + std::vector<uint8_t> app_param_; + base::WeakPtrFactory<U2fRegister> weak_factory_; +}; + +} // namespace device + +#endif // DEVICE_U2F_U2F_REGISTER_H_ diff --git a/chromium/device/u2f/u2f_register_unittest.cc b/chromium/device/u2f/u2f_register_unittest.cc new file mode 100644 index 00000000000..5bb55e461aa --- /dev/null +++ b/chromium/device/u2f/u2f_register_unittest.cc @@ -0,0 +1,134 @@ +// Copyright 2017 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 <list> + +#include "base/run_loop.h" +#include "base/test/scoped_task_environment.h" +#include "base/test/test_io_thread.h" +#include "device/base/mock_device_client.h" +#include "device/hid/mock_hid_service.h" +#include "device/test/test_device_client.h" +#include "mock_u2f_device.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "u2f_register.h" + +namespace device { + +class U2fRegisterTest : public testing::Test { + public: + U2fRegisterTest() + : scoped_task_environment_( + base::test::ScopedTaskEnvironment::MainThreadType::UI), + io_thread_(base::TestIOThread::kAutoStart) {} + + void SetUp() override { + MockHidService* hid_service = device_client_.hid_service(); + hid_service->FirstEnumerationComplete(); + } + + protected: + base::test::ScopedTaskEnvironment scoped_task_environment_; + base::TestIOThread io_thread_; + device::MockDeviceClient device_client_; +}; + +class TestRegisterCallback { + public: + TestRegisterCallback() + : callback_(base::Bind(&TestRegisterCallback::ReceivedCallback, + base::Unretained(this))) {} + ~TestRegisterCallback() {} + + void ReceivedCallback(U2fReturnCode status_code, + const std::vector<uint8_t>& response) { + response_ = std::make_pair(status_code, response); + closure_.Run(); + } + + std::pair<U2fReturnCode, std::vector<uint8_t>>& WaitForCallback() { + closure_ = run_loop_.QuitClosure(); + run_loop_.Run(); + return response_; + } + + const U2fRequest::ResponseCallback& callback() { return callback_; } + + private: + std::pair<U2fReturnCode, std::vector<uint8_t>> response_; + base::Closure closure_; + U2fRequest::ResponseCallback callback_; + base::RunLoop run_loop_; +}; + +TEST_F(U2fRegisterTest, TestRegisterSuccess) { + std::unique_ptr<MockU2fDevice> device(new MockU2fDevice()); + EXPECT_CALL(*device.get(), DeviceTransactPtr(testing::_, testing::_)) + .WillOnce(testing::Invoke(MockU2fDevice::NoErrorRegister)); + EXPECT_CALL(*device.get(), TryWink(testing::_)) + .WillOnce(testing::Invoke(MockU2fDevice::WinkDoNothing)); + TestRegisterCallback cb; + std::unique_ptr<U2fRequest> request = U2fRegister::TryRegistration( + std::vector<uint8_t>(32), std::vector<uint8_t>(32), cb.callback()); + request->Start(); + request->AddDeviceForTesting(std::move(device)); + std::pair<U2fReturnCode, std::vector<uint8_t>>& response = + cb.WaitForCallback(); + EXPECT_EQ(U2fReturnCode::SUCCESS, response.first); + ASSERT_LT(static_cast<size_t>(0), response.second.size()); + EXPECT_EQ(static_cast<uint8_t>(MockU2fDevice::kRegister), response.second[0]); +} + +TEST_F(U2fRegisterTest, TestDelayedSuccess) { + std::unique_ptr<MockU2fDevice> device(new MockU2fDevice()); + + // Go through the state machine twice before success + EXPECT_CALL(*device.get(), DeviceTransactPtr(testing::_, testing::_)) + .WillOnce(testing::Invoke(MockU2fDevice::NotSatisfied)) + .WillOnce(testing::Invoke(MockU2fDevice::NoErrorRegister)); + EXPECT_CALL(*device.get(), TryWink(testing::_)) + .Times(2) + .WillRepeatedly(testing::Invoke(MockU2fDevice::WinkDoNothing)); + TestRegisterCallback cb; + + std::unique_ptr<U2fRequest> request = U2fRegister::TryRegistration( + std::vector<uint8_t>(32), std::vector<uint8_t>(32), cb.callback()); + request->Start(); + request->AddDeviceForTesting(std::move(device)); + std::pair<U2fReturnCode, std::vector<uint8_t>>& response = + cb.WaitForCallback(); + EXPECT_EQ(U2fReturnCode::SUCCESS, response.first); + ASSERT_LT(static_cast<size_t>(0), response.second.size()); + EXPECT_EQ(static_cast<uint8_t>(MockU2fDevice::kRegister), response.second[0]); +} + +TEST_F(U2fRegisterTest, TestMultipleDevices) { + // Second device will have a successful touch + std::unique_ptr<MockU2fDevice> device0(new MockU2fDevice()); + std::unique_ptr<MockU2fDevice> device1(new MockU2fDevice()); + + EXPECT_CALL(*device0.get(), DeviceTransactPtr(testing::_, testing::_)) + .WillOnce(testing::Invoke(MockU2fDevice::NotSatisfied)); + // One wink per device + EXPECT_CALL(*device0.get(), TryWink(testing::_)) + .WillOnce(testing::Invoke(MockU2fDevice::WinkDoNothing)); + EXPECT_CALL(*device1.get(), DeviceTransactPtr(testing::_, testing::_)) + .WillOnce(testing::Invoke(MockU2fDevice::NoErrorRegister)); + EXPECT_CALL(*device1.get(), TryWink(testing::_)) + .WillOnce(testing::Invoke(MockU2fDevice::WinkDoNothing)); + + TestRegisterCallback cb; + std::unique_ptr<U2fRequest> request = U2fRegister::TryRegistration( + std::vector<uint8_t>(32), std::vector<uint8_t>(32), cb.callback()); + request->Start(); + request->AddDeviceForTesting(std::move(device0)); + request->AddDeviceForTesting(std::move(device1)); + std::pair<U2fReturnCode, std::vector<uint8_t>>& response = + cb.WaitForCallback(); + EXPECT_EQ(U2fReturnCode::SUCCESS, response.first); + ASSERT_LT(static_cast<size_t>(0), response.second.size()); + EXPECT_EQ(static_cast<uint8_t>(MockU2fDevice::kRegister), response.second[0]); +} + +} // namespace device diff --git a/chromium/device/u2f/u2f_request.cc b/chromium/device/u2f/u2f_request.cc new file mode 100644 index 00000000000..a010352ba75 --- /dev/null +++ b/chromium/device/u2f/u2f_request.cc @@ -0,0 +1,148 @@ +// Copyright 2017 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 "u2f_request.h" + +#include "base/bind.h" +#include "base/memory/ptr_util.h" +#include "base/threading/thread_task_runner_handle.h" +#include "device/base/device_client.h" +#include "u2f_hid_device.h" + +namespace device { + +U2fRequest::U2fRequest(const ResponseCallback& cb) + : state_(State::INIT), + cb_(cb), + hid_service_observer_(this), + weak_factory_(this) { + filter_.SetUsagePage(0xf1d0); +} + +void U2fRequest::Transition() { + switch (state_) { + case State::IDLE: + IterateDevice(); + if (!current_device_) { + // No devices available + state_ = State::OFF; + break; + } + state_ = State::WINK; + current_device_->TryWink( + base::Bind(&U2fRequest::Transition, weak_factory_.GetWeakPtr())); + break; + case State::WINK: + state_ = State::BUSY; + TryDevice(); + default: + break; + } +} + +void U2fRequest::Start() { + if (state_ == State::INIT) { + state_ = State::BUSY; + Enumerate(); + } +} + +void U2fRequest::Enumerate() { + HidService* hid_service = DeviceClient::Get()->GetHidService(); + DCHECK(hid_service); + hid_service_observer_.Add(hid_service); + hid_service->GetDevices( + base::Bind(&U2fRequest::OnEnumerate, weak_factory_.GetWeakPtr())); +} + +void U2fRequest::OnEnumerate( + const std::vector<scoped_refptr<HidDeviceInfo>>& devices) { + for (auto device_info : devices) { + if (filter_.Matches(device_info)) + devices_.push_back(base::MakeUnique<U2fHidDevice>(device_info)); + } + + state_ = State::IDLE; + Transition(); +} + +void U2fRequest::OnDeviceAdded(scoped_refptr<HidDeviceInfo> device_info) { + // Ignore non-U2F devices + if (!filter_.Matches(device_info)) + return; + + auto device = base::MakeUnique<U2fHidDevice>(device_info); + AddDevice(std::move(device)); +} + +void U2fRequest::OnDeviceRemoved(scoped_refptr<HidDeviceInfo> device_info) { + // Ignore non-U2F devices + if (!filter_.Matches(device_info)) + return; + + auto device = base::MakeUnique<U2fHidDevice>(device_info); + + // Check if the active device was removed + if (current_device_ && current_device_->GetId() == device->GetId()) { + current_device_ = nullptr; + state_ = State::IDLE; + Transition(); + return; + } + + // Remove the device if it exists in either device list + devices_.remove_if([&device](const std::unique_ptr<U2fDevice>& this_device) { + return this_device->GetId() == device->GetId(); + }); + attempted_devices_.remove_if( + [&device](const std::unique_ptr<U2fDevice>& this_device) { + return this_device->GetId() == device->GetId(); + }); +} + +void U2fRequest::IterateDevice() { + // Move active device to attempted device list + if (current_device_) + attempted_devices_.push_back(std::move(current_device_)); + + // If there is an additional device on device list, make it active. + // Otherwise, if all devices have been tried, move attempted devices back to + // the main device list. + if (devices_.size() > 0) { + current_device_ = std::move(devices_.front()); + devices_.pop_front(); + } else if (attempted_devices_.size() > 0) { + devices_ = std::move(attempted_devices_); + // After trying every device, wait 200ms before trying again + delay_callback_.Reset( + base::Bind(&U2fRequest::OnWaitComplete, weak_factory_.GetWeakPtr())); + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, delay_callback_.callback(), + base::TimeDelta::FromMilliseconds(200)); + } +} + +void U2fRequest::OnWaitComplete() { + state_ = State::IDLE; + Transition(); +} + +void U2fRequest::AddDevice(std::unique_ptr<U2fDevice> device) { + devices_.push_back(std::move(device)); + + // Start the state machine if this is the only device + if (state_ == State::OFF) { + state_ = State::IDLE; + delay_callback_.Cancel(); + Transition(); + } +} + +void U2fRequest::AddDeviceForTesting(std::unique_ptr<U2fDevice> device) { + AddDevice(std::move(device)); +} + +U2fRequest::~U2fRequest() {} + +} // namespace device diff --git a/chromium/device/u2f/u2f_request.h b/chromium/device/u2f/u2f_request.h new file mode 100644 index 00000000000..f8d8f3ab840 --- /dev/null +++ b/chromium/device/u2f/u2f_request.h @@ -0,0 +1,66 @@ +// Copyright 2017 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 DEVICE_U2F_U2F_REQUEST_H_ +#define DEVICE_U2F_U2F_REQUEST_H_ + +#include "base/cancelable_callback.h" +#include "base/scoped_observer.h" +#include "device/hid/hid_device_filter.h" +#include "device/hid/hid_service.h" +#include "u2f_device.h" + +namespace device { +class U2fRequest : HidService::Observer { + public: + using ResponseCallback = + base::Callback<void(U2fReturnCode status_code, + const std::vector<uint8_t>& response)>; + + U2fRequest(const ResponseCallback& callback); + virtual ~U2fRequest(); + + void Start(); + void AddDeviceForTesting(std::unique_ptr<U2fDevice> device); + + protected: + enum class State { + INIT, + BUSY, + WINK, + IDLE, + OFF, + COMPLETE, + }; + + void Transition(); + virtual void TryDevice() = 0; + + std::unique_ptr<U2fDevice> current_device_; + State state_; + ResponseCallback cb_; + + private: + FRIEND_TEST_ALL_PREFIXES(U2fRequestTest, TestAddRemoveDevice); + FRIEND_TEST_ALL_PREFIXES(U2fRequestTest, TestIterateDevice); + FRIEND_TEST_ALL_PREFIXES(U2fRequestTest, TestBasicMachine); + + void Enumerate(); + void IterateDevice(); + void OnWaitComplete(); + void AddDevice(std::unique_ptr<U2fDevice> device); + void OnDeviceAdded(scoped_refptr<HidDeviceInfo> device_info) override; + void OnDeviceRemoved(scoped_refptr<HidDeviceInfo> device_info) override; + void OnEnumerate(const std::vector<scoped_refptr<HidDeviceInfo>>& devices); + + std::list<std::unique_ptr<U2fDevice>> devices_; + std::list<std::unique_ptr<U2fDevice>> attempted_devices_; + base::CancelableClosure delay_callback_; + HidDeviceFilter filter_; + ScopedObserver<HidService, HidService::Observer> hid_service_observer_; + base::WeakPtrFactory<U2fRequest> weak_factory_; +}; +} // namespace device + +#endif // DEVICE_U2F_U2F_REQUEST_H_ diff --git a/chromium/device/u2f/u2f_request_unittest.cc b/chromium/device/u2f/u2f_request_unittest.cc new file mode 100644 index 00000000000..718e83805a2 --- /dev/null +++ b/chromium/device/u2f/u2f_request_unittest.cc @@ -0,0 +1,164 @@ +// Copyright 2017 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 <list> + +#include "base/memory/ptr_util.h" +#include "base/run_loop.h" +#include "base/test/scoped_task_environment.h" +#include "base/test/test_io_thread.h" +#include "device/base/mock_device_client.h" +#include "device/hid/mock_hid_service.h" +#include "device/test/test_device_client.h" +#include "device/test/usb_test_gadget.h" +#include "device/u2f/u2f_hid_device.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "u2f_request.h" + +namespace device { +namespace { +#if defined(OS_MACOSX) +const uint64_t kTestDeviceId0 = 42; +const uint64_t kTestDeviceId1 = 43; +const uint64_t kTestDeviceId2 = 44; +#else +const char* kTestDeviceId0 = "device0"; +const char* kTestDeviceId1 = "device1"; +const char* kTestDeviceId2 = "device2"; +#endif + +class FakeU2fRequest : public U2fRequest { + public: + FakeU2fRequest(const ResponseCallback& cb) : U2fRequest(cb) {} + ~FakeU2fRequest() override {} + + void TryDevice() override { + cb_.Run(U2fReturnCode::SUCCESS, std::vector<uint8_t>()); + } +}; +} // namespace + +class TestResponseCallback { + public: + TestResponseCallback() + : callback_(base::Bind(&TestResponseCallback::ReceivedCallback, + base::Unretained(this))) {} + ~TestResponseCallback() {} + + void ReceivedCallback(U2fReturnCode status, + const std::vector<uint8_t>& data) { + closure_.Run(); + } + + void WaitForCallback() { + closure_ = run_loop_.QuitClosure(); + run_loop_.Run(); + } + + U2fRequest::ResponseCallback& callback() { return callback_; } + + private: + base::Closure closure_; + U2fRequest::ResponseCallback callback_; + base::RunLoop run_loop_; +}; + +class U2fRequestTest : public testing::Test { + public: + U2fRequestTest() + : scoped_task_environment_( + base::test::ScopedTaskEnvironment::MainThreadType::UI), + io_thread_(base::TestIOThread::kAutoStart) {} + + protected: + base::test::ScopedTaskEnvironment scoped_task_environment_; + base::TestIOThread io_thread_; + device::MockDeviceClient device_client_; +}; + +TEST_F(U2fRequestTest, TestAddRemoveDevice) { + MockHidService* hid_service = device_client_.hid_service(); + HidCollectionInfo c_info; + hid_service->FirstEnumerationComplete(); + + TestResponseCallback cb; + FakeU2fRequest request(cb.callback()); + request.Enumerate(); + EXPECT_EQ(static_cast<size_t>(0), request.devices_.size()); + + // Add one U2F device + c_info.usage = HidUsageAndPage(1, static_cast<HidUsageAndPage::Page>(0xf1d0)); + scoped_refptr<HidDeviceInfo> u2f_device = make_scoped_refptr( + new HidDeviceInfo(kTestDeviceId0, 0, 0, "Test Fido Device", "123FIDO", + kHIDBusTypeUSB, c_info, 64, 64, 0)); + hid_service->AddDevice(u2f_device); + EXPECT_EQ(static_cast<size_t>(1), request.devices_.size()); + + // Add one non-U2F device. Verify that it is not added to our device list. + scoped_refptr<HidDeviceInfo> other_device = make_scoped_refptr( + new HidDeviceInfo(kTestDeviceId2, 0, 0, "Other Device", "OtherDevice", + kHIDBusTypeUSB, std::vector<uint8_t>())); + hid_service->AddDevice(other_device); + EXPECT_EQ(static_cast<size_t>(1), request.devices_.size()); + + // Remove the non-U2F device and verify that device list was unchanged. + hid_service->RemoveDevice(kTestDeviceId2); + EXPECT_EQ(static_cast<size_t>(1), request.devices_.size()); + + // Remove the U2F device and verify that device list is empty. + hid_service->RemoveDevice(kTestDeviceId0); + EXPECT_EQ(static_cast<size_t>(0), request.devices_.size()); +} + +TEST_F(U2fRequestTest, TestIterateDevice) { + TestResponseCallback cb; + FakeU2fRequest request(cb.callback()); + HidCollectionInfo c_info; + // Add one U2F device and one non-U2f device + c_info.usage = HidUsageAndPage(1, static_cast<HidUsageAndPage::Page>(0xf1d0)); + scoped_refptr<HidDeviceInfo> device0 = make_scoped_refptr( + new HidDeviceInfo(kTestDeviceId0, 0, 0, "Test Fido Device", "123FIDO", + kHIDBusTypeUSB, c_info, 64, 64, 0)); + request.devices_.push_back(base::MakeUnique<U2fHidDevice>(device0)); + scoped_refptr<HidDeviceInfo> device1 = make_scoped_refptr( + new HidDeviceInfo(kTestDeviceId1, 0, 0, "Test Fido Device", "123FIDO", + kHIDBusTypeUSB, c_info, 64, 64, 0)); + request.devices_.push_back(base::MakeUnique<U2fHidDevice>(device1)); + + // Move first device to current + request.IterateDevice(); + ASSERT_NE(nullptr, request.current_device_); + EXPECT_EQ(static_cast<size_t>(1), request.devices_.size()); + + // Move second device to current, first to attempted + request.IterateDevice(); + ASSERT_NE(nullptr, request.current_device_); + EXPECT_EQ(static_cast<size_t>(1), request.attempted_devices_.size()); + + // Move second device from current to attempted, move attempted to devices as + // all devices have been attempted + request.IterateDevice(); + ASSERT_EQ(nullptr, request.current_device_); + EXPECT_EQ(static_cast<size_t>(2), request.devices_.size()); + EXPECT_EQ(static_cast<size_t>(0), request.attempted_devices_.size()); +} + +TEST_F(U2fRequestTest, TestBasicMachine) { + MockHidService* hid_service = device_client_.hid_service(); + hid_service->FirstEnumerationComplete(); + TestResponseCallback cb; + FakeU2fRequest request(cb.callback()); + request.Start(); + // Add one U2F device + HidCollectionInfo c_info; + c_info.usage = HidUsageAndPage(1, static_cast<HidUsageAndPage::Page>(0xf1d0)); + scoped_refptr<HidDeviceInfo> u2f_device = make_scoped_refptr( + new HidDeviceInfo(kTestDeviceId0, 0, 0, "Test Fido Device", "123FIDO", + kHIDBusTypeUSB, c_info, 64, 64, 0)); + hid_service->AddDevice(u2f_device); + cb.WaitForCallback(); + EXPECT_EQ(U2fRequest::State::BUSY, request.state_); +} + +} // namespace device diff --git a/chromium/device/u2f/u2f_return_code.h b/chromium/device/u2f/u2f_return_code.h new file mode 100644 index 00000000000..4aa0b4284e7 --- /dev/null +++ b/chromium/device/u2f/u2f_return_code.h @@ -0,0 +1,19 @@ +// Copyright 2017 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 DEVICE_U2F_U2F_RETURN_CODE_H_ +#define DEVICE_U2F_U2F_RETURN_CODE_H_ + +namespace device { + +enum class U2fReturnCode : uint8_t { + SUCCESS, + FAILURE, + INVALID_PARAMS, + CONDITIONS_NOT_SATISFIED, +}; + +} // namespace device + +#endif // DEVICE_U2F_U2F_RETURN_CODE_H_ diff --git a/chromium/device/u2f/u2f_sign.cc b/chromium/device/u2f/u2f_sign.cc new file mode 100644 index 00000000000..a1f5b7d3d5a --- /dev/null +++ b/chromium/device/u2f/u2f_sign.cc @@ -0,0 +1,92 @@ +// Copyright 2017 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 "u2f_sign.h" + +#include "base/memory/ptr_util.h" + +namespace device { + +U2fSign::U2fSign(const std::vector<std::vector<uint8_t>>& registered_keys, + const std::vector<uint8_t>& challenge_hash, + const std::vector<uint8_t>& app_param, + const ResponseCallback& cb) + : U2fRequest(cb), + registered_keys_(registered_keys), + challenge_hash_(challenge_hash), + app_param_(app_param), + weak_factory_(this) {} + +U2fSign::~U2fSign() {} + +// static +std::unique_ptr<U2fRequest> U2fSign::TrySign( + const std::vector<std::vector<uint8_t>>& registered_keys, + const std::vector<uint8_t>& challenge_hash, + const std::vector<uint8_t>& app_param, + const ResponseCallback& cb) { + std::unique_ptr<U2fRequest> request = + base::MakeUnique<U2fSign>(registered_keys, challenge_hash, app_param, cb); + request->Start(); + return request; +} + +void U2fSign::TryDevice() { + DCHECK(current_device_); + + if (registered_keys_.size() == 0) { + // Send registration (Fake enroll) if no keys were provided + current_device_->Register( + kBogusAppParam, kBogusChallenge, + base::Bind(&U2fSign::OnTryDevice, weak_factory_.GetWeakPtr(), + registered_keys_.cbegin())); + return; + } + // Try signing current device with the first registered key + auto it = registered_keys_.cbegin(); + current_device_->Sign( + app_param_, challenge_hash_, *it, + base::Bind(&U2fSign::OnTryDevice, weak_factory_.GetWeakPtr(), it)); +} + +void U2fSign::OnTryDevice(std::vector<std::vector<uint8_t>>::const_iterator it, + U2fReturnCode return_code, + const std::vector<uint8_t>& response_data) { + switch (return_code) { + case U2fReturnCode::SUCCESS: + state_ = State::COMPLETE; + cb_.Run(return_code, response_data); + break; + case U2fReturnCode::CONDITIONS_NOT_SATISFIED: { + // Key handle is accepted by this device, but waiting on user touch. Move + // on and try this device again later. + state_ = State::IDLE; + Transition(); + break; + } + case U2fReturnCode::INVALID_PARAMS: + if (++it != registered_keys_.end()) { + // Key is not for this device. Try signing with the next key. + current_device_->Sign( + app_param_, challenge_hash_, *it, + base::Bind(&U2fSign::OnTryDevice, weak_factory_.GetWeakPtr(), it)); + } else { + // No provided key was accepted by this device. Send registration + // (Fake enroll) request to device. + current_device_->Register( + kBogusAppParam, kBogusChallenge, + base::Bind(&U2fSign::OnTryDevice, weak_factory_.GetWeakPtr(), + registered_keys_.cbegin())); + } + break; + default: + // Some sort of failure occured. Abandon this device and move on. + state_ = State::IDLE; + current_device_ = nullptr; + Transition(); + break; + } +} + +} // namespace device diff --git a/chromium/device/u2f/u2f_sign.h b/chromium/device/u2f/u2f_sign.h new file mode 100644 index 00000000000..912fc77efa8 --- /dev/null +++ b/chromium/device/u2f/u2f_sign.h @@ -0,0 +1,51 @@ +// Copyright 2017 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 DEVICE_U2F_U2F_SIGN_H_ +#define DEVICE_U2F_U2F_SIGN_H_ + +#include <vector> + +#include "u2f_request.h" + +namespace device { + +class U2fSign : public U2fRequest { + public: + U2fSign(const std::vector<std::vector<uint8_t>>& registered_keys, + const std::vector<uint8_t>& challenge_hash, + const std::vector<uint8_t>& app_param, + const ResponseCallback& cb); + ~U2fSign() override; + + static std::unique_ptr<U2fRequest> TrySign( + const std::vector<std::vector<uint8_t>>& registered_keys, + const std::vector<uint8_t>& challenge_hash, + const std::vector<uint8_t>& app_param, + const ResponseCallback& cb); + + private: + void TryDevice() override; + void OnTryDevice(std::vector<std::vector<uint8_t>>::const_iterator it, + U2fReturnCode return_code, + const std::vector<uint8_t>& response_data); + + const std::vector<std::vector<uint8_t>> registered_keys_; + std::vector<uint8_t> challenge_hash_; + std::vector<uint8_t> app_param_; + const std::vector<uint8_t> kBogusAppParam = { + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41}; + const std::vector<uint8_t> kBogusChallenge = { + 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42}; + + base::WeakPtrFactory<U2fSign> weak_factory_; +}; + +} // namespace device + +#endif // DEVICE_U2F_U2F_SIGN_H_ diff --git a/chromium/device/u2f/u2f_sign_unittest.cc b/chromium/device/u2f/u2f_sign_unittest.cc new file mode 100644 index 00000000000..fe53e38e432 --- /dev/null +++ b/chromium/device/u2f/u2f_sign_unittest.cc @@ -0,0 +1,219 @@ +// Copyright 2017 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 <list> + +#include "base/run_loop.h" +#include "base/test/scoped_task_environment.h" +#include "base/test/test_io_thread.h" +#include "device/base/mock_device_client.h" +#include "device/hid/mock_hid_service.h" +#include "device/test/test_device_client.h" +#include "mock_u2f_device.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "u2f_sign.h" + +namespace device { +class U2fSignTest : public testing::Test { + public: + U2fSignTest() + : scoped_task_environment_( + base::test::ScopedTaskEnvironment::MainThreadType::UI), + io_thread_(base::TestIOThread::kAutoStart) {} + + void SetUp() override { + MockHidService* hid_service = device_client_.hid_service(); + hid_service->FirstEnumerationComplete(); + } + + protected: + base::test::ScopedTaskEnvironment scoped_task_environment_; + base::TestIOThread io_thread_; + device::MockDeviceClient device_client_; +}; + +class TestSignCallback { + public: + TestSignCallback() + : callback_(base::Bind(&TestSignCallback::ReceivedCallback, + base::Unretained(this))) {} + ~TestSignCallback() {} + + void ReceivedCallback(U2fReturnCode status_code, + const std::vector<uint8_t>& response) { + response_ = std::make_pair(status_code, response); + closure_.Run(); + } + + std::pair<U2fReturnCode, std::vector<uint8_t>>& WaitForCallback() { + closure_ = run_loop_.QuitClosure(); + run_loop_.Run(); + return response_; + } + + const U2fRequest::ResponseCallback& callback() { return callback_; } + + private: + std::pair<U2fReturnCode, std::vector<uint8_t>> response_; + base::Closure closure_; + U2fRequest::ResponseCallback callback_; + base::RunLoop run_loop_; +}; + +TEST_F(U2fSignTest, TestSignSuccess) { + std::vector<uint8_t> key(32, 0xA); + std::vector<std::vector<uint8_t>> handles = {key}; + std::unique_ptr<MockU2fDevice> device(new MockU2fDevice()); + EXPECT_CALL(*device.get(), DeviceTransactPtr(testing::_, testing::_)) + .WillOnce(testing::Invoke(MockU2fDevice::NoErrorSign)); + EXPECT_CALL(*device.get(), TryWink(testing::_)) + .WillOnce(testing::Invoke(MockU2fDevice::WinkDoNothing)); + TestSignCallback cb; + std::unique_ptr<U2fRequest> request = + U2fSign::TrySign(handles, std::vector<uint8_t>(32), + std::vector<uint8_t>(32), cb.callback()); + request->Start(); + request->AddDeviceForTesting(std::move(device)); + std::pair<U2fReturnCode, std::vector<uint8_t>>& response = + cb.WaitForCallback(); + EXPECT_EQ(U2fReturnCode::SUCCESS, response.first); + // Correct key was sent so a sign response is expected + ASSERT_LT(static_cast<size_t>(0), response.second.size()); + EXPECT_EQ(static_cast<uint8_t>(MockU2fDevice::kSign), response.second[0]); +} + +TEST_F(U2fSignTest, TestDelayedSuccess) { + std::vector<uint8_t> key(32, 0xA); + std::vector<std::vector<uint8_t>> handles = {key}; + std::unique_ptr<MockU2fDevice> device(new MockU2fDevice()); + + // Go through the state machine twice before success + EXPECT_CALL(*device.get(), DeviceTransactPtr(testing::_, testing::_)) + .WillOnce(testing::Invoke(MockU2fDevice::NotSatisfied)) + .WillOnce(testing::Invoke(MockU2fDevice::NoErrorSign)); + EXPECT_CALL(*device.get(), TryWink(testing::_)) + .Times(2) + .WillRepeatedly(testing::Invoke(MockU2fDevice::WinkDoNothing)); + TestSignCallback cb; + + std::unique_ptr<U2fRequest> request = + U2fSign::TrySign(handles, std::vector<uint8_t>(32), + std::vector<uint8_t>(32), cb.callback()); + request->Start(); + request->AddDeviceForTesting(std::move(device)); + std::pair<U2fReturnCode, std::vector<uint8_t>>& response = + cb.WaitForCallback(); + EXPECT_EQ(U2fReturnCode::SUCCESS, response.first); + // Correct key was sent so a sign response is expected + ASSERT_LT(static_cast<size_t>(0), response.second.size()); + EXPECT_EQ(static_cast<uint8_t>(MockU2fDevice::kSign), response.second[0]); +} + +TEST_F(U2fSignTest, TestMultipleHandles) { + std::vector<uint8_t> key(32, 0xA); + std::vector<uint8_t> wrong_key0(32, 0xB); + std::vector<uint8_t> wrong_key1(32, 0xC); + std::vector<uint8_t> wrong_key2(32, 0xD); + // Put wrong key first to ensure that it will be tested before the correct key + std::vector<std::vector<uint8_t>> handles = {wrong_key0, wrong_key1, + wrong_key2, key}; + std::unique_ptr<MockU2fDevice> device(new MockU2fDevice()); + + // Wrong key would respond with SW_WRONG_DATA + EXPECT_CALL(*device.get(), DeviceTransactPtr(testing::_, testing::_)) + .WillOnce(testing::Invoke(MockU2fDevice::WrongData)) + .WillOnce(testing::Invoke(MockU2fDevice::WrongData)) + .WillOnce(testing::Invoke(MockU2fDevice::WrongData)) + .WillOnce(testing::Invoke(MockU2fDevice::NoErrorSign)); + // Only one wink expected per device + EXPECT_CALL(*device.get(), TryWink(testing::_)) + .WillOnce(testing::Invoke(MockU2fDevice::WinkDoNothing)); + + TestSignCallback cb; + std::unique_ptr<U2fRequest> request = + U2fSign::TrySign(handles, std::vector<uint8_t>(32), + std::vector<uint8_t>(32), cb.callback()); + request->Start(); + request->AddDeviceForTesting(std::move(device)); + std::pair<U2fReturnCode, std::vector<uint8_t>>& response = + cb.WaitForCallback(); + EXPECT_EQ(U2fReturnCode::SUCCESS, response.first); + // Correct key was sent so a sign response is expected + ASSERT_LT(static_cast<size_t>(0), response.second.size()); + EXPECT_EQ(static_cast<uint8_t>(MockU2fDevice::kSign), response.second[0]); +} + +TEST_F(U2fSignTest, TestMultipleDevices) { + std::vector<uint8_t> key0(32, 0xA); + std::vector<uint8_t> key1(32, 0xB); + // Second device will have a successful touch + std::vector<std::vector<uint8_t>> handles = {key0, key1}; + std::unique_ptr<MockU2fDevice> device0(new MockU2fDevice()); + std::unique_ptr<MockU2fDevice> device1(new MockU2fDevice()); + + EXPECT_CALL(*device0.get(), DeviceTransactPtr(testing::_, testing::_)) + .WillOnce(testing::Invoke(MockU2fDevice::WrongData)) + .WillOnce(testing::Invoke(MockU2fDevice::NotSatisfied)); + // One wink per device + EXPECT_CALL(*device0.get(), TryWink(testing::_)) + .WillOnce(testing::Invoke(MockU2fDevice::WinkDoNothing)); + EXPECT_CALL(*device1.get(), DeviceTransactPtr(testing::_, testing::_)) + .WillOnce(testing::Invoke(MockU2fDevice::NoErrorSign)); + EXPECT_CALL(*device1.get(), TryWink(testing::_)) + .WillOnce(testing::Invoke(MockU2fDevice::WinkDoNothing)); + + TestSignCallback cb; + std::unique_ptr<U2fRequest> request = + U2fSign::TrySign(handles, std::vector<uint8_t>(32), + std::vector<uint8_t>(32), cb.callback()); + request->Start(); + request->AddDeviceForTesting(std::move(device0)); + request->AddDeviceForTesting(std::move(device1)); + std::pair<U2fReturnCode, std::vector<uint8_t>>& response = + cb.WaitForCallback(); + EXPECT_EQ(U2fReturnCode::SUCCESS, response.first); + // Correct key was sent so a sign response is expected + ASSERT_LT(static_cast<size_t>(0), response.second.size()); + EXPECT_EQ(static_cast<uint8_t>(MockU2fDevice::kSign), response.second[0]); +} + +TEST_F(U2fSignTest, TestFakeEnroll) { + std::vector<uint8_t> key0(32, 0xA); + std::vector<uint8_t> key1(32, 0xB); + // Second device will be have a successful touch + std::vector<std::vector<uint8_t>> handles = {key0, key1}; + std::unique_ptr<MockU2fDevice> device0(new MockU2fDevice()); + std::unique_ptr<MockU2fDevice> device1(new MockU2fDevice()); + + EXPECT_CALL(*device0.get(), DeviceTransactPtr(testing::_, testing::_)) + .WillOnce(testing::Invoke(MockU2fDevice::WrongData)) + .WillOnce(testing::Invoke(MockU2fDevice::NotSatisfied)); + // One wink per device + EXPECT_CALL(*device0.get(), TryWink(testing::_)) + .WillOnce(testing::Invoke(MockU2fDevice::WinkDoNothing)); + // Both keys will be tried, when both fail, register is tried on that device + EXPECT_CALL(*device1.get(), DeviceTransactPtr(testing::_, testing::_)) + .WillOnce(testing::Invoke(MockU2fDevice::WrongData)) + .WillOnce(testing::Invoke(MockU2fDevice::WrongData)) + .WillOnce(testing::Invoke(MockU2fDevice::NoErrorRegister)); + EXPECT_CALL(*device1.get(), TryWink(testing::_)) + .WillOnce(testing::Invoke(MockU2fDevice::WinkDoNothing)); + + TestSignCallback cb; + std::unique_ptr<U2fRequest> request = + U2fSign::TrySign(handles, std::vector<uint8_t>(32), + std::vector<uint8_t>(32), cb.callback()); + request->Start(); + request->AddDeviceForTesting(std::move(device0)); + request->AddDeviceForTesting(std::move(device1)); + std::pair<U2fReturnCode, std::vector<uint8_t>>& response = + cb.WaitForCallback(); + EXPECT_EQ(U2fReturnCode::SUCCESS, response.first); + // Device that responded had no correct keys, so a registration response is + // expected + ASSERT_LT(static_cast<size_t>(0), response.second.size()); + EXPECT_EQ(static_cast<uint8_t>(MockU2fDevice::kRegister), response.second[0]); +} + +} // namespace device diff --git a/chromium/device/udev_linux/BUILD.gn b/chromium/device/udev_linux/BUILD.gn index 0b6f60e44b7..853f58c0d75 100644 --- a/chromium/device/udev_linux/BUILD.gn +++ b/chromium/device/udev_linux/BUILD.gn @@ -18,6 +18,8 @@ if (use_udev) { "udev_linux.h", "udev_loader.cc", "udev_loader.h", + "udev_watcher.cc", + "udev_watcher.h", ] deps = [ diff --git a/chromium/device/udev_linux/udev_watcher.cc b/chromium/device/udev_linux/udev_watcher.cc new file mode 100644 index 00000000000..d9e490de63a --- /dev/null +++ b/chromium/device/udev_linux/udev_watcher.cc @@ -0,0 +1,98 @@ +// Copyright 2017 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 "device/udev_linux/udev_watcher.h" + +#include "base/bind.h" +#include "base/memory/ptr_util.h" + +namespace device { + +UdevWatcher::Observer::~Observer() = default; + +void UdevWatcher::Observer::OnDeviceAdded(ScopedUdevDevicePtr device) {} + +void UdevWatcher::Observer::OnDeviceRemoved(ScopedUdevDevicePtr device) {} + +std::unique_ptr<UdevWatcher> UdevWatcher::StartWatching(Observer* observer) { + ScopedUdevPtr udev(udev_new()); + if (!udev) { + LOG(ERROR) << "Failed to initialize udev."; + return nullptr; + } + + ScopedUdevMonitorPtr udev_monitor( + udev_monitor_new_from_netlink(udev.get(), "udev")); + if (!udev_monitor) { + LOG(ERROR) << "Failed to initialize a udev monitor."; + return nullptr; + } + + if (udev_monitor_enable_receiving(udev_monitor.get()) != 0) { + LOG(ERROR) << "Failed to enable receiving udev events."; + return nullptr; + } + + int monitor_fd = udev_monitor_get_fd(udev_monitor.get()); + if (monitor_fd < 0) { + LOG(ERROR) << "Udev monitor file descriptor unavailable."; + return nullptr; + } + + return base::WrapUnique(new UdevWatcher( + std::move(udev), std::move(udev_monitor), monitor_fd, observer)); +} + +UdevWatcher::~UdevWatcher() { + DCHECK(sequence_checker_.CalledOnValidSequence()); +}; + +void UdevWatcher::EnumerateExistingDevices() { + DCHECK(sequence_checker_.CalledOnValidSequence()); + ScopedUdevEnumeratePtr enumerate(udev_enumerate_new(udev_.get())); + if (!enumerate) { + LOG(ERROR) << "Failed to initialize a udev enumerator."; + return; + } + + if (udev_enumerate_scan_devices(enumerate.get()) != 0) { + LOG(ERROR) << "Failed to begin udev enumeration."; + return; + } + + udev_list_entry* devices = udev_enumerate_get_list_entry(enumerate.get()); + for (udev_list_entry* i = devices; i != nullptr; + i = udev_list_entry_get_next(i)) { + ScopedUdevDevicePtr device( + udev_device_new_from_syspath(udev_.get(), udev_list_entry_get_name(i))); + if (device) + observer_->OnDeviceAdded(std::move(device)); + } +} + +UdevWatcher::UdevWatcher(ScopedUdevPtr udev, + ScopedUdevMonitorPtr udev_monitor, + int monitor_fd, + Observer* observer) + : udev_(std::move(udev)), + udev_monitor_(std::move(udev_monitor)), + observer_(observer) { + file_watcher_ = base::FileDescriptorWatcher::WatchReadable( + monitor_fd, + base::Bind(&UdevWatcher::OnMonitorReadable, base::Unretained(this))); +} + +void UdevWatcher::OnMonitorReadable() { + ScopedUdevDevicePtr device(udev_monitor_receive_device(udev_monitor_.get())); + if (!device) + return; + + std::string action(udev_device_get_action(device.get())); + if (action == "add") + observer_->OnDeviceAdded(std::move(device)); + else if (action == "remove") + observer_->OnDeviceRemoved(std::move(device)); +} + +} // namespace device diff --git a/chromium/device/udev_linux/udev_watcher.h b/chromium/device/udev_linux/udev_watcher.h new file mode 100644 index 00000000000..0da372b291d --- /dev/null +++ b/chromium/device/udev_linux/udev_watcher.h @@ -0,0 +1,55 @@ +// Copyright 2017 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 DEVICE_UDEV_LINUX_UDEV_WATCHER_H_ +#define DEVICE_UDEV_LINUX_UDEV_WATCHER_H_ + +#include <memory> + +#include "base/files/file_descriptor_watcher_posix.h" +#include "base/macros.h" +#include "base/sequence_checker.h" +#include "device/udev_linux/scoped_udev.h" + +namespace device { + +// This class wraps an instance of udev_monitor, watching for devices that are +// added and removed from the system. This class has sequence affinity. +class UdevWatcher { + public: + class Observer { + public: + virtual ~Observer(); + virtual void OnDeviceAdded(ScopedUdevDevicePtr device); + virtual void OnDeviceRemoved(ScopedUdevDevicePtr device); + }; + + static std::unique_ptr<UdevWatcher> StartWatching(Observer* observer); + + ~UdevWatcher(); + + // Synchronously enumerates the all devices known to udev, calling + // OnDeviceAdded on the provided Observer for each. + void EnumerateExistingDevices(); + + private: + UdevWatcher(ScopedUdevPtr udev, + ScopedUdevMonitorPtr udev_monitor, + int monitor_fd, + Observer* observer); + + void OnMonitorReadable(); + + ScopedUdevPtr udev_; + ScopedUdevMonitorPtr udev_monitor_; + Observer* observer_; + std::unique_ptr<base::FileDescriptorWatcher::Controller> file_watcher_; + base::SequenceChecker sequence_checker_; + + DISALLOW_COPY_AND_ASSIGN(UdevWatcher); +}; + +} // namespace device + +#endif // DEVICE_UDEV_LINUX_UDEV_WATCHER_H_ diff --git a/chromium/device/usb/BUILD.gn b/chromium/device/usb/BUILD.gn index 76fa59e24d4..83ff8c1140b 100644 --- a/chromium/device/usb/BUILD.gn +++ b/chromium/device/usb/BUILD.gn @@ -57,13 +57,22 @@ static_library("usb") { deps = [ ":usb_device_ids", - "//base", "//base/third_party/dynamic_annotations", "//components/device_event_log", "//device/base", "//net", ] + public_deps = [ + "//base", + "//url", + + # Depend on the header generation target only to avoid the circular + # dependency caused by both using enums defined in the mojom headers and + # typemappings linking against this target. + "public/interfaces:interfaces__generator", + ] + if (use_udev) { sources += [ "usb_service_linux.cc", diff --git a/chromium/device/usb/fake_usb_device_handle.cc b/chromium/device/usb/fake_usb_device_handle.cc index 27ddfb31c8d..78c0134b761 100644 --- a/chromium/device/usb/fake_usb_device_handle.cc +++ b/chromium/device/usb/fake_usb_device_handle.cc @@ -55,9 +55,9 @@ void FakeUsbDeviceHandle::ClearHalt(uint8_t endpoint, } void FakeUsbDeviceHandle::ControlTransfer( - UsbEndpointDirection direction, - UsbDeviceHandle::TransferRequestType request_type, - UsbDeviceHandle::TransferRecipient recipient, + UsbTransferDirection direction, + UsbControlTransferType request_type, + UsbControlTransferRecipient recipient, uint8_t request, uint16_t value, uint16_t index, @@ -66,7 +66,7 @@ void FakeUsbDeviceHandle::ControlTransfer( unsigned int timeout, const UsbDeviceHandle::TransferCallback& callback) { if (position_ == size_) { - callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0); + callback.Run(UsbTransferStatus::DISCONNECT, buffer, 0); return; } @@ -79,14 +79,14 @@ void FakeUsbDeviceHandle::ControlTransfer( bytes_transferred = std::min(bytes_transferred, size_ - position_); } - if (direction == USB_DIRECTION_INBOUND) { + if (direction == UsbTransferDirection::INBOUND) { memcpy(buffer->data(), &data_[position_], bytes_transferred); position_ += bytes_transferred; } - callback.Run(USB_TRANSFER_COMPLETED, buffer, bytes_transferred); + callback.Run(UsbTransferStatus::COMPLETED, buffer, bytes_transferred); } else { - callback.Run(USB_TRANSFER_ERROR, buffer, 0); + callback.Run(UsbTransferStatus::TRANSFER_ERROR, buffer, 0); } } @@ -107,7 +107,7 @@ void FakeUsbDeviceHandle::IsochronousTransferOut( NOTIMPLEMENTED(); } -void FakeUsbDeviceHandle::GenericTransfer(UsbEndpointDirection direction, +void FakeUsbDeviceHandle::GenericTransfer(UsbTransferDirection direction, uint8_t endpoint_number, scoped_refptr<net::IOBuffer> buffer, size_t length, diff --git a/chromium/device/usb/fake_usb_device_handle.h b/chromium/device/usb/fake_usb_device_handle.h index 121a287a3b0..aa48ad75be4 100644 --- a/chromium/device/usb/fake_usb_device_handle.h +++ b/chromium/device/usb/fake_usb_device_handle.h @@ -37,9 +37,9 @@ class FakeUsbDeviceHandle : public UsbDeviceHandle { void ResetDevice(const ResultCallback& callback) override; void ClearHalt(uint8_t endpoint, const ResultCallback& callback) override; - void ControlTransfer(UsbEndpointDirection direction, - TransferRequestType request_type, - TransferRecipient recipient, + void ControlTransfer(UsbTransferDirection direction, + UsbControlTransferType request_type, + UsbControlTransferRecipient recipient, uint8_t request, uint16_t value, uint16_t index, @@ -61,7 +61,7 @@ class FakeUsbDeviceHandle : public UsbDeviceHandle { unsigned int timeout, const IsochronousTransferCallback& callback) override; - void GenericTransfer(UsbEndpointDirection direction, + void GenericTransfer(UsbTransferDirection direction, uint8_t endpoint_number, scoped_refptr<net::IOBuffer> buffer, size_t length, diff --git a/chromium/device/usb/mock_usb_device.h b/chromium/device/usb/mock_usb_device.h index 7b7f2e786bb..6f3d0526c30 100644 --- a/chromium/device/usb/mock_usb_device.h +++ b/chromium/device/usb/mock_usb_device.h @@ -7,13 +7,11 @@ #include <stdint.h> -#include <memory> #include <string> #include <vector> #include "device/usb/usb_device.h" #include "device/usb/usb_device_handle.h" -#include "device/usb/webusb_descriptors.h" #include "testing/gmock/include/gmock/gmock.h" namespace device { @@ -50,11 +48,6 @@ class MockUsbDevice : public UsbDevice { void AddMockConfig(const UsbConfigDescriptor& config); - void set_webusb_allowed_origins( - std::unique_ptr<WebUsbAllowedOrigins> webusb_allowed_origins) { - webusb_allowed_origins_ = std::move(webusb_allowed_origins); - } - // Public wrappers around protected functions. void ActiveConfigurationChanged(int configuration_value); void NotifyDeviceRemoved(); diff --git a/chromium/device/usb/mock_usb_device_handle.h b/chromium/device/usb/mock_usb_device_handle.h index 5e2a3c237c5..15e6974f739 100644 --- a/chromium/device/usb/mock_usb_device_handle.h +++ b/chromium/device/usb/mock_usb_device_handle.h @@ -36,9 +36,9 @@ class MockUsbDeviceHandle : public UsbDeviceHandle { MOCK_METHOD2(ClearHalt, void(uint8_t endpoint, const ResultCallback& callback)); MOCK_METHOD10(ControlTransfer, - void(UsbEndpointDirection direction, - TransferRequestType request_type, - TransferRecipient recipient, + void(UsbTransferDirection direction, + UsbControlTransferType request_type, + UsbControlTransferRecipient recipient, uint8_t request, uint16_t value, uint16_t index, @@ -58,7 +58,7 @@ class MockUsbDeviceHandle : public UsbDeviceHandle { unsigned int timeout, const IsochronousTransferCallback& callback)); MOCK_METHOD6(GenericTransfer, - void(UsbEndpointDirection direction, + void(UsbTransferDirection direction, uint8_t endpoint, scoped_refptr<net::IOBuffer> buffer, size_t length, diff --git a/chromium/device/usb/mock_usb_service.cc b/chromium/device/usb/mock_usb_service.cc index 48ff6012f7e..930fbd9c3ff 100644 --- a/chromium/device/usb/mock_usb_service.cc +++ b/chromium/device/usb/mock_usb_service.cc @@ -14,10 +14,7 @@ namespace device { MockUsbService::MockUsbService() : UsbService(nullptr) {} -MockUsbService::~MockUsbService() { - // Shutdown() must be called before the base class destructor. - Shutdown(); -} +MockUsbService::~MockUsbService() = default; void MockUsbService::AddDevice(scoped_refptr<UsbDevice> device) { devices()[device->guid()] = device; diff --git a/chromium/device/usb/mojo/device_impl.cc b/chromium/device/usb/mojo/device_impl.cc index acbf4682c32..6bbb81bba61 100644 --- a/chromium/device/usb/mojo/device_impl.cc +++ b/chromium/device/usb/mojo/device_impl.cc @@ -22,6 +22,10 @@ #include "net/base/io_buffer.h" namespace device { + +using mojom::UsbControlTransferParamsPtr; +using mojom::UsbControlTransferRecipient; + namespace usb { namespace { @@ -31,7 +35,7 @@ scoped_refptr<net::IOBuffer> CreateTransferBuffer(size_t size) { std::max(static_cast<size_t>(1u), static_cast<size_t>(size))); } -void OnTransferIn(const Device::GenericTransferInCallback& callback, +void OnTransferIn(const mojom::UsbDevice::GenericTransferInCallback& callback, UsbTransferStatus status, scoped_refptr<net::IOBuffer> buffer, size_t buffer_size) { @@ -44,23 +48,23 @@ void OnTransferIn(const Device::GenericTransferInCallback& callback, std::copy(buffer->data(), buffer->data() + buffer_size, data.begin()); } - callback.Run(mojo::ConvertTo<TransferStatus>(status), data); + callback.Run(mojo::ConvertTo<mojom::UsbTransferStatus>(status), data); } -void OnTransferOut(const Device::GenericTransferOutCallback& callback, +void OnTransferOut(const mojom::UsbDevice::GenericTransferOutCallback& callback, UsbTransferStatus status, scoped_refptr<net::IOBuffer> buffer, size_t buffer_size) { - callback.Run(mojo::ConvertTo<TransferStatus>(status)); + callback.Run(mojo::ConvertTo<mojom::UsbTransferStatus>(status)); } -std::vector<IsochronousPacketPtr> BuildIsochronousPacketArray( +std::vector<mojom::UsbIsochronousPacketPtr> BuildIsochronousPacketArray( const std::vector<uint32_t>& packet_lengths, - TransferStatus status) { - std::vector<IsochronousPacketPtr> packets; + mojom::UsbTransferStatus status) { + std::vector<mojom::UsbIsochronousPacketPtr> packets; packets.reserve(packet_lengths.size()); for (uint32_t packet_length : packet_lengths) { - auto packet = IsochronousPacket::New(); + auto packet = mojom::UsbIsochronousPacket::New(); packet->length = packet_length; packet->status = status; packets.push_back(std::move(packet)); @@ -69,7 +73,7 @@ std::vector<IsochronousPacketPtr> BuildIsochronousPacketArray( } void OnIsochronousTransferIn( - const Device::IsochronousTransferInCallback& callback, + const mojom::UsbDevice::IsochronousTransferInCallback& callback, scoped_refptr<net::IOBuffer> buffer, const std::vector<UsbDeviceHandle::IsochronousPacket>& packets) { std::vector<uint8_t> data; @@ -86,23 +90,25 @@ void OnIsochronousTransferIn( data.resize(buffer_size); std::copy(buffer->data(), buffer->data() + buffer_size, data.begin()); } - callback.Run(data, - mojo::ConvertTo<std::vector<IsochronousPacketPtr>>(packets)); + callback.Run( + data, + mojo::ConvertTo<std::vector<mojom::UsbIsochronousPacketPtr>>(packets)); } void OnIsochronousTransferOut( - const Device::IsochronousTransferOutCallback& callback, + const mojom::UsbDevice::IsochronousTransferOutCallback& callback, scoped_refptr<net::IOBuffer> buffer, const std::vector<UsbDeviceHandle::IsochronousPacket>& packets) { - callback.Run(mojo::ConvertTo<std::vector<IsochronousPacketPtr>>(packets)); + callback.Run( + mojo::ConvertTo<std::vector<mojom::UsbIsochronousPacketPtr>>(packets)); } } // namespace // static -void DeviceImpl::Create(scoped_refptr<UsbDevice> device, +void DeviceImpl::Create(scoped_refptr<device::UsbDevice> device, base::WeakPtr<PermissionProvider> permission_provider, - DeviceRequest request) { + mojom::UsbDeviceRequest request) { auto* device_impl = new DeviceImpl(std::move(device), std::move(permission_provider)); device_impl->binding_ = mojo::MakeStrongBinding(base::WrapUnique(device_impl), @@ -113,7 +119,7 @@ DeviceImpl::~DeviceImpl() { CloseHandle(); } -DeviceImpl::DeviceImpl(scoped_refptr<UsbDevice> device, +DeviceImpl::DeviceImpl(scoped_refptr<device::UsbDevice> device, base::WeakPtr<PermissionProvider> permission_provider) : device_(std::move(device)), permission_provider_(std::move(permission_provider)), @@ -133,43 +139,33 @@ void DeviceImpl::CloseHandle() { } bool DeviceImpl::HasControlTransferPermission( - ControlTransferRecipient recipient, + UsbControlTransferRecipient recipient, uint16_t index) { DCHECK(device_handle_); - const UsbConfigDescriptor* config = device_->active_configuration(); - if (!permission_provider_) + if (recipient != UsbControlTransferRecipient::INTERFACE && + recipient != UsbControlTransferRecipient::ENDPOINT) { + return true; + } + + const UsbConfigDescriptor* config = device_->active_configuration(); + if (!config) return false; - if (recipient == ControlTransferRecipient::INTERFACE || - recipient == ControlTransferRecipient::ENDPOINT) { - if (!config) - return false; - - const UsbInterfaceDescriptor* interface = nullptr; - if (recipient == ControlTransferRecipient::ENDPOINT) { - interface = device_handle_->FindInterfaceByEndpoint(index & 0xff); - } else { - auto interface_it = - std::find_if(config->interfaces.begin(), config->interfaces.end(), - [index](const UsbInterfaceDescriptor& this_iface) { - return this_iface.interface_number == (index & 0xff); - }); - if (interface_it != config->interfaces.end()) - interface = &*interface_it; - } - if (interface == nullptr) - return false; - - return permission_provider_->HasFunctionPermission( - interface->first_interface, config->configuration_value, device_); - } else if (config) { - return permission_provider_->HasConfigurationPermission( - config->configuration_value, device_); + const UsbInterfaceDescriptor* interface = nullptr; + if (recipient == UsbControlTransferRecipient::ENDPOINT) { + interface = device_handle_->FindInterfaceByEndpoint(index & 0xff); } else { - // Client must already have device permission to have gotten this far. - return true; + auto interface_it = + std::find_if(config->interfaces.begin(), config->interfaces.end(), + [index](const UsbInterfaceDescriptor& this_iface) { + return this_iface.interface_number == (index & 0xff); + }); + if (interface_it != config->interfaces.end()) + interface = &*interface_it; } + + return interface != nullptr; } // static @@ -184,24 +180,23 @@ void DeviceImpl::OnOpen(base::WeakPtr<DeviceImpl> self, self->device_handle_ = std::move(handle); if (self->device_handle_ && self->permission_provider_) self->permission_provider_->IncrementConnectionCount(); - callback.Run(self->device_handle_ ? OpenDeviceError::OK - : OpenDeviceError::ACCESS_DENIED); + callback.Run(self->device_handle_ ? mojom::UsbOpenDeviceError::OK + : mojom::UsbOpenDeviceError::ACCESS_DENIED); } void DeviceImpl::OnPermissionGrantedForOpen(const OpenCallback& callback, bool granted) { - if (granted && permission_provider_ && - permission_provider_->HasDevicePermission(device_)) { + if (granted) { device_->Open( base::Bind(&DeviceImpl::OnOpen, weak_factory_.GetWeakPtr(), callback)); } else { - callback.Run(OpenDeviceError::ACCESS_DENIED); + callback.Run(mojom::UsbOpenDeviceError::ACCESS_DENIED); } } void DeviceImpl::Open(const OpenCallback& callback) { if (device_handle_) { - callback.Run(OpenDeviceError::ALREADY_OPEN); + callback.Run(mojom::UsbOpenDeviceError::ALREADY_OPEN); return; } @@ -212,13 +207,8 @@ void DeviceImpl::Open(const OpenCallback& callback) { return; } - if (permission_provider_ && - permission_provider_->HasDevicePermission(device_)) { - device_->Open( - base::Bind(&DeviceImpl::OnOpen, weak_factory_.GetWeakPtr(), callback)); - } else { - callback.Run(OpenDeviceError::ACCESS_DENIED); - } + device_->Open( + base::Bind(&DeviceImpl::OnOpen, weak_factory_.GetWeakPtr(), callback)); } void DeviceImpl::Close(const CloseCallback& callback) { @@ -233,12 +223,7 @@ void DeviceImpl::SetConfiguration(uint8_t value, return; } - if (permission_provider_ && - permission_provider_->HasConfigurationPermission(value, device_)) { - device_handle_->SetConfiguration(value, callback); - } else { - callback.Run(false); - } + device_handle_->SetConfiguration(value, callback); } void DeviceImpl::ClaimInterface(uint8_t interface_number, @@ -264,14 +249,7 @@ void DeviceImpl::ClaimInterface(uint8_t interface_number, return; } - if (permission_provider_ && - permission_provider_->HasFunctionPermission(interface_it->first_interface, - config->configuration_value, - device_)) { - device_handle_->ClaimInterface(interface_number, callback); - } else { - callback.Run(false); - } + device_handle_->ClaimInterface(interface_number, callback); } void DeviceImpl::ReleaseInterface(uint8_t interface_number, @@ -316,35 +294,33 @@ void DeviceImpl::ClearHalt(uint8_t endpoint, device_handle_->ClearHalt(endpoint, callback); } -void DeviceImpl::ControlTransferIn(ControlTransferParamsPtr params, +void DeviceImpl::ControlTransferIn(UsbControlTransferParamsPtr params, uint32_t length, uint32_t timeout, const ControlTransferInCallback& callback) { if (!device_handle_) { - callback.Run(TransferStatus::TRANSFER_ERROR, base::nullopt); + callback.Run(mojom::UsbTransferStatus::TRANSFER_ERROR, base::nullopt); return; } if (HasControlTransferPermission(params->recipient, params->index)) { scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(length); device_handle_->ControlTransfer( - USB_DIRECTION_INBOUND, - mojo::ConvertTo<UsbDeviceHandle::TransferRequestType>(params->type), - mojo::ConvertTo<UsbDeviceHandle::TransferRecipient>(params->recipient), + UsbTransferDirection::INBOUND, params->type, params->recipient, params->request, params->value, params->index, buffer, length, timeout, base::Bind(&OnTransferIn, callback)); } else { - callback.Run(TransferStatus::PERMISSION_DENIED, base::nullopt); + callback.Run(mojom::UsbTransferStatus::PERMISSION_DENIED, base::nullopt); } } void DeviceImpl::ControlTransferOut( - ControlTransferParamsPtr params, + UsbControlTransferParamsPtr params, const std::vector<uint8_t>& data, uint32_t timeout, const ControlTransferOutCallback& callback) { if (!device_handle_) { - callback.Run(TransferStatus::TRANSFER_ERROR); + callback.Run(mojom::UsbTransferStatus::TRANSFER_ERROR); return; } @@ -352,13 +328,11 @@ void DeviceImpl::ControlTransferOut( scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(data.size()); std::copy(data.begin(), data.end(), buffer->data()); device_handle_->ControlTransfer( - USB_DIRECTION_OUTBOUND, - mojo::ConvertTo<UsbDeviceHandle::TransferRequestType>(params->type), - mojo::ConvertTo<UsbDeviceHandle::TransferRecipient>(params->recipient), + UsbTransferDirection::OUTBOUND, params->type, params->recipient, params->request, params->value, params->index, buffer, data.size(), timeout, base::Bind(&OnTransferOut, callback)); } else { - callback.Run(TransferStatus::PERMISSION_DENIED); + callback.Run(mojom::UsbTransferStatus::PERMISSION_DENIED); } } @@ -367,14 +341,14 @@ void DeviceImpl::GenericTransferIn(uint8_t endpoint_number, uint32_t timeout, const GenericTransferInCallback& callback) { if (!device_handle_) { - callback.Run(TransferStatus::TRANSFER_ERROR, base::nullopt); + callback.Run(mojom::UsbTransferStatus::TRANSFER_ERROR, base::nullopt); return; } uint8_t endpoint_address = endpoint_number | 0x80; scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(length); - device_handle_->GenericTransfer(USB_DIRECTION_INBOUND, endpoint_address, - buffer, length, timeout, + device_handle_->GenericTransfer(UsbTransferDirection::INBOUND, + endpoint_address, buffer, length, timeout, base::Bind(&OnTransferIn, callback)); } @@ -384,16 +358,16 @@ void DeviceImpl::GenericTransferOut( uint32_t timeout, const GenericTransferOutCallback& callback) { if (!device_handle_) { - callback.Run(TransferStatus::TRANSFER_ERROR); + callback.Run(mojom::UsbTransferStatus::TRANSFER_ERROR); return; } uint8_t endpoint_address = endpoint_number; scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(data.size()); std::copy(data.begin(), data.end(), buffer->data()); - device_handle_->GenericTransfer(USB_DIRECTION_OUTBOUND, endpoint_address, - buffer, data.size(), timeout, - base::Bind(&OnTransferOut, callback)); + device_handle_->GenericTransfer( + UsbTransferDirection::OUTBOUND, endpoint_address, buffer, data.size(), + timeout, base::Bind(&OnTransferOut, callback)); } void DeviceImpl::IsochronousTransferIn( @@ -403,8 +377,8 @@ void DeviceImpl::IsochronousTransferIn( const IsochronousTransferInCallback& callback) { if (!device_handle_) { callback.Run(base::nullopt, - BuildIsochronousPacketArray(packet_lengths, - TransferStatus::TRANSFER_ERROR)); + BuildIsochronousPacketArray( + packet_lengths, mojom::UsbTransferStatus::TRANSFER_ERROR)); return; } @@ -421,8 +395,8 @@ void DeviceImpl::IsochronousTransferOut( uint32_t timeout, const IsochronousTransferOutCallback& callback) { if (!device_handle_) { - callback.Run(BuildIsochronousPacketArray(packet_lengths, - TransferStatus::TRANSFER_ERROR)); + callback.Run(BuildIsochronousPacketArray( + packet_lengths, mojom::UsbTransferStatus::TRANSFER_ERROR)); return; } @@ -434,7 +408,7 @@ void DeviceImpl::IsochronousTransferOut( base::Bind(&OnIsochronousTransferOut, callback)); } -void DeviceImpl::OnDeviceRemoved(scoped_refptr<UsbDevice> device) { +void DeviceImpl::OnDeviceRemoved(scoped_refptr<device::UsbDevice> device) { DCHECK_EQ(device_, device); binding_->Close(); } diff --git a/chromium/device/usb/mojo/device_impl.h b/chromium/device/usb/mojo/device_impl.h index 60a7756bb43..02983cae5fe 100644 --- a/chromium/device/usb/mojo/device_impl.h +++ b/chromium/device/usb/mojo/device_impl.h @@ -27,16 +27,16 @@ class PermissionProvider; // Implementation of the public Device interface. Instances of this class are // constructed by DeviceManagerImpl and are strongly bound to their MessagePipe // lifetime. -class DeviceImpl : public Device, public device::UsbDevice::Observer { +class DeviceImpl : public mojom::UsbDevice, public device::UsbDevice::Observer { public: - static void Create(scoped_refptr<UsbDevice> device, + static void Create(scoped_refptr<device::UsbDevice> device, base::WeakPtr<PermissionProvider> permission_provider, - DeviceRequest request); + mojom::UsbDeviceRequest request); ~DeviceImpl() override; private: - DeviceImpl(scoped_refptr<UsbDevice> device, + DeviceImpl(scoped_refptr<device::UsbDevice> device, base::WeakPtr<PermissionProvider> permission_provider); // Closes the device if it's open. This will always set |device_handle_| to @@ -44,8 +44,9 @@ class DeviceImpl : public Device, public device::UsbDevice::Observer { void CloseHandle(); // Checks interface permissions for control transfers. - bool HasControlTransferPermission(ControlTransferRecipient recipient, - uint16_t index); + bool HasControlTransferPermission( + mojom::UsbControlTransferRecipient recipient, + uint16_t index); // Handles completion of an open request. static void OnOpen(base::WeakPtr<DeviceImpl> device, @@ -68,11 +69,11 @@ class DeviceImpl : public Device, public device::UsbDevice::Observer { const SetInterfaceAlternateSettingCallback& callback) override; void Reset(const ResetCallback& callback) override; void ClearHalt(uint8_t endpoint, const ClearHaltCallback& callback) override; - void ControlTransferIn(ControlTransferParamsPtr params, + void ControlTransferIn(mojom::UsbControlTransferParamsPtr params, uint32_t length, uint32_t timeout, const ControlTransferInCallback& callback) override; - void ControlTransferOut(ControlTransferParamsPtr params, + void ControlTransferOut(mojom::UsbControlTransferParamsPtr params, const std::vector<uint8_t>& data, uint32_t timeout, const ControlTransferOutCallback& callback) override; @@ -99,7 +100,7 @@ class DeviceImpl : public Device, public device::UsbDevice::Observer { // device::UsbDevice::Observer implementation: void OnDeviceRemoved(scoped_refptr<device::UsbDevice> device) override; - const scoped_refptr<UsbDevice> device_; + const scoped_refptr<device::UsbDevice> device_; base::WeakPtr<PermissionProvider> permission_provider_; ScopedObserver<device::UsbDevice, device::UsbDevice::Observer> observer_; @@ -107,7 +108,7 @@ class DeviceImpl : public Device, public device::UsbDevice::Observer { // has been closed. scoped_refptr<UsbDeviceHandle> device_handle_; - mojo::StrongBindingPtr<Device> binding_; + mojo::StrongBindingPtr<mojom::UsbDevice> binding_; base::WeakPtrFactory<DeviceImpl> weak_factory_; DISALLOW_COPY_AND_ASSIGN(DeviceImpl); diff --git a/chromium/device/usb/mojo/device_impl_unittest.cc b/chromium/device/usb/mojo/device_impl_unittest.cc index 8fbf075d6b6..3d42e9d71c9 100644 --- a/chromium/device/usb/mojo/device_impl_unittest.cc +++ b/chromium/device/usb/mojo/device_impl_unittest.cc @@ -34,6 +34,12 @@ using ::testing::Invoke; using ::testing::_; namespace device { + +using mojom::UsbIsochronousPacketPtr; +using mojom::UsbControlTransferRecipient; +using mojom::UsbControlTransferType; +using mojom::UsbDevicePtr; + namespace usb { namespace { @@ -58,9 +64,9 @@ class ConfigBuilder { UsbConfigDescriptor config_; }; -void ExpectOpenAndThen(OpenDeviceError expected, +void ExpectOpenAndThen(mojom::UsbOpenDeviceError expected, const base::Closure& continuation, - OpenDeviceError error) { + mojom::UsbOpenDeviceError error) { EXPECT_EQ(expected, error); continuation.Run(); } @@ -73,10 +79,10 @@ void ExpectResultAndThen(bool expected_result, } void ExpectTransferInAndThen( - TransferStatus expected_status, + mojom::UsbTransferStatus expected_status, const std::vector<uint8_t>& expected_bytes, const base::Closure& continuation, - TransferStatus actual_status, + mojom::UsbTransferStatus actual_status, const base::Optional<std::vector<uint8_t>>& actual_bytes) { EXPECT_EQ(expected_status, actual_status); ASSERT_TRUE(actual_bytes); @@ -88,14 +94,15 @@ void ExpectTransferInAndThen( continuation.Run(); } -void ExpectPacketsOutAndThen(const std::vector<uint32_t>& expected_packets, - const base::Closure& continuation, - std::vector<IsochronousPacketPtr> actual_packets) { +void ExpectPacketsOutAndThen( + const std::vector<uint32_t>& expected_packets, + const base::Closure& continuation, + std::vector<UsbIsochronousPacketPtr> actual_packets) { ASSERT_EQ(expected_packets.size(), actual_packets.size()); for (size_t i = 0; i < expected_packets.size(); ++i) { EXPECT_EQ(expected_packets[i], actual_packets[i]->transferred_length) << "Packet lengths differ at index: " << i; - EXPECT_EQ(TransferStatus::COMPLETED, actual_packets[i]->status) + EXPECT_EQ(mojom::UsbTransferStatus::COMPLETED, actual_packets[i]->status) << "Packet at index " << i << " not completed."; } continuation.Run(); @@ -106,12 +113,12 @@ void ExpectPacketsInAndThen( const std::vector<uint32_t>& expected_packets, const base::Closure& continuation, const base::Optional<std::vector<uint8_t>>& actual_bytes, - std::vector<IsochronousPacketPtr> actual_packets) { + std::vector<UsbIsochronousPacketPtr> actual_packets) { ASSERT_EQ(expected_packets.size(), actual_packets.size()); for (size_t i = 0; i < expected_packets.size(); ++i) { EXPECT_EQ(expected_packets[i], actual_packets[i]->transferred_length) << "Packet lengths differ at index: " << i; - EXPECT_EQ(TransferStatus::COMPLETED, actual_packets[i]->status) + EXPECT_EQ(mojom::UsbTransferStatus::COMPLETED, actual_packets[i]->status) << "Packet at index " << i << " not completed."; } ASSERT_TRUE(actual_bytes); @@ -123,9 +130,9 @@ void ExpectPacketsInAndThen( continuation.Run(); } -void ExpectTransferStatusAndThen(TransferStatus expected_status, +void ExpectTransferStatusAndThen(mojom::UsbTransferStatus expected_status, const base::Closure& continuation, - TransferStatus actual_status) { + mojom::UsbTransferStatus actual_status) { EXPECT_EQ(expected_status, actual_status); continuation.Run(); } @@ -151,16 +158,16 @@ class USBDeviceImplTest : public testing::Test { // Creates a mock device and binds a Device proxy to a Device service impl // wrapping the mock device. - DevicePtr GetMockDeviceProxy(uint16_t vendor_id, - uint16_t product_id, - const std::string& manufacturer, - const std::string& product, - const std::string& serial) { + UsbDevicePtr GetMockDeviceProxy(uint16_t vendor_id, + uint16_t product_id, + const std::string& manufacturer, + const std::string& product, + const std::string& serial) { mock_device_ = new MockUsbDevice(vendor_id, product_id, manufacturer, product, serial); mock_handle_ = new MockUsbDeviceHandle(mock_device_.get()); - DevicePtr proxy; + UsbDevicePtr proxy; DeviceImpl::Create(mock_device_, permission_provider_.GetWeakPtr(), mojo::MakeRequest(&proxy)); @@ -194,7 +201,7 @@ class USBDeviceImplTest : public testing::Test { return proxy; } - DevicePtr GetMockDeviceProxy() { + UsbDevicePtr GetMockDeviceProxy() { return GetMockDeviceProxy(0x1234, 0x5678, "ACME", "Frobinator", "ABCDEF"); } @@ -300,7 +307,7 @@ class USBDeviceImplTest : public testing::Test { scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(length); std::copy(bytes.begin(), bytes.end(), buffer->data()); mock_inbound_data_.pop(); - callback.Run(USB_TRANSFER_COMPLETED, buffer, length); + callback.Run(UsbTransferStatus::COMPLETED, buffer, length); } void OutboundTransfer(scoped_refptr<net::IOBuffer> buffer, @@ -314,12 +321,12 @@ class USBDeviceImplTest : public testing::Test { << i; } mock_outbound_data_.pop(); - callback.Run(USB_TRANSFER_COMPLETED, buffer, length); + callback.Run(UsbTransferStatus::COMPLETED, buffer, length); } - void ControlTransfer(UsbEndpointDirection direction, - UsbDeviceHandle::TransferRequestType request_type, - UsbDeviceHandle::TransferRecipient recipient, + void ControlTransfer(UsbTransferDirection direction, + UsbControlTransferType request_type, + UsbControlTransferRecipient recipient, uint8_t request, uint16_t value, uint16_t index, @@ -327,19 +334,19 @@ class USBDeviceImplTest : public testing::Test { size_t length, unsigned int timeout, const UsbDeviceHandle::TransferCallback& callback) { - if (direction == USB_DIRECTION_INBOUND) + if (direction == UsbTransferDirection::INBOUND) InboundTransfer(callback); else OutboundTransfer(buffer, length, callback); } - void GenericTransfer(UsbEndpointDirection direction, + void GenericTransfer(UsbTransferDirection direction, uint8_t endpoint, scoped_refptr<net::IOBuffer> buffer, size_t length, unsigned int timeout, const UsbDeviceHandle::TransferCallback& callback) { - if (direction == USB_DIRECTION_INBOUND) + if (direction == UsbTransferDirection::INBOUND) InboundTransfer(callback); else OutboundTransfer(buffer, length, callback); @@ -425,7 +432,7 @@ class USBDeviceImplTest : public testing::Test { } // namespace TEST_F(USBDeviceImplTest, Disconnect) { - DevicePtr device = GetMockDeviceProxy(); + UsbDevicePtr device = GetMockDeviceProxy(); base::RunLoop loop; device.set_connection_error_handler(loop.QuitClosure()); @@ -434,31 +441,34 @@ TEST_F(USBDeviceImplTest, Disconnect) { } TEST_F(USBDeviceImplTest, Open) { - DevicePtr device = GetMockDeviceProxy(); + UsbDevicePtr device = GetMockDeviceProxy(); EXPECT_FALSE(is_device_open()); EXPECT_CALL(mock_device(), Open(_)); + EXPECT_CALL(permission_provider(), IncrementConnectionCount()); { base::RunLoop loop; - device->Open(base::Bind(&ExpectOpenAndThen, OpenDeviceError::OK, + device->Open(base::Bind(&ExpectOpenAndThen, mojom::UsbOpenDeviceError::OK, loop.QuitClosure())); loop.Run(); } { base::RunLoop loop; - device->Open(base::Bind(&ExpectOpenAndThen, OpenDeviceError::ALREADY_OPEN, + device->Open(base::Bind(&ExpectOpenAndThen, + mojom::UsbOpenDeviceError::ALREADY_OPEN, loop.QuitClosure())); loop.Run(); } EXPECT_CALL(mock_handle(), Close()); + EXPECT_CALL(permission_provider(), DecrementConnectionCount()); } TEST_F(USBDeviceImplTest, Close) { - DevicePtr device = GetMockDeviceProxy(); + UsbDevicePtr device = GetMockDeviceProxy(); EXPECT_FALSE(is_device_open()); @@ -466,7 +476,7 @@ TEST_F(USBDeviceImplTest, Close) { { base::RunLoop loop; - device->Open(base::Bind(&ExpectOpenAndThen, OpenDeviceError::OK, + device->Open(base::Bind(&ExpectOpenAndThen, mojom::UsbOpenDeviceError::OK, loop.QuitClosure())); loop.Run(); } @@ -483,19 +493,18 @@ TEST_F(USBDeviceImplTest, Close) { } TEST_F(USBDeviceImplTest, SetInvalidConfiguration) { - DevicePtr device = GetMockDeviceProxy(); + UsbDevicePtr device = GetMockDeviceProxy(); EXPECT_CALL(mock_device(), Open(_)); { base::RunLoop loop; - device->Open(base::Bind(&ExpectOpenAndThen, OpenDeviceError::OK, + device->Open(base::Bind(&ExpectOpenAndThen, mojom::UsbOpenDeviceError::OK, loop.QuitClosure())); loop.Run(); } EXPECT_CALL(mock_handle(), SetConfiguration(42, _)); - EXPECT_CALL(permission_provider(), HasConfigurationPermission(42, _)); { // SetConfiguration should fail because 42 is not a valid mock @@ -510,19 +519,18 @@ TEST_F(USBDeviceImplTest, SetInvalidConfiguration) { } TEST_F(USBDeviceImplTest, SetValidConfiguration) { - DevicePtr device = GetMockDeviceProxy(); + UsbDevicePtr device = GetMockDeviceProxy(); EXPECT_CALL(mock_device(), Open(_)); { base::RunLoop loop; - device->Open(base::Bind(&ExpectOpenAndThen, OpenDeviceError::OK, + device->Open(base::Bind(&ExpectOpenAndThen, mojom::UsbOpenDeviceError::OK, loop.QuitClosure())); loop.Run(); } EXPECT_CALL(mock_handle(), SetConfiguration(42, _)); - EXPECT_CALL(permission_provider(), HasConfigurationPermission(42, _)); AddMockConfig(ConfigBuilder(42)); @@ -540,13 +548,13 @@ TEST_F(USBDeviceImplTest, SetValidConfiguration) { // Verify that the result of Reset() reflects the underlying UsbDeviceHandle's // ResetDevice() result. TEST_F(USBDeviceImplTest, Reset) { - DevicePtr device = GetMockDeviceProxy(); + UsbDevicePtr device = GetMockDeviceProxy(); EXPECT_CALL(mock_device(), Open(_)); { base::RunLoop loop; - device->Open(base::Bind(&ExpectOpenAndThen, OpenDeviceError::OK, + device->Open(base::Bind(&ExpectOpenAndThen, mojom::UsbOpenDeviceError::OK, loop.QuitClosure())); loop.Run(); } @@ -575,13 +583,13 @@ TEST_F(USBDeviceImplTest, Reset) { } TEST_F(USBDeviceImplTest, ClaimAndReleaseInterface) { - DevicePtr device = GetMockDeviceProxy(); + UsbDevicePtr device = GetMockDeviceProxy(); EXPECT_CALL(mock_device(), Open(_)); { base::RunLoop loop; - device->Open(base::Bind(&ExpectOpenAndThen, OpenDeviceError::OK, + device->Open(base::Bind(&ExpectOpenAndThen, mojom::UsbOpenDeviceError::OK, loop.QuitClosure())); loop.Run(); } @@ -590,7 +598,6 @@ TEST_F(USBDeviceImplTest, ClaimAndReleaseInterface) { AddMockConfig(ConfigBuilder(1).AddInterface(1, 0, 1, 2, 3)); EXPECT_CALL(mock_handle(), SetConfiguration(1, _)); - EXPECT_CALL(permission_provider(), HasConfigurationPermission(1, _)); { base::RunLoop loop; @@ -608,7 +615,6 @@ TEST_F(USBDeviceImplTest, ClaimAndReleaseInterface) { } EXPECT_CALL(mock_handle(), ClaimInterface(1, _)); - EXPECT_CALL(permission_provider(), HasFunctionPermission(1, 1, _)); { base::RunLoop loop; @@ -641,13 +647,13 @@ TEST_F(USBDeviceImplTest, ClaimAndReleaseInterface) { } TEST_F(USBDeviceImplTest, SetInterfaceAlternateSetting) { - DevicePtr device = GetMockDeviceProxy(); + UsbDevicePtr device = GetMockDeviceProxy(); EXPECT_CALL(mock_device(), Open(_)); { base::RunLoop loop; - device->Open(base::Bind(&ExpectOpenAndThen, OpenDeviceError::OK, + device->Open(base::Bind(&ExpectOpenAndThen, mojom::UsbOpenDeviceError::OK, loop.QuitClosure())); loop.Run(); } @@ -679,13 +685,13 @@ TEST_F(USBDeviceImplTest, SetInterfaceAlternateSetting) { } TEST_F(USBDeviceImplTest, ControlTransfer) { - DevicePtr device = GetMockDeviceProxy(); + UsbDevicePtr device = GetMockDeviceProxy(); EXPECT_CALL(mock_device(), Open(_)); { base::RunLoop loop; - device->Open(base::Bind(&ExpectOpenAndThen, OpenDeviceError::OK, + device->Open(base::Bind(&ExpectOpenAndThen, mojom::UsbOpenDeviceError::OK, loop.QuitClosure())); loop.Run(); } @@ -693,7 +699,6 @@ TEST_F(USBDeviceImplTest, ControlTransfer) { AddMockConfig(ConfigBuilder(1).AddInterface(7, 0, 1, 2, 3)); EXPECT_CALL(mock_handle(), SetConfiguration(1, _)); - EXPECT_CALL(permission_provider(), HasConfigurationPermission(1, _)); { base::RunLoop loop; @@ -710,44 +715,47 @@ TEST_F(USBDeviceImplTest, ControlTransfer) { AddMockInboundData(fake_data); EXPECT_CALL(mock_handle(), - ControlTransfer(USB_DIRECTION_INBOUND, UsbDeviceHandle::STANDARD, - UsbDeviceHandle::DEVICE, 5, 6, 7, _, _, 0, _)); - EXPECT_CALL(permission_provider(), HasConfigurationPermission(1, _)); + ControlTransfer(UsbTransferDirection::INBOUND, + UsbControlTransferType::STANDARD, + UsbControlTransferRecipient::DEVICE, 5, 6, 7, _, + _, 0, _)); { - auto params = ControlTransferParams::New(); - params->type = ControlTransferType::STANDARD; - params->recipient = ControlTransferRecipient::DEVICE; + auto params = mojom::UsbControlTransferParams::New(); + params->type = UsbControlTransferType::STANDARD; + params->recipient = UsbControlTransferRecipient::DEVICE; params->request = 5; params->value = 6; params->index = 7; base::RunLoop loop; - device->ControlTransferIn( - std::move(params), static_cast<uint32_t>(fake_data.size()), 0, - base::Bind(&ExpectTransferInAndThen, TransferStatus::COMPLETED, - fake_data, loop.QuitClosure())); + device->ControlTransferIn(std::move(params), + static_cast<uint32_t>(fake_data.size()), 0, + base::Bind(&ExpectTransferInAndThen, + mojom::UsbTransferStatus::COMPLETED, + fake_data, loop.QuitClosure())); loop.Run(); } AddMockOutboundData(fake_data); EXPECT_CALL(mock_handle(), - ControlTransfer(USB_DIRECTION_OUTBOUND, UsbDeviceHandle::STANDARD, - UsbDeviceHandle::INTERFACE, 5, 6, 7, _, _, 0, _)); - EXPECT_CALL(permission_provider(), HasFunctionPermission(7, 1, _)); + ControlTransfer(UsbTransferDirection::OUTBOUND, + UsbControlTransferType::STANDARD, + UsbControlTransferRecipient::INTERFACE, 5, 6, 7, + _, _, 0, _)); { - auto params = ControlTransferParams::New(); - params->type = ControlTransferType::STANDARD; - params->recipient = ControlTransferRecipient::INTERFACE; + auto params = mojom::UsbControlTransferParams::New(); + params->type = UsbControlTransferType::STANDARD; + params->recipient = UsbControlTransferRecipient::INTERFACE; params->request = 5; params->value = 6; params->index = 7; base::RunLoop loop; device->ControlTransferOut( std::move(params), fake_data, 0, - base::Bind(&ExpectTransferStatusAndThen, TransferStatus::COMPLETED, - loop.QuitClosure())); + base::Bind(&ExpectTransferStatusAndThen, + mojom::UsbTransferStatus::COMPLETED, loop.QuitClosure())); loop.Run(); } @@ -755,13 +763,13 @@ TEST_F(USBDeviceImplTest, ControlTransfer) { } TEST_F(USBDeviceImplTest, GenericTransfer) { - DevicePtr device = GetMockDeviceProxy(); + UsbDevicePtr device = GetMockDeviceProxy(); EXPECT_CALL(mock_device(), Open(_)); { base::RunLoop loop; - device->Open(base::Bind(&ExpectOpenAndThen, OpenDeviceError::OK, + device->Open(base::Bind(&ExpectOpenAndThen, mojom::UsbOpenDeviceError::OK, loop.QuitClosure())); loop.Run(); } @@ -778,27 +786,30 @@ TEST_F(USBDeviceImplTest, GenericTransfer) { AddMockOutboundData(fake_outbound_data); AddMockInboundData(fake_inbound_data); - EXPECT_CALL(mock_handle(), GenericTransfer(USB_DIRECTION_OUTBOUND, 0x01, _, - fake_outbound_data.size(), 0, _)); + EXPECT_CALL(mock_handle(), + GenericTransfer(UsbTransferDirection::OUTBOUND, 0x01, _, + fake_outbound_data.size(), 0, _)); { base::RunLoop loop; device->GenericTransferOut( 1, fake_outbound_data, 0, - base::Bind(&ExpectTransferStatusAndThen, TransferStatus::COMPLETED, - loop.QuitClosure())); + base::Bind(&ExpectTransferStatusAndThen, + mojom::UsbTransferStatus::COMPLETED, loop.QuitClosure())); loop.Run(); } - EXPECT_CALL(mock_handle(), GenericTransfer(USB_DIRECTION_INBOUND, 0x81, _, - fake_inbound_data.size(), 0, _)); + EXPECT_CALL(mock_handle(), + GenericTransfer(UsbTransferDirection::INBOUND, 0x81, _, + fake_inbound_data.size(), 0, _)); { base::RunLoop loop; device->GenericTransferIn( 1, static_cast<uint32_t>(fake_inbound_data.size()), 0, - base::Bind(&ExpectTransferInAndThen, TransferStatus::COMPLETED, - fake_inbound_data, loop.QuitClosure())); + base::Bind(&ExpectTransferInAndThen, + mojom::UsbTransferStatus::COMPLETED, fake_inbound_data, + loop.QuitClosure())); loop.Run(); } @@ -806,13 +817,13 @@ TEST_F(USBDeviceImplTest, GenericTransfer) { } TEST_F(USBDeviceImplTest, IsochronousTransfer) { - DevicePtr device = GetMockDeviceProxy(); + UsbDevicePtr device = GetMockDeviceProxy(); EXPECT_CALL(mock_device(), Open(_)); { base::RunLoop loop; - device->Open(base::Bind(&ExpectOpenAndThen, OpenDeviceError::OK, + device->Open(base::Bind(&ExpectOpenAndThen, mojom::UsbOpenDeviceError::OK, loop.QuitClosure())); loop.Run(); } @@ -821,7 +832,7 @@ TEST_F(USBDeviceImplTest, IsochronousTransfer) { for (size_t i = 0; i < fake_packets.size(); ++i) { fake_packets[i].length = 8; fake_packets[i].transferred_length = 8; - fake_packets[i].status = USB_TRANSFER_COMPLETED; + fake_packets[i].status = UsbTransferStatus::COMPLETED; } std::vector<uint32_t> fake_packet_lengths(4, 8); diff --git a/chromium/device/usb/mojo/device_manager_impl.cc b/chromium/device/usb/mojo/device_manager_impl.cc index 53a0834bd99..31a08beb1b0 100644 --- a/chromium/device/usb/mojo/device_manager_impl.cc +++ b/chromium/device/usb/mojo/device_manager_impl.cc @@ -28,7 +28,7 @@ namespace usb { // static void DeviceManagerImpl::Create( base::WeakPtr<PermissionProvider> permission_provider, - DeviceManagerRequest request) { + mojom::UsbDeviceManagerRequest request) { DCHECK(DeviceClient::Get()); UsbService* service = DeviceClient::Get()->GetUsbService(); if (!service) @@ -56,7 +56,7 @@ DeviceManagerImpl::DeviceManagerImpl( DeviceManagerImpl::~DeviceManagerImpl() { } -void DeviceManagerImpl::GetDevices(EnumerationOptionsPtr options, +void DeviceManagerImpl::GetDevices(mojom::UsbEnumerationOptionsPtr options, const GetDevicesCallback& callback) { usb_service_->GetDevices(base::Bind(&DeviceManagerImpl::OnGetDevices, weak_factory_.GetWeakPtr(), @@ -64,7 +64,7 @@ void DeviceManagerImpl::GetDevices(EnumerationOptionsPtr options, } void DeviceManagerImpl::GetDevice(const std::string& guid, - DeviceRequest device_request) { + mojom::UsbDeviceRequest device_request) { scoped_refptr<UsbDevice> device = usb_service_->GetDevice(guid); if (!device) return; @@ -76,24 +76,24 @@ void DeviceManagerImpl::GetDevice(const std::string& guid, } } -void DeviceManagerImpl::SetClient(DeviceManagerClientPtr client) { +void DeviceManagerImpl::SetClient(mojom::UsbDeviceManagerClientPtr client) { client_ = std::move(client); } void DeviceManagerImpl::OnGetDevices( - EnumerationOptionsPtr options, + mojom::UsbEnumerationOptionsPtr options, const GetDevicesCallback& callback, const std::vector<scoped_refptr<UsbDevice>>& devices) { std::vector<UsbDeviceFilter> filters; if (options && options->filters) filters.swap(*options->filters); - std::vector<DeviceInfoPtr> device_infos; + std::vector<mojom::UsbDeviceInfoPtr> device_infos; for (const auto& device : devices) { if (UsbDeviceFilter::MatchesAny(*device, filters)) { if (permission_provider_ && permission_provider_->HasDevicePermission(device)) { - device_infos.push_back(DeviceInfo::From(*device)); + device_infos.push_back(mojom::UsbDeviceInfo::From(*device)); } } } @@ -104,13 +104,13 @@ void DeviceManagerImpl::OnGetDevices( void DeviceManagerImpl::OnDeviceAdded(scoped_refptr<UsbDevice> device) { if (client_ && permission_provider_ && permission_provider_->HasDevicePermission(device)) - client_->OnDeviceAdded(DeviceInfo::From(*device)); + client_->OnDeviceAdded(mojom::UsbDeviceInfo::From(*device)); } void DeviceManagerImpl::OnDeviceRemoved(scoped_refptr<UsbDevice> device) { if (client_ && permission_provider_ && permission_provider_->HasDevicePermission(device)) - client_->OnDeviceRemoved(DeviceInfo::From(*device)); + client_->OnDeviceRemoved(mojom::UsbDeviceInfo::From(*device)); } void DeviceManagerImpl::WillDestroyUsbService() { diff --git a/chromium/device/usb/mojo/device_manager_impl.h b/chromium/device/usb/mojo/device_manager_impl.h index 9bb75492114..52c73a93ebd 100644 --- a/chromium/device/usb/mojo/device_manager_impl.h +++ b/chromium/device/usb/mojo/device_manager_impl.h @@ -28,10 +28,11 @@ class PermissionProvider; // Implementation of the public DeviceManager interface. This interface can be // requested from the devices app located at "devices", if available. -class DeviceManagerImpl : public DeviceManager, public UsbService::Observer { +class DeviceManagerImpl : public mojom::UsbDeviceManager, + public UsbService::Observer { public: static void Create(base::WeakPtr<PermissionProvider> permission_provider, - DeviceManagerRequest request); + mojom::UsbDeviceManagerRequest request); ~DeviceManagerImpl() override; @@ -40,14 +41,14 @@ class DeviceManagerImpl : public DeviceManager, public UsbService::Observer { UsbService* usb_service); // DeviceManager implementation: - void GetDevices(EnumerationOptionsPtr options, + void GetDevices(mojom::UsbEnumerationOptionsPtr options, const GetDevicesCallback& callback) override; void GetDevice(const std::string& guid, - DeviceRequest device_request) override; - void SetClient(DeviceManagerClientPtr client) override; + mojom::UsbDeviceRequest device_request) override; + void SetClient(mojom::UsbDeviceManagerClientPtr client) override; // Callbacks to handle the async responses from the underlying UsbService. - void OnGetDevices(EnumerationOptionsPtr options, + void OnGetDevices(mojom::UsbEnumerationOptionsPtr options, const GetDevicesCallback& callback, const std::vector<scoped_refptr<UsbDevice>>& devices); @@ -58,12 +59,12 @@ class DeviceManagerImpl : public DeviceManager, public UsbService::Observer { void MaybeRunDeviceChangesCallback(); - mojo::StrongBindingPtr<DeviceManager> binding_; + mojo::StrongBindingPtr<mojom::UsbDeviceManager> binding_; base::WeakPtr<PermissionProvider> permission_provider_; UsbService* usb_service_; ScopedObserver<UsbService, UsbService::Observer> observer_; - DeviceManagerClientPtr client_; + mojom::UsbDeviceManagerClientPtr client_; base::WeakPtrFactory<DeviceManagerImpl> weak_factory_; diff --git a/chromium/device/usb/mojo/device_manager_impl_unittest.cc b/chromium/device/usb/mojo/device_manager_impl_unittest.cc index f3a1c9dcbf9..1a234cdaa85 100644 --- a/chromium/device/usb/mojo/device_manager_impl_unittest.cc +++ b/chromium/device/usb/mojo/device_manager_impl_unittest.cc @@ -30,6 +30,13 @@ using ::testing::Invoke; using ::testing::_; namespace device { + +using mojom::UsbDevicePtr; +using mojom::UsbDeviceInfoPtr; +using mojom::UsbDeviceManagerClientPtr; +using mojom::UsbDeviceManagerPtr; +using mojom::UsbEnumerationOptionsPtr; + namespace usb { namespace { @@ -47,8 +54,8 @@ class USBDeviceManagerImplTest : public testing::Test { ~USBDeviceManagerImplTest() override {} protected: - DeviceManagerPtr ConnectToDeviceManager() { - DeviceManagerPtr device_manager; + UsbDeviceManagerPtr ConnectToDeviceManager() { + UsbDeviceManagerPtr device_manager; DeviceManagerImpl::Create(permission_provider_.GetWeakPtr(), mojo::MakeRequest(&device_manager)); return device_manager; @@ -61,32 +68,32 @@ class USBDeviceManagerImplTest : public testing::Test { std::unique_ptr<base::MessageLoop> message_loop_; }; -class MockDeviceManagerClient : public DeviceManagerClient { +class MockDeviceManagerClient : public mojom::UsbDeviceManagerClient { public: MockDeviceManagerClient() : binding_(this) {} ~MockDeviceManagerClient() {} - DeviceManagerClientPtr CreateInterfacePtrAndBind() { + UsbDeviceManagerClientPtr CreateInterfacePtrAndBind() { return binding_.CreateInterfacePtrAndBind(); } - MOCK_METHOD1(DoOnDeviceAdded, void(DeviceInfo*)); - void OnDeviceAdded(DeviceInfoPtr device_info) { + MOCK_METHOD1(DoOnDeviceAdded, void(mojom::UsbDeviceInfo*)); + void OnDeviceAdded(UsbDeviceInfoPtr device_info) { DoOnDeviceAdded(device_info.get()); } - MOCK_METHOD1(DoOnDeviceRemoved, void(DeviceInfo*)); - void OnDeviceRemoved(DeviceInfoPtr device_info) { + MOCK_METHOD1(DoOnDeviceRemoved, void(mojom::UsbDeviceInfo*)); + void OnDeviceRemoved(UsbDeviceInfoPtr device_info) { DoOnDeviceRemoved(device_info.get()); } private: - mojo::Binding<DeviceManagerClient> binding_; + mojo::Binding<mojom::UsbDeviceManagerClient> binding_; }; void ExpectDevicesAndThen(const std::set<std::string>& expected_guids, const base::Closure& continuation, - std::vector<DeviceInfoPtr> results) { + std::vector<UsbDeviceInfoPtr> results) { EXPECT_EQ(expected_guids.size(), results.size()); std::set<std::string> actual_guids; for (size_t i = 0; i < results.size(); ++i) @@ -111,9 +118,9 @@ TEST_F(USBDeviceManagerImplTest, GetDevices) { device_client_.usb_service()->AddDevice(device1); device_client_.usb_service()->AddDevice(device2); - DeviceManagerPtr device_manager = ConnectToDeviceManager(); + UsbDeviceManagerPtr device_manager = ConnectToDeviceManager(); - EnumerationOptionsPtr options = EnumerationOptions::New(); + UsbEnumerationOptionsPtr options = mojom::UsbEnumerationOptions::New(); UsbDeviceFilter filter; filter.vendor_id = 0x1234; options->filters.emplace(); @@ -138,11 +145,11 @@ TEST_F(USBDeviceManagerImplTest, GetDevice) { device_client_.usb_service()->AddDevice(mock_device); - DeviceManagerPtr device_manager = ConnectToDeviceManager(); + UsbDeviceManagerPtr device_manager = ConnectToDeviceManager(); { base::RunLoop loop; - DevicePtr device; + UsbDevicePtr device; device_manager->GetDevice(mock_device->guid(), mojo::MakeRequest(&device)); // Close is a no-op if the device hasn't been opened but ensures that the // pipe was successfully connected. @@ -150,7 +157,7 @@ TEST_F(USBDeviceManagerImplTest, GetDevice) { loop.Run(); } - DevicePtr bad_device; + UsbDevicePtr bad_device; device_manager->GetDevice("not a real guid", mojo::MakeRequest(&bad_device)); { @@ -173,7 +180,7 @@ TEST_F(USBDeviceManagerImplTest, Client) { device_client_.usb_service()->AddDevice(device0); - DeviceManagerPtr device_manager = ConnectToDeviceManager(); + UsbDeviceManagerPtr device_manager = ConnectToDeviceManager(); MockDeviceManagerClient mock_client; device_manager->SetClient(mock_client.CreateInterfacePtrAndBind()); diff --git a/chromium/device/usb/mojo/mock_permission_provider.cc b/chromium/device/usb/mojo/mock_permission_provider.cc index e45b0f6db53..3af59f6d64d 100644 --- a/chromium/device/usb/mojo/mock_permission_provider.cc +++ b/chromium/device/usb/mojo/mock_permission_provider.cc @@ -17,8 +17,6 @@ namespace usb { MockPermissionProvider::MockPermissionProvider() : weak_factory_(this) { ON_CALL(*this, HasDevicePermission(_)).WillByDefault(Return(true)); - ON_CALL(*this, HasConfigurationPermission(_, _)).WillByDefault(Return(true)); - ON_CALL(*this, HasFunctionPermission(_, _, _)).WillByDefault(Return(true)); } MockPermissionProvider::~MockPermissionProvider() {} diff --git a/chromium/device/usb/mojo/mock_permission_provider.h b/chromium/device/usb/mojo/mock_permission_provider.h index 26521e25006..c558323a271 100644 --- a/chromium/device/usb/mojo/mock_permission_provider.h +++ b/chromium/device/usb/mojo/mock_permission_provider.h @@ -23,13 +23,6 @@ class MockPermissionProvider : public PermissionProvider { base::WeakPtr<PermissionProvider> GetWeakPtr(); MOCK_CONST_METHOD1(HasDevicePermission, bool(scoped_refptr<const UsbDevice> device)); - MOCK_CONST_METHOD2(HasConfigurationPermission, - bool(uint8_t requested_configuration, - scoped_refptr<const UsbDevice> device)); - MOCK_CONST_METHOD3(HasFunctionPermission, - bool(uint8_t requested_function, - uint8_t configuration_value, - scoped_refptr<const UsbDevice> device)); MOCK_METHOD0(IncrementConnectionCount, void()); MOCK_METHOD0(DecrementConnectionCount, void()); diff --git a/chromium/device/usb/mojo/permission_provider.h b/chromium/device/usb/mojo/permission_provider.h index 008fdc36030..5bb6a716670 100644 --- a/chromium/device/usb/mojo/permission_provider.h +++ b/chromium/device/usb/mojo/permission_provider.h @@ -5,8 +5,6 @@ #ifndef DEVICE_USB_MOJO_PERMISSION_PROVIDER_H_ #define DEVICE_USB_MOJO_PERMISSION_PROVIDER_H_ -#include <stdint.h> - #include "base/memory/ref_counted.h" namespace device { @@ -24,13 +22,6 @@ class PermissionProvider { virtual bool HasDevicePermission( scoped_refptr<const UsbDevice> device) const = 0; - virtual bool HasConfigurationPermission( - uint8_t requested_configuration, - scoped_refptr<const UsbDevice> device) const = 0; - virtual bool HasFunctionPermission( - uint8_t requested_function, - uint8_t configuration_value, - scoped_refptr<const UsbDevice> device) const = 0; virtual void IncrementConnectionCount() = 0; virtual void DecrementConnectionCount() = 0; }; diff --git a/chromium/device/usb/mojo/type_converters.cc b/chromium/device/usb/mojo/type_converters.cc index 09b8bd94f56..fbe17d88600 100644 --- a/chromium/device/usb/mojo/type_converters.cc +++ b/chromium/device/usb/mojo/type_converters.cc @@ -17,122 +17,24 @@ namespace mojo { // static -device::usb::TransferDirection -TypeConverter<device::usb::TransferDirection, device::UsbEndpointDirection>:: - Convert(const device::UsbEndpointDirection& direction) { - if (direction == device::USB_DIRECTION_INBOUND) - return device::usb::TransferDirection::INBOUND; - DCHECK(direction == device::USB_DIRECTION_OUTBOUND); - return device::usb::TransferDirection::OUTBOUND; -} - -// static -device::usb::TransferStatus -TypeConverter<device::usb::TransferStatus, device::UsbTransferStatus>::Convert( - const device::UsbTransferStatus& status) { - switch (status) { - case device::USB_TRANSFER_COMPLETED: - return device::usb::TransferStatus::COMPLETED; - case device::USB_TRANSFER_ERROR: - return device::usb::TransferStatus::TRANSFER_ERROR; - case device::USB_TRANSFER_TIMEOUT: - return device::usb::TransferStatus::TIMEOUT; - case device::USB_TRANSFER_CANCELLED: - return device::usb::TransferStatus::CANCELLED; - case device::USB_TRANSFER_STALLED: - return device::usb::TransferStatus::STALLED; - case device::USB_TRANSFER_DISCONNECT: - return device::usb::TransferStatus::DISCONNECT; - case device::USB_TRANSFER_OVERFLOW: - return device::usb::TransferStatus::BABBLE; - case device::USB_TRANSFER_LENGTH_SHORT: - return device::usb::TransferStatus::SHORT_PACKET; - default: - NOTREACHED(); - return device::usb::TransferStatus::TRANSFER_ERROR; - } -} - -// static -device::UsbDeviceHandle::TransferRequestType -TypeConverter<device::UsbDeviceHandle::TransferRequestType, - device::usb::ControlTransferType>:: - Convert(const device::usb::ControlTransferType& type) { - switch (type) { - case device::usb::ControlTransferType::STANDARD: - return device::UsbDeviceHandle::STANDARD; - case device::usb::ControlTransferType::CLASS: - return device::UsbDeviceHandle::CLASS; - case device::usb::ControlTransferType::VENDOR: - return device::UsbDeviceHandle::VENDOR; - case device::usb::ControlTransferType::RESERVED: - return device::UsbDeviceHandle::RESERVED; - default: - NOTREACHED(); - return device::UsbDeviceHandle::RESERVED; - } -} - -// static -device::UsbDeviceHandle::TransferRecipient -TypeConverter<device::UsbDeviceHandle::TransferRecipient, - device::usb::ControlTransferRecipient>:: - Convert(const device::usb::ControlTransferRecipient& recipient) { - switch (recipient) { - case device::usb::ControlTransferRecipient::DEVICE: - return device::UsbDeviceHandle::DEVICE; - case device::usb::ControlTransferRecipient::INTERFACE: - return device::UsbDeviceHandle::INTERFACE; - case device::usb::ControlTransferRecipient::ENDPOINT: - return device::UsbDeviceHandle::ENDPOINT; - case device::usb::ControlTransferRecipient::OTHER: - return device::UsbDeviceHandle::OTHER; - default: - NOTREACHED(); - return device::UsbDeviceHandle::OTHER; - } -} - -// static -device::usb::EndpointType -TypeConverter<device::usb::EndpointType, device::UsbTransferType>::Convert( - const device::UsbTransferType& type) { - switch (type) { - case device::USB_TRANSFER_ISOCHRONOUS: - return device::usb::EndpointType::ISOCHRONOUS; - case device::USB_TRANSFER_BULK: - return device::usb::EndpointType::BULK; - case device::USB_TRANSFER_INTERRUPT: - return device::usb::EndpointType::INTERRUPT; - // Note that we do not expose control transfer in the public interface - // because control endpoints are implied rather than explicitly enumerated - // there. - default: - NOTREACHED(); - return device::usb::EndpointType::BULK; - } -} - -// static -device::usb::EndpointInfoPtr -TypeConverter<device::usb::EndpointInfoPtr, device::UsbEndpointDescriptor>:: - Convert(const device::UsbEndpointDescriptor& endpoint) { - device::usb::EndpointInfoPtr info = device::usb::EndpointInfo::New(); +device::mojom::UsbEndpointInfoPtr TypeConverter< + device::mojom::UsbEndpointInfoPtr, + device::UsbEndpointDescriptor>::Convert(const device::UsbEndpointDescriptor& + endpoint) { + auto info = device::mojom::UsbEndpointInfo::New(); info->endpoint_number = endpoint.address & 0xf; - info->direction = - ConvertTo<device::usb::TransferDirection>(endpoint.direction); - info->type = ConvertTo<device::usb::EndpointType>(endpoint.transfer_type); + info->direction = endpoint.direction; + info->type = endpoint.transfer_type; info->packet_size = static_cast<uint32_t>(endpoint.maximum_packet_size); return info; } // static -device::usb::AlternateInterfaceInfoPtr -TypeConverter<device::usb::AlternateInterfaceInfoPtr, +device::mojom::UsbAlternateInterfaceInfoPtr +TypeConverter<device::mojom::UsbAlternateInterfaceInfoPtr, device::UsbInterfaceDescriptor>:: Convert(const device::UsbInterfaceDescriptor& interface) { - device::usb::AlternateInterfaceInfoPtr info = - device::usb::AlternateInterfaceInfo::New(); + auto info = device::mojom::UsbAlternateInterfaceInfo::New(); info->alternate_setting = interface.alternate_setting; info->class_code = interface.interface_class; info->subclass_code = interface.interface_subclass; @@ -141,30 +43,31 @@ TypeConverter<device::usb::AlternateInterfaceInfoPtr, // Filter out control endpoints for the public interface. info->endpoints.reserve(interface.endpoints.size()); for (const auto& endpoint : interface.endpoints) { - if (endpoint.transfer_type != device::USB_TRANSFER_CONTROL) - info->endpoints.push_back(device::usb::EndpointInfo::From(endpoint)); + if (endpoint.transfer_type != device::UsbTransferType::CONTROL) + info->endpoints.push_back(device::mojom::UsbEndpointInfo::From(endpoint)); } return info; } // static -std::vector<device::usb::InterfaceInfoPtr> -TypeConverter<std::vector<device::usb::InterfaceInfoPtr>, +std::vector<device::mojom::UsbInterfaceInfoPtr> +TypeConverter<std::vector<device::mojom::UsbInterfaceInfoPtr>, std::vector<device::UsbInterfaceDescriptor>>:: Convert(const std::vector<device::UsbInterfaceDescriptor>& interfaces) { - std::vector<device::usb::InterfaceInfoPtr> infos; + std::vector<device::mojom::UsbInterfaceInfoPtr> infos; // Aggregate each alternate setting into an InterfaceInfo corresponding to its // interface number. - std::map<uint8_t, device::usb::InterfaceInfo*> interface_map; + std::map<uint8_t, device::mojom::UsbInterfaceInfo*> interface_map; for (size_t i = 0; i < interfaces.size(); ++i) { - auto alternate = device::usb::AlternateInterfaceInfo::From(interfaces[i]); + auto alternate = + device::mojom::UsbAlternateInterfaceInfo::From(interfaces[i]); auto iter = interface_map.find(interfaces[i].interface_number); if (iter == interface_map.end()) { // This is the first time we're seeing an alternate with this interface // number, so add a new InterfaceInfo to the array and map the number. - auto info = device::usb::InterfaceInfo::New(); + auto info = device::mojom::UsbInterfaceInfo::New(); info->interface_number = interfaces[i].interface_number; iter = interface_map .insert( @@ -179,23 +82,23 @@ TypeConverter<std::vector<device::usb::InterfaceInfoPtr>, } // static -device::usb::ConfigurationInfoPtr -TypeConverter<device::usb::ConfigurationInfoPtr, device::UsbConfigDescriptor>:: - Convert(const device::UsbConfigDescriptor& config) { - device::usb::ConfigurationInfoPtr info = - device::usb::ConfigurationInfo::New(); +device::mojom::UsbConfigurationInfoPtr TypeConverter< + device::mojom::UsbConfigurationInfoPtr, + device::UsbConfigDescriptor>::Convert(const device::UsbConfigDescriptor& + config) { + auto info = device::mojom::UsbConfigurationInfo::New(); info->configuration_value = config.configuration_value; info->interfaces = - mojo::ConvertTo<std::vector<device::usb::InterfaceInfoPtr>>( + mojo::ConvertTo<std::vector<device::mojom::UsbInterfaceInfoPtr>>( config.interfaces); return info; } // static -device::usb::DeviceInfoPtr -TypeConverter<device::usb::DeviceInfoPtr, device::UsbDevice>::Convert( +device::mojom::UsbDeviceInfoPtr +TypeConverter<device::mojom::UsbDeviceInfoPtr, device::UsbDevice>::Convert( const device::UsbDevice& device) { - device::usb::DeviceInfoPtr info = device::usb::DeviceInfo::New(); + auto info = device::mojom::UsbDeviceInfo::New(); info->guid = device.guid(); info->usb_version_major = device.usb_version() >> 8; info->usb_version_minor = device.usb_version() >> 4 & 0xf; @@ -214,21 +117,21 @@ TypeConverter<device::usb::DeviceInfoPtr, device::UsbDevice>::Convert( const device::UsbConfigDescriptor* config = device.active_configuration(); info->active_configuration = config ? config->configuration_value : 0; info->configurations = - mojo::ConvertTo<std::vector<device::usb::ConfigurationInfoPtr>>( + mojo::ConvertTo<std::vector<device::mojom::UsbConfigurationInfoPtr>>( device.configurations()); return info; } // static -device::usb::IsochronousPacketPtr -TypeConverter<device::usb::IsochronousPacketPtr, +device::mojom::UsbIsochronousPacketPtr +TypeConverter<device::mojom::UsbIsochronousPacketPtr, device::UsbDeviceHandle::IsochronousPacket>:: Convert(const device::UsbDeviceHandle::IsochronousPacket& packet) { - device::usb::IsochronousPacketPtr info = - device::usb::IsochronousPacket::New(); + auto info = device::mojom::UsbIsochronousPacket::New(); info->length = packet.length; info->transferred_length = packet.transferred_length; - info->status = mojo::ConvertTo<device::usb::TransferStatus>(packet.status); + info->status = + mojo::ConvertTo<device::mojom::UsbTransferStatus>(packet.status); return info; } diff --git a/chromium/device/usb/mojo/type_converters.h b/chromium/device/usb/mojo/type_converters.h index cd4a405a3c5..cb9514c1301 100644 --- a/chromium/device/usb/mojo/type_converters.h +++ b/chromium/device/usb/mojo/type_converters.h @@ -25,48 +25,16 @@ class UsbDevice; namespace mojo { template <> -struct TypeConverter<device::usb::TransferDirection, - device::UsbEndpointDirection> { - static device::usb::TransferDirection Convert( - const device::UsbEndpointDirection& direction); -}; - -template <> -struct TypeConverter<device::usb::TransferStatus, device::UsbTransferStatus> { - static device::usb::TransferStatus Convert( - const device::UsbTransferStatus& status); -}; - -template <> -struct TypeConverter<device::UsbDeviceHandle::TransferRequestType, - device::usb::ControlTransferType> { - static device::UsbDeviceHandle::TransferRequestType Convert( - const device::usb::ControlTransferType& type); -}; - -template <> -struct TypeConverter<device::UsbDeviceHandle::TransferRecipient, - device::usb::ControlTransferRecipient> { - static device::UsbDeviceHandle::TransferRecipient Convert( - const device::usb::ControlTransferRecipient& recipient); -}; - -template <> -struct TypeConverter<device::usb::EndpointType, device::UsbTransferType> { - static device::usb::EndpointType Convert(const device::UsbTransferType& type); -}; - -template <> -struct TypeConverter<device::usb::EndpointInfoPtr, +struct TypeConverter<device::mojom::UsbEndpointInfoPtr, device::UsbEndpointDescriptor> { - static device::usb::EndpointInfoPtr Convert( + static device::mojom::UsbEndpointInfoPtr Convert( const device::UsbEndpointDescriptor& endpoint); }; template <> -struct TypeConverter<device::usb::AlternateInterfaceInfoPtr, +struct TypeConverter<device::mojom::UsbAlternateInterfaceInfoPtr, device::UsbInterfaceDescriptor> { - static device::usb::AlternateInterfaceInfoPtr Convert( + static device::mojom::UsbAlternateInterfaceInfoPtr Convert( const device::UsbInterfaceDescriptor& iface); }; @@ -75,28 +43,29 @@ struct TypeConverter<device::usb::AlternateInterfaceInfoPtr, // settings, whereas InterfaceInfos contain their own sets of alternates with // a different structure type. template <> -struct TypeConverter<std::vector<device::usb::InterfaceInfoPtr>, +struct TypeConverter<std::vector<device::mojom::UsbInterfaceInfoPtr>, std::vector<device::UsbInterfaceDescriptor>> { - static std::vector<device::usb::InterfaceInfoPtr> Convert( + static std::vector<device::mojom::UsbInterfaceInfoPtr> Convert( const std::vector<device::UsbInterfaceDescriptor>& interfaces); }; template <> -struct TypeConverter<device::usb::ConfigurationInfoPtr, +struct TypeConverter<device::mojom::UsbConfigurationInfoPtr, device::UsbConfigDescriptor> { - static device::usb::ConfigurationInfoPtr Convert( + static device::mojom::UsbConfigurationInfoPtr Convert( const device::UsbConfigDescriptor& config); }; template <> -struct TypeConverter<device::usb::DeviceInfoPtr, device::UsbDevice> { - static device::usb::DeviceInfoPtr Convert(const device::UsbDevice& device); +struct TypeConverter<device::mojom::UsbDeviceInfoPtr, device::UsbDevice> { + static device::mojom::UsbDeviceInfoPtr Convert( + const device::UsbDevice& device); }; template <> -struct TypeConverter<device::usb::IsochronousPacketPtr, +struct TypeConverter<device::mojom::UsbIsochronousPacketPtr, device::UsbDeviceHandle::IsochronousPacket> { - static device::usb::IsochronousPacketPtr Convert( + static device::mojom::UsbIsochronousPacketPtr Convert( const device::UsbDeviceHandle::IsochronousPacket& packet); }; diff --git a/chromium/device/usb/public/interfaces/BUILD.gn b/chromium/device/usb/public/interfaces/BUILD.gn index 7f12a8402a8..2ff08c002f4 100644 --- a/chromium/device/usb/public/interfaces/BUILD.gn +++ b/chromium/device/usb/public/interfaces/BUILD.gn @@ -10,4 +10,7 @@ mojom("interfaces") { "device.mojom", "device_manager.mojom", ] + + # TODO(crbug.com/714018): Convert the implementation to use OnceCallback. + use_once_callback = false } diff --git a/chromium/device/usb/public/interfaces/OWNERS b/chromium/device/usb/public/interfaces/OWNERS index ac44cd00686..fda0d857f5e 100644 --- a/chromium/device/usb/public/interfaces/OWNERS +++ b/chromium/device/usb/public/interfaces/OWNERS @@ -3,3 +3,6 @@ per-file *.mojom=file://ipc/SECURITY_OWNERS per-file *_struct_traits*.*=set noparent per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS + +per-file *.typemap=set noparent +per-file *.typemap=file://ipc/SECURITY_OWNERS diff --git a/chromium/device/usb/public/interfaces/chooser_service.mojom b/chromium/device/usb/public/interfaces/chooser_service.mojom index 29f130b7489..d7fd2fe8698 100644 --- a/chromium/device/usb/public/interfaces/chooser_service.mojom +++ b/chromium/device/usb/public/interfaces/chooser_service.mojom @@ -2,18 +2,18 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -module device.usb; +module device.mojom; import "device.mojom"; import "device_manager.mojom"; -interface ChooserService { +interface UsbChooserService { // Get permission from user to use the device. // // |device_filters| filters the available devices and the filtered // devices will be listed for user to grant permission. // // |result| is the device that user grants permission to use. - GetPermission(array<device.usb.DeviceFilter> device_filters) - => (device.usb.DeviceInfo? result); + GetPermission(array<device.mojom.UsbDeviceFilter> device_filters) + => (device.mojom.UsbDeviceInfo? result); }; diff --git a/chromium/device/usb/public/interfaces/device.mojom b/chromium/device/usb/public/interfaces/device.mojom index 8da2922bf45..d1c139aad8f 100644 --- a/chromium/device/usb/public/interfaces/device.mojom +++ b/chromium/device/usb/public/interfaces/device.mojom @@ -2,9 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -module device.usb; +module device.mojom; -enum OpenDeviceError { +enum UsbOpenDeviceError { // Opening the device succeeded. OK, @@ -15,59 +15,62 @@ enum OpenDeviceError { ALREADY_OPEN, }; -enum TransferDirection { - INBOUND, +// Corresponds to the USBDirection WebIDL type. +enum UsbTransferDirection { + INBOUND = 0, OUTBOUND, }; -enum ControlTransferType { +enum UsbControlTransferType { STANDARD, CLASS, VENDOR, RESERVED }; -enum ControlTransferRecipient { +// Corresponds to the USBRecipient WebIDL type. +enum UsbControlTransferRecipient { DEVICE, INTERFACE, ENDPOINT, OTHER }; -enum EndpointType { +enum UsbTransferType { + CONTROL = 0, + ISOCHRONOUS, BULK, INTERRUPT, - ISOCHRONOUS, }; -struct EndpointInfo { +struct UsbEndpointInfo { uint8 endpoint_number; - TransferDirection direction; - EndpointType type; + UsbTransferDirection direction; + UsbTransferType type; uint32 packet_size; }; -struct AlternateInterfaceInfo { +struct UsbAlternateInterfaceInfo { uint8 alternate_setting; uint8 class_code; uint8 subclass_code; uint8 protocol_code; string? interface_name; - array<EndpointInfo> endpoints; + array<UsbEndpointInfo> endpoints; }; -struct InterfaceInfo { +struct UsbInterfaceInfo { uint8 interface_number; - array<AlternateInterfaceInfo> alternates; + array<UsbAlternateInterfaceInfo> alternates; }; -struct ConfigurationInfo { +struct UsbConfigurationInfo { uint8 configuration_value; string? configuration_name; - array<InterfaceInfo> interfaces; + array<UsbInterfaceInfo> interfaces; }; -struct DeviceInfo { +struct UsbDeviceInfo { string guid; uint8 usb_version_major; uint8 usb_version_minor; @@ -84,27 +87,26 @@ struct DeviceInfo { string? product_name; string? serial_number; uint8 active_configuration; - array<ConfigurationInfo> configurations; + array<UsbConfigurationInfo> configurations; }; -struct ControlTransferParams { - ControlTransferType type; - ControlTransferRecipient recipient; +struct UsbControlTransferParams { + UsbControlTransferType type; + UsbControlTransferRecipient recipient; uint8 request; uint16 value; uint16 index; }; -enum TransferStatus { +// This enum is exposed through the chrome.usb extension API so existing values +// should not be changed or reordered. +enum UsbTransferStatus { // The transfer completed successfully. - COMPLETED, + COMPLETED = 0, // The transfer failed due to a non-specific error. TRANSFER_ERROR, - // The transfer was not allowed. - PERMISSION_DENIED, - // The transfer timed out. TIMEOUT, @@ -124,17 +126,20 @@ enum TransferStatus { // The transfer succeeded, but the device sent less data than was requested. // This applies only to inbound transfers. SHORT_PACKET, + + // The transfer was not allowed. + PERMISSION_DENIED, }; -struct IsochronousPacket { +struct UsbIsochronousPacket { uint32 length; uint32 transferred_length; - TransferStatus status; + UsbTransferStatus status; }; -interface Device { +interface UsbDevice { // Opens the device. Methods below require the device be opened first. - Open() => (OpenDeviceError error); + Open() => (UsbOpenDeviceError error); // Closes the device. Close() => (); @@ -170,8 +175,10 @@ interface Device { // |timeout| specifies the request timeout in milliseconds. A timeout of 0 // indicates no timeout: the request will remain pending indefinitely until // completed or otherwise terminated. - ControlTransferIn(ControlTransferParams params, uint32 length, uint32 timeout) - => (TransferStatus status, array<uint8>? data); + ControlTransferIn(UsbControlTransferParams params, + uint32 length, + uint32 timeout) + => (UsbTransferStatus status, array<uint8>? data); // Initiates an inbound control transfer request. |params| determine the // details of the request. Transfers to recipients other than DEVICE require a @@ -182,10 +189,10 @@ interface Device { // |timeout| specifies the request timeout in milliseconds. A timeout of 0 // indicates no timeout: the request will remain pending indefinitely until // completed or otherwise terminated. - ControlTransferOut(ControlTransferParams params, + ControlTransferOut(UsbControlTransferParams params, array<uint8> data, uint32 timeout) - => (TransferStatus status); + => (UsbTransferStatus status); // Initiates an inbound generic transfer request on a specific endpoint. The // interface to which |endpoint_number| belongs must be claimed, and the @@ -201,7 +208,7 @@ interface Device { // indicates no timeout: the request will remain pending indefinitely until // completed or otherwise terminated. GenericTransferIn(uint8 endpoint_number, uint32 length, uint32 timeout) - => (TransferStatus status, array<uint8>? data); + => (UsbTransferStatus status, array<uint8>? data); // Initiates an outbound generic transfer request on a specific endpoint. The // interface to which |endpoint_number| belongs must be claimed, and the @@ -215,7 +222,7 @@ interface Device { // indicates no timeout: the request will remain pending indefinitely until // completed or otherwise terminated. GenericTransferOut(uint8 endpoint_number, array<uint8> data, uint32 timeout) - => (TransferStatus status); + => (UsbTransferStatus status); // Initiates an inbound isochronous transfer request on a specific endpoint. // The interface to which |endpoint_number| belongs must be claimed, and the @@ -238,7 +245,7 @@ interface Device { IsochronousTransferIn(uint8 endpoint_number, array<uint32> packet_lengths, uint32 timeout) - => (array<uint8>? data, array<IsochronousPacket> packets); + => (array<uint8>? data, array<UsbIsochronousPacket> packets); // Initiates an outbound isochronous transfer request on a specific endpoint. // The interface to which |endpoint_number| belongs must be claimed, and the @@ -260,5 +267,5 @@ interface Device { array<uint8> data, array<uint32> packet_lengths, uint32 timeout) - => (array<IsochronousPacket> packets); + => (array<UsbIsochronousPacket> packets); }; diff --git a/chromium/device/usb/public/interfaces/device_manager.mojom b/chromium/device/usb/public/interfaces/device_manager.mojom index c1a88ae0ae9..9e906816c3d 100644 --- a/chromium/device/usb/public/interfaces/device_manager.mojom +++ b/chromium/device/usb/public/interfaces/device_manager.mojom @@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -module device.usb; +module device.mojom; import "device.mojom"; -struct DeviceFilter { +struct UsbDeviceFilter { bool has_vendor_id; uint16 vendor_id; @@ -25,27 +25,27 @@ struct DeviceFilter { string? serial_number; }; -struct EnumerationOptions { - array<DeviceFilter>? filters; +struct UsbEnumerationOptions { + array<UsbDeviceFilter>? filters; }; -interface DeviceManager { +interface UsbDeviceManager { // Retrieves information about all devices available to the DeviceManager // implementation. - GetDevices(EnumerationOptions? options) => (array<DeviceInfo> results); + GetDevices(UsbEnumerationOptions? options) => (array<UsbDeviceInfo> results); // Requests a device by guid. - GetDevice(string guid, Device& device_request); + GetDevice(string guid, UsbDevice& device_request); // Sets the client for this DeviceManager service. The service will notify its // client of device events such as connection and disconnection. - SetClient(DeviceManagerClient client); + SetClient(UsbDeviceManagerClient client); }; -interface DeviceManagerClient { +interface UsbDeviceManagerClient { // Called when a device is connected to the host. - OnDeviceAdded(DeviceInfo device_info); + OnDeviceAdded(UsbDeviceInfo device_info); // Called when a device is disconnected from the host. - OnDeviceRemoved(DeviceInfo device_info); + OnDeviceRemoved(UsbDeviceInfo device_info); }; diff --git a/chromium/device/usb/public/interfaces/device_manager.typemap b/chromium/device/usb/public/interfaces/device_manager.typemap index 7c350a1c072..088ee808e75 100644 --- a/chromium/device/usb/public/interfaces/device_manager.typemap +++ b/chromium/device/usb/public/interfaces/device_manager.typemap @@ -12,4 +12,4 @@ sources = [ deps = [ "//device/usb", ] -type_mappings = [ "device.usb.DeviceFilter=device::UsbDeviceFilter" ] +type_mappings = [ "device.mojom.UsbDeviceFilter=device::UsbDeviceFilter" ] diff --git a/chromium/device/usb/public/interfaces/device_manager_struct_traits.cc b/chromium/device/usb/public/interfaces/device_manager_struct_traits.cc index 771abdaba6f..8198152ebe9 100644 --- a/chromium/device/usb/public/interfaces/device_manager_struct_traits.cc +++ b/chromium/device/usb/public/interfaces/device_manager_struct_traits.cc @@ -7,9 +7,10 @@ namespace mojo { // static -bool StructTraits<device::usb::DeviceFilterDataView, device::UsbDeviceFilter>:: - Read(device::usb::DeviceFilterDataView input, - device::UsbDeviceFilter* output) { +bool StructTraits< + device::mojom::UsbDeviceFilterDataView, + device::UsbDeviceFilter>::Read(device::mojom::UsbDeviceFilterDataView input, + device::UsbDeviceFilter* output) { if (input.has_vendor_id()) output->vendor_id = input.vendor_id(); if (input.has_product_id()) diff --git a/chromium/device/usb/public/interfaces/device_manager_struct_traits.h b/chromium/device/usb/public/interfaces/device_manager_struct_traits.h index 682d5fe53b4..1028f661b86 100644 --- a/chromium/device/usb/public/interfaces/device_manager_struct_traits.h +++ b/chromium/device/usb/public/interfaces/device_manager_struct_traits.h @@ -11,7 +11,7 @@ namespace mojo { template <> -struct StructTraits<device::usb::DeviceFilterDataView, +struct StructTraits<device::mojom::UsbDeviceFilterDataView, device::UsbDeviceFilter> { static bool has_vendor_id(const device::UsbDeviceFilter& filter) { return filter.vendor_id.has_value(); @@ -58,7 +58,7 @@ struct StructTraits<device::usb::DeviceFilterDataView, return filter.serial_number; } - static bool Read(device::usb::DeviceFilterDataView input, + static bool Read(device::mojom::UsbDeviceFilterDataView input, device::UsbDeviceFilter* output); }; diff --git a/chromium/device/usb/usb_descriptors.cc b/chromium/device/usb/usb_descriptors.cc index 5ad332b4b12..ae25c1b79c6 100644 --- a/chromium/device/usb/usb_descriptors.cc +++ b/chromium/device/usb/usb_descriptors.cc @@ -41,7 +41,7 @@ const uint8_t kInterfaceDescriptorLength = 9; const uint8_t kEndpointDescriptorLength = 7; const uint8_t kInterfaceAssociationDescriptorLength = 8; -const int kControlTransferTimeout = 60000; // 1 minute +const int kControlTransferTimeoutMs = 2000; // 2 seconds struct UsbInterfaceAssociationDescriptor { UsbInterfaceAssociationDescriptor(uint8_t first_interface, @@ -97,7 +97,7 @@ void OnReadConfigDescriptor(UsbDeviceDescriptor* desc, UsbTransferStatus status, scoped_refptr<IOBuffer> buffer, size_t length) { - if (status == USB_TRANSFER_COMPLETED) { + if (status == UsbTransferStatus::COMPLETED) { if (!desc->Parse( std::vector<uint8_t>(buffer->data(), buffer->data() + length))) { LOG(ERROR) << "Failed to parse configuration descriptor."; @@ -115,15 +115,15 @@ void OnReadConfigDescriptorHeader(scoped_refptr<UsbDeviceHandle> device_handle, UsbTransferStatus status, scoped_refptr<IOBuffer> header, size_t length) { - if (status == USB_TRANSFER_COMPLETED && length == 4) { + if (status == UsbTransferStatus::COMPLETED && length == 4) { const uint8_t* data = reinterpret_cast<const uint8_t*>(header->data()); uint16_t total_length = data[2] | data[3] << 8; scoped_refptr<IOBuffer> buffer = new IOBuffer(total_length); device_handle->ControlTransfer( - USB_DIRECTION_INBOUND, UsbDeviceHandle::STANDARD, - UsbDeviceHandle::DEVICE, kGetDescriptorRequest, + UsbTransferDirection::INBOUND, UsbControlTransferType::STANDARD, + UsbControlTransferRecipient::DEVICE, kGetDescriptorRequest, kConfigurationDescriptorType << 8 | index, 0, buffer, total_length, - kControlTransferTimeout, + kControlTransferTimeoutMs, base::Bind(&OnReadConfigDescriptor, desc, closure)); } else { LOG(ERROR) << "Failed to read length for configuration " @@ -138,7 +138,7 @@ void OnReadDeviceDescriptor( UsbTransferStatus status, scoped_refptr<IOBuffer> buffer, size_t length) { - if (status != USB_TRANSFER_COMPLETED) { + if (status != UsbTransferStatus::COMPLETED) { LOG(ERROR) << "Failed to read device descriptor."; callback.Run(nullptr); return; @@ -166,10 +166,10 @@ void OnReadDeviceDescriptor( for (uint8_t i = 0; i < num_configurations; ++i) { scoped_refptr<IOBufferWithSize> header = new IOBufferWithSize(4); device_handle->ControlTransfer( - USB_DIRECTION_INBOUND, UsbDeviceHandle::STANDARD, - UsbDeviceHandle::DEVICE, kGetDescriptorRequest, + UsbTransferDirection::INBOUND, UsbControlTransferType::STANDARD, + UsbControlTransferRecipient::DEVICE, kGetDescriptorRequest, kConfigurationDescriptorType << 8 | i, 0, header, header->size(), - kControlTransferTimeout, + kControlTransferTimeoutMs, base::Bind(&OnReadConfigDescriptorHeader, device_handle, desc_ptr, i, closure)); } @@ -188,7 +188,7 @@ void OnReadStringDescriptor( scoped_refptr<IOBuffer> buffer, size_t length) { base::string16 string; - if (status == USB_TRANSFER_COMPLETED && + if (status == UsbTransferStatus::COMPLETED && ParseUsbStringDescriptor( std::vector<uint8_t>(buffer->data(), buffer->data() + length), &string)) { @@ -205,10 +205,10 @@ void ReadStringDescriptor( const base::Callback<void(const base::string16&)>& callback) { scoped_refptr<IOBufferWithSize> buffer = new IOBufferWithSize(255); device_handle->ControlTransfer( - USB_DIRECTION_INBOUND, UsbDeviceHandle::STANDARD, UsbDeviceHandle::DEVICE, - kGetDescriptorRequest, kStringDescriptorType << 8 | index, language_id, - buffer, buffer->size(), kControlTransferTimeout, - base::Bind(&OnReadStringDescriptor, callback)); + UsbTransferDirection::INBOUND, UsbControlTransferType::STANDARD, + UsbControlTransferRecipient::DEVICE, kGetDescriptorRequest, + kStringDescriptorType << 8 | index, language_id, buffer, buffer->size(), + kControlTransferTimeoutMs, base::Bind(&OnReadStringDescriptor, callback)); } void OnReadLanguageIds(scoped_refptr<UsbDeviceHandle> device_handle, @@ -254,24 +254,24 @@ UsbEndpointDescriptor::UsbEndpointDescriptor(uint8_t address, // These fields are defined in Table 9-24 of the USB 3.1 Specification. switch (address & 0x80) { case 0x00: - direction = USB_DIRECTION_OUTBOUND; + direction = UsbTransferDirection::OUTBOUND; break; case 0x80: - direction = USB_DIRECTION_INBOUND; + direction = UsbTransferDirection::INBOUND; break; } switch (attributes & 0x03) { case 0x00: - transfer_type = USB_TRANSFER_CONTROL; + transfer_type = UsbTransferType::CONTROL; break; case 0x01: - transfer_type = USB_TRANSFER_ISOCHRONOUS; + transfer_type = UsbTransferType::ISOCHRONOUS; break; case 0x02: - transfer_type = USB_TRANSFER_BULK; + transfer_type = UsbTransferType::BULK; break; case 0x03: - transfer_type = USB_TRANSFER_INTERRUPT; + transfer_type = UsbTransferType::INTERRUPT; break; } switch (attributes & 0x0F) { @@ -500,9 +500,10 @@ void ReadUsbDescriptors(scoped_refptr<UsbDeviceHandle> device_handle, scoped_refptr<IOBufferWithSize> buffer = new IOBufferWithSize(kDeviceDescriptorLength); device_handle->ControlTransfer( - USB_DIRECTION_INBOUND, UsbDeviceHandle::STANDARD, UsbDeviceHandle::DEVICE, - kGetDescriptorRequest, kDeviceDescriptorType << 8, 0, buffer, - buffer->size(), kControlTransferTimeout, + UsbTransferDirection::INBOUND, UsbControlTransferType::STANDARD, + UsbControlTransferRecipient::DEVICE, kGetDescriptorRequest, + kDeviceDescriptorType << 8, 0, buffer, buffer->size(), + kControlTransferTimeoutMs, base::Bind(&OnReadDeviceDescriptor, device_handle, callback)); } diff --git a/chromium/device/usb/usb_descriptors.h b/chromium/device/usb/usb_descriptors.h index 9039c957100..b0f5be6b6f4 100644 --- a/chromium/device/usb/usb_descriptors.h +++ b/chromium/device/usb/usb_descriptors.h @@ -14,22 +14,14 @@ #include "base/callback_forward.h" #include "base/memory/ref_counted.h" #include "base/strings/string16.h" +#include "device/usb/public/interfaces/device.mojom.h" namespace device { class UsbDeviceHandle; -enum UsbTransferType { - USB_TRANSFER_CONTROL = 0, - USB_TRANSFER_ISOCHRONOUS, - USB_TRANSFER_BULK, - USB_TRANSFER_INTERRUPT, -}; - -enum UsbEndpointDirection { - USB_DIRECTION_INBOUND = 0, - USB_DIRECTION_OUTBOUND, -}; +using UsbTransferType = mojom::UsbTransferType; +using UsbTransferDirection = mojom::UsbTransferDirection; enum UsbSynchronizationType { USB_SYNCHRONIZATION_NONE = 0, @@ -61,7 +53,7 @@ struct UsbEndpointDescriptor { ~UsbEndpointDescriptor(); uint8_t address; - UsbEndpointDirection direction; + UsbTransferDirection direction; uint16_t maximum_packet_size; UsbSynchronizationType synchronization_type; UsbTransferType transfer_type; diff --git a/chromium/device/usb/usb_descriptors_fuzzer.cc b/chromium/device/usb/usb_descriptors_fuzzer.cc index 560a9bfaa03..d1a971306bf 100644 --- a/chromium/device/usb/usb_descriptors_fuzzer.cc +++ b/chromium/device/usb/usb_descriptors_fuzzer.cc @@ -14,7 +14,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { device::UsbDeviceDescriptor desc; desc.Parse(std::vector<uint8_t>(data, data + size)); - mojo::ConvertTo<std::vector<device::usb::ConfigurationInfoPtr>>( + mojo::ConvertTo<std::vector<device::mojom::UsbConfigurationInfoPtr>>( desc.configurations); return 0; } diff --git a/chromium/device/usb/usb_descriptors_unittest.cc b/chromium/device/usb/usb_descriptors_unittest.cc index 195b01b40b6..06cc682473f 100644 --- a/chromium/device/usb/usb_descriptors_unittest.cc +++ b/chromium/device/usb/usb_descriptors_unittest.cc @@ -22,7 +22,7 @@ namespace { ACTION_P2(InvokeCallback, data, length) { size_t transferred_length = std::min(length, arg7); memcpy(arg6->data(), data, transferred_length); - arg9.Run(USB_TRANSFER_COMPLETED, arg6, transferred_length); + arg9.Run(UsbTransferStatus::COMPLETED, arg6, transferred_length); } void ExpectStringDescriptors( @@ -86,33 +86,36 @@ void ExpectConfig1Descriptor(const UsbConfigDescriptor& config) { EXPECT_EQ(0, config.interfaces[0].first_interface); // Endpoint 1 IN EXPECT_EQ(0x81, config.interfaces[0].endpoints[0].address); - EXPECT_EQ(USB_DIRECTION_INBOUND, config.interfaces[0].endpoints[0].direction); + EXPECT_EQ(UsbTransferDirection::INBOUND, + config.interfaces[0].endpoints[0].direction); EXPECT_EQ(512, config.interfaces[0].endpoints[0].maximum_packet_size); EXPECT_EQ(USB_SYNCHRONIZATION_NONE, config.interfaces[0].endpoints[0].synchronization_type); - EXPECT_EQ(USB_TRANSFER_BULK, config.interfaces[0].endpoints[0].transfer_type); + EXPECT_EQ(UsbTransferType::BULK, + config.interfaces[0].endpoints[0].transfer_type); EXPECT_EQ(USB_USAGE_RESERVED, config.interfaces[0].endpoints[0].usage_type); EXPECT_EQ(0, config.interfaces[0].endpoints[0].polling_interval); EXPECT_EQ(0u, config.interfaces[0].endpoints[0].extra_data.size()); // Endpoint 2 IN EXPECT_EQ(0x82, config.interfaces[0].endpoints[1].address); - EXPECT_EQ(USB_DIRECTION_INBOUND, config.interfaces[0].endpoints[1].direction); + EXPECT_EQ(UsbTransferDirection::INBOUND, + config.interfaces[0].endpoints[1].direction); EXPECT_EQ(512, config.interfaces[0].endpoints[1].maximum_packet_size); EXPECT_EQ(USB_SYNCHRONIZATION_NONE, config.interfaces[0].endpoints[1].synchronization_type); - EXPECT_EQ(USB_TRANSFER_INTERRUPT, + EXPECT_EQ(UsbTransferType::INTERRUPT, config.interfaces[0].endpoints[1].transfer_type); EXPECT_EQ(USB_USAGE_PERIODIC, config.interfaces[0].endpoints[1].usage_type); EXPECT_EQ(4, config.interfaces[0].endpoints[1].polling_interval); EXPECT_EQ(0u, config.interfaces[0].endpoints[1].extra_data.size()); // Endpoint 3 OUT EXPECT_EQ(0x03, config.interfaces[0].endpoints[2].address); - EXPECT_EQ(USB_DIRECTION_OUTBOUND, + EXPECT_EQ(UsbTransferDirection::OUTBOUND, config.interfaces[0].endpoints[2].direction); EXPECT_EQ(512, config.interfaces[0].endpoints[2].maximum_packet_size); EXPECT_EQ(USB_SYNCHRONIZATION_NONE, config.interfaces[0].endpoints[2].synchronization_type); - EXPECT_EQ(USB_TRANSFER_INTERRUPT, + EXPECT_EQ(UsbTransferType::INTERRUPT, config.interfaces[0].endpoints[2].transfer_type); EXPECT_EQ(USB_USAGE_NOTIFICATION, config.interfaces[0].endpoints[2].usage_type); @@ -157,23 +160,24 @@ void ExpectConfig2Descriptor(const UsbConfigDescriptor& config) { EXPECT_EQ(0, config.interfaces[1].first_interface); // Endpoint 1 IN EXPECT_EQ(0x81, config.interfaces[1].endpoints[0].address); - EXPECT_EQ(USB_DIRECTION_INBOUND, config.interfaces[1].endpoints[0].direction); + EXPECT_EQ(UsbTransferDirection::INBOUND, + config.interfaces[1].endpoints[0].direction); EXPECT_EQ(1024, config.interfaces[1].endpoints[0].maximum_packet_size); EXPECT_EQ(USB_SYNCHRONIZATION_NONE, config.interfaces[1].endpoints[0].synchronization_type); - EXPECT_EQ(USB_TRANSFER_ISOCHRONOUS, + EXPECT_EQ(UsbTransferType::ISOCHRONOUS, config.interfaces[1].endpoints[0].transfer_type); EXPECT_EQ(USB_USAGE_DATA, config.interfaces[1].endpoints[0].usage_type); EXPECT_EQ(8, config.interfaces[1].endpoints[0].polling_interval); EXPECT_EQ(0u, config.interfaces[1].endpoints[0].extra_data.size()); // Endpoint 2 OUT EXPECT_EQ(0x02, config.interfaces[1].endpoints[1].address); - EXPECT_EQ(USB_DIRECTION_OUTBOUND, + EXPECT_EQ(UsbTransferDirection::OUTBOUND, config.interfaces[1].endpoints[1].direction); EXPECT_EQ(1024, config.interfaces[1].endpoints[1].maximum_packet_size); EXPECT_EQ(USB_SYNCHRONIZATION_NONE, config.interfaces[1].endpoints[1].synchronization_type); - EXPECT_EQ(USB_TRANSFER_ISOCHRONOUS, + EXPECT_EQ(UsbTransferType::ISOCHRONOUS, config.interfaces[1].endpoints[1].transfer_type); EXPECT_EQ(USB_USAGE_FEEDBACK, config.interfaces[1].endpoints[1].usage_type); EXPECT_EQ(8, config.interfaces[1].endpoints[1].polling_interval); @@ -219,21 +223,24 @@ TEST_F(UsbDescriptorsTest, ReadDescriptors) { scoped_refptr<MockUsbDeviceHandle> device_handle( new MockUsbDeviceHandle(nullptr)); EXPECT_CALL(*device_handle, - ControlTransfer(USB_DIRECTION_INBOUND, UsbDeviceHandle::STANDARD, - UsbDeviceHandle::DEVICE, 0x06, 0x0100, 0x0000, _, - _, _, _)) + ControlTransfer(UsbTransferDirection::INBOUND, + UsbControlTransferType::STANDARD, + UsbControlTransferRecipient::DEVICE, 0x06, 0x0100, + 0x0000, _, _, _, _)) .WillOnce(InvokeCallback(kDeviceDescriptor, sizeof(kDeviceDescriptor))); EXPECT_CALL(*device_handle, - ControlTransfer(USB_DIRECTION_INBOUND, UsbDeviceHandle::STANDARD, - UsbDeviceHandle::DEVICE, 0x06, 0x0200, 0x0000, _, - _, _, _)) + ControlTransfer(UsbTransferDirection::INBOUND, + UsbControlTransferType::STANDARD, + UsbControlTransferRecipient::DEVICE, 0x06, 0x0200, + 0x0000, _, _, _, _)) .Times(2) .WillRepeatedly( InvokeCallback(kConfig1Descriptor, sizeof(kConfig1Descriptor))); EXPECT_CALL(*device_handle, - ControlTransfer(USB_DIRECTION_INBOUND, UsbDeviceHandle::STANDARD, - UsbDeviceHandle::DEVICE, 0x06, 0x0201, 0x0000, _, - _, _, _)) + ControlTransfer(UsbTransferDirection::INBOUND, + UsbControlTransferType::STANDARD, + UsbControlTransferRecipient::DEVICE, 0x06, 0x0201, + 0x0000, _, _, _, _)) .Times(2) .WillRepeatedly( InvokeCallback(kConfig2Descriptor, sizeof(kConfig2Descriptor))); @@ -400,33 +407,37 @@ TEST_F(UsbDescriptorsTest, ReadStringDescriptors) { new MockUsbDeviceHandle(nullptr)); static const uint8_t kStringDescriptor0[] = {0x04, 0x03, 0x21, 0x43}; EXPECT_CALL(*device_handle, - ControlTransfer(USB_DIRECTION_INBOUND, UsbDeviceHandle::STANDARD, - UsbDeviceHandle::DEVICE, 0x06, 0x0300, 0x0000, _, - _, _, _)) + ControlTransfer(UsbTransferDirection::INBOUND, + UsbControlTransferType::STANDARD, + UsbControlTransferRecipient::DEVICE, 0x06, 0x0300, + 0x0000, _, _, _, _)) .WillOnce(InvokeCallback(kStringDescriptor0, sizeof(kStringDescriptor0))); static const uint8_t kStringDescriptor1[] = {0x12, 0x03, 'S', 0, 't', 0, 'r', 0, 'i', 0, 'n', 0, 'g', 0, ' ', 0, '1', 0}; EXPECT_CALL(*device_handle, - ControlTransfer(USB_DIRECTION_INBOUND, UsbDeviceHandle::STANDARD, - UsbDeviceHandle::DEVICE, 0x06, 0x0301, 0x4321, _, - _, _, _)) + ControlTransfer(UsbTransferDirection::INBOUND, + UsbControlTransferType::STANDARD, + UsbControlTransferRecipient::DEVICE, 0x06, 0x0301, + 0x4321, _, _, _, _)) .WillOnce(InvokeCallback(kStringDescriptor1, sizeof(kStringDescriptor1))); static const uint8_t kStringDescriptor2[] = {0x12, 0x03, 'S', 0, 't', 0, 'r', 0, 'i', 0, 'n', 0, 'g', 0, ' ', 0, '2', 0}; EXPECT_CALL(*device_handle, - ControlTransfer(USB_DIRECTION_INBOUND, UsbDeviceHandle::STANDARD, - UsbDeviceHandle::DEVICE, 0x06, 0x0302, 0x4321, _, - _, _, _)) + ControlTransfer(UsbTransferDirection::INBOUND, + UsbControlTransferType::STANDARD, + UsbControlTransferRecipient::DEVICE, 0x06, 0x0302, + 0x4321, _, _, _, _)) .WillOnce(InvokeCallback(kStringDescriptor2, sizeof(kStringDescriptor2))); static const uint8_t kStringDescriptor3[] = {0x12, 0x03, 'S', 0, 't', 0, 'r', 0, 'i', 0, 'n', 0, 'g', 0, ' ', 0, '3', 0}; EXPECT_CALL(*device_handle, - ControlTransfer(USB_DIRECTION_INBOUND, UsbDeviceHandle::STANDARD, - UsbDeviceHandle::DEVICE, 0x06, 0x0303, 0x4321, _, - _, _, _)) + ControlTransfer(UsbTransferDirection::INBOUND, + UsbControlTransferType::STANDARD, + UsbControlTransferRecipient::DEVICE, 0x06, 0x0303, + 0x4321, _, _, _, _)) .WillOnce(InvokeCallback(kStringDescriptor3, sizeof(kStringDescriptor3))); ReadUsbStringDescriptors(device_handle, std::move(string_map), diff --git a/chromium/device/usb/usb_device.h b/chromium/device/usb/usb_device.h index bc678f43ff9..27fc6b4571f 100644 --- a/chromium/device/usb/usb_device.h +++ b/chromium/device/usb/usb_device.h @@ -23,7 +23,6 @@ namespace device { class UsbDeviceHandle; -struct WebUsbAllowedOrigins; // A UsbDevice object represents a detected USB device, providing basic // information about it. Methods other than simple property accessors must be @@ -64,9 +63,6 @@ class UsbDevice : public base::RefCountedThreadSafe<UsbDevice> { } const base::string16& product_string() const { return product_string_; } const base::string16& serial_number() const { return serial_number_; } - const WebUsbAllowedOrigins* webusb_allowed_origins() const { - return webusb_allowed_origins_.get(); - } const GURL& webusb_landing_page() const { return webusb_landing_page_; } const std::vector<UsbConfigDescriptor>& configurations() const { return descriptor_.configurations; @@ -125,7 +121,6 @@ class UsbDevice : public base::RefCountedThreadSafe<UsbDevice> { base::string16 manufacturer_string_; base::string16 product_string_; base::string16 serial_number_; - std::unique_ptr<WebUsbAllowedOrigins> webusb_allowed_origins_; GURL webusb_landing_page_; private: diff --git a/chromium/device/usb/usb_device_android.cc b/chromium/device/usb/usb_device_android.cc index 7f98ec6f5d0..72b496f44ed 100644 --- a/chromium/device/usb/usb_device_android.cc +++ b/chromium/device/usb/usb_device_android.cc @@ -27,7 +27,6 @@ namespace device { scoped_refptr<UsbDeviceAndroid> UsbDeviceAndroid::Create( JNIEnv* env, base::WeakPtr<UsbServiceAndroid> service, - scoped_refptr<base::SequencedTaskRunner> blocking_task_runner, const JavaRef<jobject>& usb_device) { ScopedJavaLocalRef<jobject> wrapper = Java_ChromeUsbDevice_create(env, usb_device); @@ -51,8 +50,7 @@ scoped_refptr<UsbDeviceAndroid> UsbDeviceAndroid::Create( Java_ChromeUsbDevice_getDeviceProtocol(env, wrapper), Java_ChromeUsbDevice_getVendorId(env, wrapper), Java_ChromeUsbDevice_getProductId(env, wrapper), device_version, - manufacturer_string, product_string, serial_number, blocking_task_runner, - wrapper)); + manufacturer_string, product_string, serial_number, wrapper)); } void UsbDeviceAndroid::RequestPermission(const ResultCallback& callback) { @@ -72,8 +70,7 @@ void UsbDeviceAndroid::Open(const OpenCallback& callback) { ScopedJavaLocalRef<jobject> connection = service_->OpenDevice(env, j_object_); if (!connection.is_null()) { - device_handle = UsbDeviceHandleAndroid::Create( - env, this, blocking_task_runner_, connection); + device_handle = UsbDeviceHandleAndroid::Create(env, this, connection); handles().push_back(device_handle.get()); } } @@ -98,7 +95,6 @@ UsbDeviceAndroid::UsbDeviceAndroid( const base::string16& manufacturer_string, const base::string16& product_string, const base::string16& serial_number, - scoped_refptr<base::SequencedTaskRunner> blocking_task_runner, const JavaRef<jobject>& wrapper) : UsbDevice(usb_version, device_class, @@ -110,7 +106,6 @@ UsbDeviceAndroid::UsbDeviceAndroid( manufacturer_string, product_string, serial_number), - blocking_task_runner_(blocking_task_runner), device_id_(Java_ChromeUsbDevice_getDeviceId(env, wrapper)), service_(service), j_object_(wrapper) { @@ -200,10 +195,7 @@ void UsbDeviceAndroid::OnReadDescriptors( void UsbDeviceAndroid::OnReadWebUsbDescriptors( scoped_refptr<UsbDeviceHandle> device_handle, - std::unique_ptr<WebUsbAllowedOrigins> allowed_origins, const GURL& landing_page) { - if (allowed_origins) - webusb_allowed_origins_ = std::move(allowed_origins); if (landing_page.is_valid()) webusb_landing_page_ = landing_page; diff --git a/chromium/device/usb/usb_device_android.h b/chromium/device/usb/usb_device_android.h index 699354e9f7b..70782635e79 100644 --- a/chromium/device/usb/usb_device_android.h +++ b/chromium/device/usb/usb_device_android.h @@ -9,10 +9,6 @@ #include "base/memory/weak_ptr.h" #include "device/usb/usb_device.h" -namespace base { -class SequencedTaskRunner; -} - namespace device { class UsbServiceAndroid; @@ -22,7 +18,6 @@ class UsbDeviceAndroid : public UsbDevice { static scoped_refptr<UsbDeviceAndroid> Create( JNIEnv* env, base::WeakPtr<UsbServiceAndroid> service, - scoped_refptr<base::SequencedTaskRunner> blocking_task_runner, const base::android::JavaRef<jobject>& usb_device); // UsbDevice: @@ -47,7 +42,6 @@ class UsbDeviceAndroid : public UsbDevice { const base::string16& manufacturer_string, const base::string16& product_string, const base::string16& serial_number, - scoped_refptr<base::SequencedTaskRunner> blocking_task_runner, const base::android::JavaRef<jobject>& wrapper); ~UsbDeviceAndroid() override; @@ -58,11 +52,8 @@ class UsbDeviceAndroid : public UsbDevice { std::unique_ptr<UsbDeviceDescriptor> descriptor); void OnReadWebUsbDescriptors( scoped_refptr<UsbDeviceHandle> device_handle, - std::unique_ptr<WebUsbAllowedOrigins> allowed_origins, const GURL& landing_page); - scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_; - const jint device_id_; bool permission_granted_ = false; std::list<ResultCallback> request_permission_callbacks_; diff --git a/chromium/device/usb/usb_device_handle.h b/chromium/device/usb/usb_device_handle.h index 32d25f39a60..d592a8d4b2e 100644 --- a/chromium/device/usb/usb_device_handle.h +++ b/chromium/device/usb/usb_device_handle.h @@ -16,6 +16,7 @@ #include "base/memory/ref_counted.h" #include "base/strings/string16.h" #include "base/threading/thread_checker.h" +#include "device/usb/public/interfaces/device.mojom.h" #include "device/usb/usb_descriptors.h" namespace net { @@ -26,16 +27,9 @@ namespace device { class UsbDevice; -enum UsbTransferStatus { - USB_TRANSFER_COMPLETED = 0, - USB_TRANSFER_ERROR, - USB_TRANSFER_TIMEOUT, - USB_TRANSFER_CANCELLED, - USB_TRANSFER_STALLED, - USB_TRANSFER_DISCONNECT, - USB_TRANSFER_OVERFLOW, - USB_TRANSFER_LENGTH_SHORT, -}; +using UsbTransferStatus = mojom::UsbTransferStatus; +using UsbControlTransferType = mojom::UsbControlTransferType; +using UsbControlTransferRecipient = mojom::UsbControlTransferRecipient; // UsbDeviceHandle class provides basic I/O related functionalities. class UsbDeviceHandle : public base::RefCountedThreadSafe<UsbDeviceHandle> { @@ -53,9 +47,6 @@ class UsbDeviceHandle : public base::RefCountedThreadSafe<UsbDeviceHandle> { base::Callback<void(scoped_refptr<net::IOBuffer>, const std::vector<IsochronousPacket>& packets)>; - enum TransferRequestType { STANDARD, CLASS, VENDOR, RESERVED }; - enum TransferRecipient { DEVICE, INTERFACE, ENDPOINT, OTHER }; - virtual scoped_refptr<UsbDevice> GetDevice() const = 0; // Notifies UsbDevice to drop the reference of this object; cancels all the @@ -80,9 +71,9 @@ class UsbDeviceHandle : public base::RefCountedThreadSafe<UsbDeviceHandle> { // The transfer functions may be called from any thread. The provided callback // will be run on the caller's thread. - virtual void ControlTransfer(UsbEndpointDirection direction, - TransferRequestType request_type, - TransferRecipient recipient, + virtual void ControlTransfer(UsbTransferDirection direction, + UsbControlTransferType request_type, + UsbControlTransferRecipient recipient, uint8_t request, uint16_t value, uint16_t index, @@ -104,7 +95,7 @@ class UsbDeviceHandle : public base::RefCountedThreadSafe<UsbDeviceHandle> { unsigned int timeout, const IsochronousTransferCallback& callback) = 0; - virtual void GenericTransfer(UsbEndpointDirection direction, + virtual void GenericTransfer(UsbTransferDirection direction, uint8_t endpoint_number, scoped_refptr<net::IOBuffer> buffer, size_t length, diff --git a/chromium/device/usb/usb_device_handle_android.cc b/chromium/device/usb/usb_device_handle_android.cc index d5dce7a8e0f..d3d794ab310 100644 --- a/chromium/device/usb/usb_device_handle_android.cc +++ b/chromium/device/usb/usb_device_handle_android.cc @@ -7,6 +7,7 @@ #include "base/bind.h" #include "base/location.h" #include "device/usb/usb_device.h" +#include "device/usb/usb_service.h" #include "jni/ChromeUsbConnection_jni.h" using base::android::ScopedJavaLocalRef; @@ -17,23 +18,23 @@ namespace device { scoped_refptr<UsbDeviceHandleAndroid> UsbDeviceHandleAndroid::Create( JNIEnv* env, scoped_refptr<UsbDevice> device, - scoped_refptr<base::SequencedTaskRunner> blocking_task_runner, const base::android::JavaRef<jobject>& usb_connection) { ScopedJavaLocalRef<jobject> wrapper = Java_ChromeUsbConnection_create(env, usb_connection); // C++ doesn't own this file descriptor so CloseBlocking() is overridden // below to release it without closing it. base::ScopedFD fd(Java_ChromeUsbConnection_getFileDescriptor(env, wrapper)); - return make_scoped_refptr(new UsbDeviceHandleAndroid( - device, std::move(fd), blocking_task_runner, wrapper)); + return make_scoped_refptr( + new UsbDeviceHandleAndroid(device, std::move(fd), wrapper)); } UsbDeviceHandleAndroid::UsbDeviceHandleAndroid( scoped_refptr<UsbDevice> device, base::ScopedFD fd, - scoped_refptr<base::SequencedTaskRunner> blocking_task_runner, const base::android::JavaRef<jobject>& wrapper) - : UsbDeviceHandleUsbfs(device, std::move(fd), blocking_task_runner), + : UsbDeviceHandleUsbfs(device, + std::move(fd), + UsbService::CreateBlockingTaskRunner()), j_object_(wrapper) {} UsbDeviceHandleAndroid::~UsbDeviceHandleAndroid() {} diff --git a/chromium/device/usb/usb_device_handle_android.h b/chromium/device/usb/usb_device_handle_android.h index d6a7cb7deeb..6e7a51c41ed 100644 --- a/chromium/device/usb/usb_device_handle_android.h +++ b/chromium/device/usb/usb_device_handle_android.h @@ -7,7 +7,6 @@ #include "base/android/scoped_java_ref.h" #include "base/memory/ref_counted.h" -#include "base/sequenced_task_runner.h" #include "device/usb/usb_device_handle_usbfs.h" namespace device { @@ -21,7 +20,6 @@ class UsbDeviceHandleAndroid : public UsbDeviceHandleUsbfs { static scoped_refptr<UsbDeviceHandleAndroid> Create( JNIEnv* env, scoped_refptr<UsbDevice> device, - scoped_refptr<base::SequencedTaskRunner> blocking_task_runner, const base::android::JavaRef<jobject>& usb_connection); private: @@ -29,7 +27,6 @@ class UsbDeviceHandleAndroid : public UsbDeviceHandleUsbfs { UsbDeviceHandleAndroid( scoped_refptr<UsbDevice> device, base::ScopedFD fd, - scoped_refptr<base::SequencedTaskRunner> blocking_task_runner, const base::android::JavaRef<jobject>& wrapper); ~UsbDeviceHandleAndroid() override; diff --git a/chromium/device/usb/usb_device_handle_impl.cc b/chromium/device/usb/usb_device_handle_impl.cc index d8b28a92310..e8b5b4244fa 100644 --- a/chromium/device/usb/usb_device_handle_impl.cc +++ b/chromium/device/usb/usb_device_handle_impl.cc @@ -13,10 +13,10 @@ #include "base/bind.h" #include "base/location.h" #include "base/macros.h" +#include "base/sequence_checker.h" #include "base/single_thread_task_runner.h" #include "base/stl_util.h" #include "base/strings/string16.h" -#include "base/synchronization/lock.h" #include "base/threading/thread_task_runner_handle.h" #include "components/device_event_log/device_event_log.h" #include "device/usb/usb_context.h" @@ -35,49 +35,48 @@ void HandleTransferCompletion(PlatformUsbTransferHandle transfer); namespace { -uint8_t ConvertTransferDirection(UsbEndpointDirection direction) { +uint8_t ConvertTransferDirection(UsbTransferDirection direction) { switch (direction) { - case USB_DIRECTION_INBOUND: + case UsbTransferDirection::INBOUND: return LIBUSB_ENDPOINT_IN; - case USB_DIRECTION_OUTBOUND: + case UsbTransferDirection::OUTBOUND: return LIBUSB_ENDPOINT_OUT; - default: - NOTREACHED(); - return LIBUSB_ENDPOINT_IN; } + NOTREACHED(); + return 0; } -uint8_t CreateRequestType(UsbEndpointDirection direction, - UsbDeviceHandle::TransferRequestType request_type, - UsbDeviceHandle::TransferRecipient recipient) { +uint8_t CreateRequestType(UsbTransferDirection direction, + UsbControlTransferType request_type, + UsbControlTransferRecipient recipient) { uint8_t result = ConvertTransferDirection(direction); switch (request_type) { - case UsbDeviceHandle::STANDARD: + case UsbControlTransferType::STANDARD: result |= LIBUSB_REQUEST_TYPE_STANDARD; break; - case UsbDeviceHandle::CLASS: + case UsbControlTransferType::CLASS: result |= LIBUSB_REQUEST_TYPE_CLASS; break; - case UsbDeviceHandle::VENDOR: + case UsbControlTransferType::VENDOR: result |= LIBUSB_REQUEST_TYPE_VENDOR; break; - case UsbDeviceHandle::RESERVED: + case UsbControlTransferType::RESERVED: result |= LIBUSB_REQUEST_TYPE_RESERVED; break; } switch (recipient) { - case UsbDeviceHandle::DEVICE: + case UsbControlTransferRecipient::DEVICE: result |= LIBUSB_RECIPIENT_DEVICE; break; - case UsbDeviceHandle::INTERFACE: + case UsbControlTransferRecipient::INTERFACE: result |= LIBUSB_RECIPIENT_INTERFACE; break; - case UsbDeviceHandle::ENDPOINT: + case UsbControlTransferRecipient::ENDPOINT: result |= LIBUSB_RECIPIENT_ENDPOINT; break; - case UsbDeviceHandle::OTHER: + case UsbControlTransferRecipient::OTHER: result |= LIBUSB_RECIPIENT_OTHER; break; } @@ -89,23 +88,22 @@ static UsbTransferStatus ConvertTransferStatus( const libusb_transfer_status status) { switch (status) { case LIBUSB_TRANSFER_COMPLETED: - return USB_TRANSFER_COMPLETED; + return UsbTransferStatus::COMPLETED; case LIBUSB_TRANSFER_ERROR: - return USB_TRANSFER_ERROR; + return UsbTransferStatus::TRANSFER_ERROR; case LIBUSB_TRANSFER_TIMED_OUT: - return USB_TRANSFER_TIMEOUT; + return UsbTransferStatus::TIMEOUT; case LIBUSB_TRANSFER_STALL: - return USB_TRANSFER_STALLED; + return UsbTransferStatus::STALLED; case LIBUSB_TRANSFER_NO_DEVICE: - return USB_TRANSFER_DISCONNECT; + return UsbTransferStatus::DISCONNECT; case LIBUSB_TRANSFER_OVERFLOW: - return USB_TRANSFER_OVERFLOW; + return UsbTransferStatus::BABBLE; case LIBUSB_TRANSFER_CANCELLED: - return USB_TRANSFER_CANCELLED; - default: - NOTREACHED(); - return USB_TRANSFER_ERROR; + return UsbTransferStatus::CANCELLED; } + NOTREACHED(); + return UsbTransferStatus::TRANSFER_ERROR; } static void RunTransferCallback( @@ -114,7 +112,7 @@ static void RunTransferCallback( UsbTransferStatus status, scoped_refptr<net::IOBuffer> buffer, size_t result) { - if (callback_task_runner->RunsTasksOnCurrentThread()) { + if (callback_task_runner->RunsTasksInCurrentSequence()) { callback.Run(status, buffer, result); } else { callback_task_runner->PostTask( @@ -134,7 +132,7 @@ void ReportIsochronousTransferError( packets[i].transferred_length = 0; packets[i].status = status; } - if (callback_task_runner->RunsTasksOnCurrentThread()) { + if (callback_task_runner->RunsTasksInCurrentSequence()) { callback.Run(nullptr, packets); } else { callback_task_runner->PostTask(FROM_HERE, @@ -170,7 +168,7 @@ class UsbDeviceHandleImpl::InterfaceClaimer int alternate_setting_; const scoped_refptr<base::SingleThreadTaskRunner> task_runner_; ResultCallback release_callback_; - base::ThreadChecker thread_checker_; + base::SequenceChecker sequence_checker_; DISALLOW_COPY_AND_ASSIGN(InterfaceClaimer); }; @@ -185,7 +183,7 @@ UsbDeviceHandleImpl::InterfaceClaimer::InterfaceClaimer( task_runner_(task_runner) {} UsbDeviceHandleImpl::InterfaceClaimer::~InterfaceClaimer() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(sequence_checker_.CalledOnValidSequence()); int rc = libusb_release_interface(handle_->handle(), interface_number_); if (rc != LIBUSB_SUCCESS) { USB_LOG(DEBUG) << "Failed to release interface: " @@ -298,7 +296,7 @@ UsbDeviceHandleImpl::Transfer::CreateControlTransfer( scoped_refptr<base::TaskRunner> callback_task_runner, const TransferCallback& callback) { std::unique_ptr<Transfer> transfer(new Transfer( - device_handle, nullptr, USB_TRANSFER_CONTROL, buffer, + device_handle, nullptr, UsbTransferType::CONTROL, buffer, length + LIBUSB_CONTROL_SETUP_SIZE, callback_task_runner, callback)); transfer->platform_transfer_ = libusb_alloc_transfer(0); @@ -330,7 +328,7 @@ UsbDeviceHandleImpl::Transfer::CreateBulkTransfer( const TransferCallback& callback) { std::unique_ptr<Transfer> transfer(new Transfer( device_handle, device_handle->GetClaimedInterfaceForEndpoint(endpoint), - USB_TRANSFER_BULK, buffer, length, callback_task_runner, callback)); + UsbTransferType::BULK, buffer, length, callback_task_runner, callback)); transfer->platform_transfer_ = libusb_alloc_transfer(0); if (!transfer->platform_transfer_) { @@ -359,7 +357,8 @@ UsbDeviceHandleImpl::Transfer::CreateInterruptTransfer( const TransferCallback& callback) { std::unique_ptr<Transfer> transfer(new Transfer( device_handle, device_handle->GetClaimedInterfaceForEndpoint(endpoint), - USB_TRANSFER_INTERRUPT, buffer, length, callback_task_runner, callback)); + UsbTransferType::INTERRUPT, buffer, length, callback_task_runner, + callback)); transfer->platform_transfer_ = libusb_alloc_transfer(0); if (!transfer->platform_transfer_) { @@ -433,7 +432,7 @@ UsbDeviceHandleImpl::Transfer::Transfer( scoped_refptr<net::IOBuffer> buffer, scoped_refptr<base::TaskRunner> callback_task_runner, const IsochronousTransferCallback& callback) - : transfer_type_(USB_TRANSFER_ISOCHRONOUS), + : transfer_type_(UsbTransferType::ISOCHRONOUS), device_handle_(device_handle), buffer_(buffer), claimed_interface_(claimed_interface), @@ -453,7 +452,7 @@ void UsbDeviceHandleImpl::Transfer::Submit() { if (rv != LIBUSB_SUCCESS) { USB_LOG(EVENT) << "Failed to submit transfer: " << ConvertPlatformUsbErrorToString(rv); - TransferComplete(USB_TRANSFER_ERROR, 0); + TransferComplete(UsbTransferStatus::TRANSFER_ERROR, 0); } } @@ -475,7 +474,7 @@ void UsbDeviceHandleImpl::Transfer::ProcessCompletion() { << "data too big for our buffer (libusb failure?)"; switch (transfer_type_) { - case USB_TRANSFER_CONTROL: + case UsbTransferType::CONTROL: // If the transfer is a control transfer we do not expose the control // setup header to the caller. This logic strips off the header if // present before invoking the callback provided with the transfer. @@ -495,13 +494,13 @@ void UsbDeviceHandleImpl::Transfer::ProcessCompletion() { } // Fall through! - case USB_TRANSFER_BULK: - case USB_TRANSFER_INTERRUPT: + case UsbTransferType::BULK: + case UsbTransferType::INTERRUPT: TransferComplete(ConvertTransferStatus(platform_transfer_->status), actual_length); break; - case USB_TRANSFER_ISOCHRONOUS: + case UsbTransferType::ISOCHRONOUS: IsochronousTransferComplete(); break; @@ -523,7 +522,7 @@ void LIBUSB_CALL UsbDeviceHandleImpl::Transfer::PlatformCallback( void UsbDeviceHandleImpl::Transfer::TransferComplete(UsbTransferStatus status, size_t bytes_transferred) { base::Closure closure; - if (transfer_type_ == USB_TRANSFER_ISOCHRONOUS) { + if (transfer_type_ == UsbTransferType::ISOCHRONOUS) { DCHECK_NE(LIBUSB_TRANSFER_COMPLETED, platform_transfer_->status); std::vector<IsochronousPacket> packets(platform_transfer_->num_iso_packets); for (size_t i = 0; i < packets.size(); ++i) { @@ -697,9 +696,9 @@ void UsbDeviceHandleImpl::ClearHalt(uint8_t endpoint, this, endpoint, callback)); } -void UsbDeviceHandleImpl::ControlTransfer(UsbEndpointDirection direction, - TransferRequestType request_type, - TransferRecipient recipient, +void UsbDeviceHandleImpl::ControlTransfer(UsbTransferDirection direction, + UsbControlTransferType request_type, + UsbControlTransferRecipient recipient, uint8_t request, uint16_t value, uint16_t index, @@ -726,7 +725,7 @@ void UsbDeviceHandleImpl::IsochronousTransferIn( unsigned int timeout, const IsochronousTransferCallback& callback) { uint8_t endpoint_address = - ConvertTransferDirection(USB_DIRECTION_INBOUND) | endpoint_number; + ConvertTransferDirection(UsbTransferDirection::INBOUND) | endpoint_number; if (task_runner_->BelongsToCurrentThread()) { IsochronousTransferInInternal(endpoint_address, packet_lengths, timeout, task_runner_, callback); @@ -746,7 +745,8 @@ void UsbDeviceHandleImpl::IsochronousTransferOut( unsigned int timeout, const IsochronousTransferCallback& callback) { uint8_t endpoint_address = - ConvertTransferDirection(USB_DIRECTION_OUTBOUND) | endpoint_number; + ConvertTransferDirection(UsbTransferDirection::OUTBOUND) | + endpoint_number; if (task_runner_->BelongsToCurrentThread()) { IsochronousTransferOutInternal(endpoint_address, buffer, packet_lengths, timeout, task_runner_, callback); @@ -759,7 +759,7 @@ void UsbDeviceHandleImpl::IsochronousTransferOut( } } -void UsbDeviceHandleImpl::GenericTransfer(UsbEndpointDirection direction, +void UsbDeviceHandleImpl::GenericTransfer(UsbTransferDirection direction, uint8_t endpoint_number, scoped_refptr<net::IOBuffer> buffer, size_t length, @@ -806,7 +806,7 @@ UsbDeviceHandleImpl::~UsbDeviceHandleImpl() { // This class is RefCountedThreadSafe and so the destructor may be called on // any thread. libusb is not safe to reentrancy so be sure not to try to close // the device from inside a transfer completion callback. - if (blocking_task_runner_->RunsTasksOnCurrentThread()) { + if (blocking_task_runner_->RunsTasksInCurrentSequence()) { libusb_close(handle_); } else { blocking_task_runner_->PostTask(FROM_HERE, @@ -969,9 +969,9 @@ UsbDeviceHandleImpl::GetClaimedInterfaceForEndpoint(uint8_t endpoint) { } void UsbDeviceHandleImpl::ControlTransferInternal( - UsbEndpointDirection direction, - TransferRequestType request_type, - TransferRecipient recipient, + UsbTransferDirection direction, + UsbControlTransferType request_type, + UsbControlTransferRecipient recipient, uint8_t request, uint16_t value, uint16_t index, @@ -983,15 +983,15 @@ void UsbDeviceHandleImpl::ControlTransferInternal( DCHECK(thread_checker_.CalledOnValidThread()); if (!device_) { - RunTransferCallback(callback_task_runner, callback, USB_TRANSFER_DISCONNECT, - buffer, 0); + RunTransferCallback(callback_task_runner, callback, + UsbTransferStatus::DISCONNECT, buffer, 0); return; } if (!base::IsValueInRangeForNumericType<uint16_t>(length)) { USB_LOG(USER) << "Transfer too long."; - RunTransferCallback(callback_task_runner, callback, USB_TRANSFER_ERROR, - buffer, 0); + RunTransferCallback(callback_task_runner, callback, + UsbTransferStatus::TRANSFER_ERROR, buffer, 0); return; } @@ -999,8 +999,8 @@ void UsbDeviceHandleImpl::ControlTransferInternal( scoped_refptr<net::IOBuffer> resized_buffer = new net::IOBufferWithSize(resized_length); if (!resized_buffer.get()) { - RunTransferCallback(callback_task_runner, callback, USB_TRANSFER_ERROR, - buffer, 0); + RunTransferCallback(callback_task_runner, callback, + UsbTransferStatus::TRANSFER_ERROR, buffer, 0); return; } memcpy(resized_buffer->data() + LIBUSB_CONTROL_SETUP_SIZE, buffer->data(), @@ -1011,8 +1011,8 @@ void UsbDeviceHandleImpl::ControlTransferInternal( value, index, static_cast<uint16_t>(length), resized_buffer, timeout, callback_task_runner, callback); if (!transfer) { - RunTransferCallback(callback_task_runner, callback, USB_TRANSFER_ERROR, - buffer, 0); + RunTransferCallback(callback_task_runner, callback, + UsbTransferStatus::TRANSFER_ERROR, buffer, 0); return; } @@ -1029,7 +1029,8 @@ void UsbDeviceHandleImpl::IsochronousTransferInInternal( if (!device_) { ReportIsochronousTransferError(callback_task_runner, callback, - packet_lengths, USB_TRANSFER_DISCONNECT); + packet_lengths, + UsbTransferStatus::DISCONNECT); return; } @@ -1054,7 +1055,8 @@ void UsbDeviceHandleImpl::IsochronousTransferOutInternal( if (!device_) { ReportIsochronousTransferError(callback_task_runner, callback, - packet_lengths, USB_TRANSFER_DISCONNECT); + packet_lengths, + UsbTransferStatus::DISCONNECT); return; } @@ -1077,8 +1079,8 @@ void UsbDeviceHandleImpl::GenericTransferInternal( DCHECK(thread_checker_.CalledOnValidThread()); if (!device_) { - RunTransferCallback(callback_task_runner, callback, USB_TRANSFER_DISCONNECT, - buffer, 0); + RunTransferCallback(callback_task_runner, callback, + UsbTransferStatus::DISCONNECT, buffer, 0); return; } @@ -1087,33 +1089,33 @@ void UsbDeviceHandleImpl::GenericTransferInternal( USB_LOG(DEBUG) << "Failed to submit transfer because endpoint " << static_cast<int>(endpoint_address) << " not part of a claimed interface."; - RunTransferCallback(callback_task_runner, callback, USB_TRANSFER_ERROR, - buffer, 0); + RunTransferCallback(callback_task_runner, callback, + UsbTransferStatus::TRANSFER_ERROR, buffer, 0); return; } if (!base::IsValueInRangeForNumericType<int>(length)) { USB_LOG(DEBUG) << "Transfer too long."; - RunTransferCallback(callback_task_runner, callback, USB_TRANSFER_ERROR, - buffer, 0); + RunTransferCallback(callback_task_runner, callback, + UsbTransferStatus::TRANSFER_ERROR, buffer, 0); return; } std::unique_ptr<Transfer> transfer; UsbTransferType transfer_type = endpoint_it->second.endpoint->transfer_type; - if (transfer_type == USB_TRANSFER_BULK) { + if (transfer_type == UsbTransferType::BULK) { transfer = Transfer::CreateBulkTransfer(this, endpoint_address, buffer, static_cast<int>(length), timeout, callback_task_runner, callback); - } else if (transfer_type == USB_TRANSFER_INTERRUPT) { + } else if (transfer_type == UsbTransferType::INTERRUPT) { transfer = Transfer::CreateInterruptTransfer( this, endpoint_address, buffer, static_cast<int>(length), timeout, callback_task_runner, callback); } else { USB_LOG(DEBUG) << "Endpoint " << static_cast<int>(endpoint_address) << " is not a bulk or interrupt endpoint."; - RunTransferCallback(callback_task_runner, callback, USB_TRANSFER_ERROR, - buffer, 0); + RunTransferCallback(callback_task_runner, callback, + UsbTransferStatus::TRANSFER_ERROR, buffer, 0); return; } @@ -1138,7 +1140,7 @@ void UsbDeviceHandleImpl::TransferComplete(Transfer* transfer, << "Missing transfer completed"; transfers_.erase(transfer); - if (transfer->callback_task_runner()->RunsTasksOnCurrentThread()) { + if (transfer->callback_task_runner()->RunsTasksInCurrentSequence()) { callback.Run(); } else { transfer->callback_task_runner()->PostTask(FROM_HERE, callback); diff --git a/chromium/device/usb/usb_device_handle_impl.h b/chromium/device/usb/usb_device_handle_impl.h index 4d3401aad83..1322e192f0b 100644 --- a/chromium/device/usb/usb_device_handle_impl.h +++ b/chromium/device/usb/usb_device_handle_impl.h @@ -61,9 +61,9 @@ class UsbDeviceHandleImpl : public UsbDeviceHandle { void ResetDevice(const ResultCallback& callback) override; void ClearHalt(uint8_t endpoint, const ResultCallback& callback) override; - void ControlTransfer(UsbEndpointDirection direction, - TransferRequestType request_type, - TransferRecipient recipient, + void ControlTransfer(UsbTransferDirection direction, + UsbControlTransferType request_type, + UsbControlTransferRecipient recipient, uint8_t request, uint16_t value, uint16_t index, @@ -85,7 +85,7 @@ class UsbDeviceHandleImpl : public UsbDeviceHandle { unsigned int timeout, const IsochronousTransferCallback& callback) override; - void GenericTransfer(UsbEndpointDirection direction, + void GenericTransfer(UsbTransferDirection direction, uint8_t endpoint_number, scoped_refptr<net::IOBuffer> buffer, size_t length, @@ -141,9 +141,9 @@ class UsbDeviceHandleImpl : public UsbDeviceHandle { uint8_t endpoint); void ControlTransferInternal( - UsbEndpointDirection direction, - TransferRequestType request_type, - TransferRecipient recipient, + UsbTransferDirection direction, + UsbControlTransferType request_type, + UsbControlTransferRecipient recipient, uint8_t request, uint16_t value, uint16_t index, diff --git a/chromium/device/usb/usb_device_handle_unittest.cc b/chromium/device/usb/usb_device_handle_unittest.cc index 7257570955d..998162fca51 100644 --- a/chromium/device/usb/usb_device_handle_unittest.cc +++ b/chromium/device/usb/usb_device_handle_unittest.cc @@ -12,6 +12,7 @@ #include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/strings/utf_string_conversions.h" +#include "base/test/scoped_task_environment.h" #include "base/test/test_io_thread.h" #include "device/test/test_device_client.h" #include "device/test/usb_test_gadget.h" @@ -25,18 +26,17 @@ namespace { class UsbDeviceHandleTest : public ::testing::Test { public: - void SetUp() override { - message_loop_.reset(new base::MessageLoopForUI); - io_thread_.reset(new base::TestIOThread(base::TestIOThread::kAutoStart)); - device_client_.reset(new TestDeviceClient(io_thread_->task_runner())); - } + UsbDeviceHandleTest() + : io_thread_(base::TestIOThread::kAutoStart), + scoped_task_environment_( + base::test::ScopedTaskEnvironment::MainThreadType::UI) {} protected: - std::unique_ptr<base::TestIOThread> io_thread_; + base::TestIOThread io_thread_; private: - std::unique_ptr<base::MessageLoop> message_loop_; - std::unique_ptr<TestDeviceClient> device_client_; + base::test::ScopedTaskEnvironment scoped_task_environment_; + TestDeviceClient device_client_; }; class TestOpenCallback { @@ -121,7 +121,7 @@ void ExpectTimeoutAndClose(scoped_refptr<UsbDeviceHandle> handle, UsbTransferStatus status, scoped_refptr<net::IOBuffer> buffer, size_t transferred) { - EXPECT_EQ(USB_TRANSFER_TIMEOUT, status); + EXPECT_EQ(UsbTransferStatus::TIMEOUT, status); handle->Close(); quit_closure.Run(); } @@ -132,7 +132,7 @@ TEST_F(UsbDeviceHandleTest, InterruptTransfer) { } std::unique_ptr<UsbTestGadget> gadget = - UsbTestGadget::Claim(io_thread_->task_runner()); + UsbTestGadget::Claim(io_thread_.task_runner()); ASSERT_TRUE(gadget.get()); ASSERT_TRUE(gadget->SetType(UsbTestGadget::ECHO)); @@ -157,7 +157,7 @@ TEST_F(UsbDeviceHandleTest, InterruptTransfer) { scoped_refptr<net::IOBufferWithSize> in_buffer(new net::IOBufferWithSize(64)); TestCompletionCallback in_completion; - handle->GenericTransfer(USB_DIRECTION_INBOUND, 0x81, in_buffer.get(), + handle->GenericTransfer(UsbTransferDirection::INBOUND, 0x81, in_buffer.get(), in_buffer->size(), 5000, // 5 second timeout in_completion.callback()); @@ -169,17 +169,17 @@ TEST_F(UsbDeviceHandleTest, InterruptTransfer) { out_buffer->data()[i] = i; } - handle->GenericTransfer(USB_DIRECTION_OUTBOUND, 0x01, out_buffer.get(), - out_buffer->size(), + handle->GenericTransfer(UsbTransferDirection::OUTBOUND, 0x01, + out_buffer.get(), out_buffer->size(), 5000, // 5 second timeout out_completion.callback()); out_completion.WaitForResult(); - ASSERT_EQ(USB_TRANSFER_COMPLETED, out_completion.status()); + ASSERT_EQ(UsbTransferStatus::COMPLETED, out_completion.status()); EXPECT_EQ(static_cast<size_t>(out_buffer->size()), out_completion.transferred()); in_completion.WaitForResult(); - ASSERT_EQ(USB_TRANSFER_COMPLETED, in_completion.status()); + ASSERT_EQ(UsbTransferStatus::COMPLETED, in_completion.status()); EXPECT_EQ(static_cast<size_t>(in_buffer->size()), in_completion.transferred()); for (size_t i = 0; i < in_completion.transferred(); ++i) { @@ -200,7 +200,7 @@ TEST_F(UsbDeviceHandleTest, BulkTransfer) { } std::unique_ptr<UsbTestGadget> gadget = - UsbTestGadget::Claim(io_thread_->task_runner()); + UsbTestGadget::Claim(io_thread_.task_runner()); ASSERT_TRUE(gadget.get()); ASSERT_TRUE(gadget->SetType(UsbTestGadget::ECHO)); @@ -226,7 +226,7 @@ TEST_F(UsbDeviceHandleTest, BulkTransfer) { scoped_refptr<net::IOBufferWithSize> in_buffer( new net::IOBufferWithSize(512)); TestCompletionCallback in_completion; - handle->GenericTransfer(USB_DIRECTION_INBOUND, 0x82, in_buffer.get(), + handle->GenericTransfer(UsbTransferDirection::INBOUND, 0x82, in_buffer.get(), in_buffer->size(), 5000, // 5 second timeout in_completion.callback()); @@ -238,17 +238,17 @@ TEST_F(UsbDeviceHandleTest, BulkTransfer) { out_buffer->data()[i] = i; } - handle->GenericTransfer(USB_DIRECTION_OUTBOUND, 0x02, out_buffer.get(), - out_buffer->size(), + handle->GenericTransfer(UsbTransferDirection::OUTBOUND, 0x02, + out_buffer.get(), out_buffer->size(), 5000, // 5 second timeout out_completion.callback()); out_completion.WaitForResult(); - ASSERT_EQ(USB_TRANSFER_COMPLETED, out_completion.status()); + ASSERT_EQ(UsbTransferStatus::COMPLETED, out_completion.status()); EXPECT_EQ(static_cast<size_t>(out_buffer->size()), out_completion.transferred()); in_completion.WaitForResult(); - ASSERT_EQ(USB_TRANSFER_COMPLETED, in_completion.status()); + ASSERT_EQ(UsbTransferStatus::COMPLETED, in_completion.status()); EXPECT_EQ(static_cast<size_t>(in_buffer->size()), in_completion.transferred()); for (size_t i = 0; i < in_completion.transferred(); ++i) { @@ -268,7 +268,7 @@ TEST_F(UsbDeviceHandleTest, ControlTransfer) { return; std::unique_ptr<UsbTestGadget> gadget = - UsbTestGadget::Claim(io_thread_->task_runner()); + UsbTestGadget::Claim(io_thread_.task_runner()); ASSERT_TRUE(gadget.get()); TestOpenCallback open_device; @@ -278,11 +278,12 @@ TEST_F(UsbDeviceHandleTest, ControlTransfer) { scoped_refptr<net::IOBufferWithSize> buffer(new net::IOBufferWithSize(255)); TestCompletionCallback completion; - handle->ControlTransfer(USB_DIRECTION_INBOUND, UsbDeviceHandle::STANDARD, - UsbDeviceHandle::DEVICE, 0x06, 0x0301, 0x0409, buffer, - buffer->size(), 0, completion.callback()); + handle->ControlTransfer( + UsbTransferDirection::INBOUND, UsbControlTransferType::STANDARD, + UsbControlTransferRecipient::DEVICE, 0x06, 0x0301, 0x0409, buffer, + buffer->size(), 0, completion.callback()); completion.WaitForResult(); - ASSERT_EQ(USB_TRANSFER_COMPLETED, completion.status()); + ASSERT_EQ(UsbTransferStatus::COMPLETED, completion.status()); const char expected_str[] = "\x18\x03G\0o\0o\0g\0l\0e\0 \0I\0n\0c\0.\0"; EXPECT_EQ(sizeof(expected_str) - 1, completion.transferred()); for (size_t i = 0; i < completion.transferred(); ++i) { @@ -299,7 +300,7 @@ TEST_F(UsbDeviceHandleTest, SetInterfaceAlternateSetting) { } std::unique_ptr<UsbTestGadget> gadget = - UsbTestGadget::Claim(io_thread_->task_runner()); + UsbTestGadget::Claim(io_thread_.task_runner()); ASSERT_TRUE(gadget.get()); ASSERT_TRUE(gadget->SetType(UsbTestGadget::ECHO)); @@ -329,7 +330,7 @@ TEST_F(UsbDeviceHandleTest, CancelOnClose) { } std::unique_ptr<UsbTestGadget> gadget = - UsbTestGadget::Claim(io_thread_->task_runner()); + UsbTestGadget::Claim(io_thread_.task_runner()); ASSERT_TRUE(gadget.get()); ASSERT_TRUE(gadget->SetType(UsbTestGadget::ECHO)); @@ -344,14 +345,14 @@ TEST_F(UsbDeviceHandleTest, CancelOnClose) { scoped_refptr<net::IOBufferWithSize> buffer(new net::IOBufferWithSize(512)); TestCompletionCallback completion; - handle->GenericTransfer(USB_DIRECTION_INBOUND, 0x82, buffer.get(), + handle->GenericTransfer(UsbTransferDirection::INBOUND, 0x82, buffer.get(), buffer->size(), 5000, // 5 second timeout completion.callback()); handle->Close(); completion.WaitForResult(); - ASSERT_EQ(USB_TRANSFER_CANCELLED, completion.status()); + ASSERT_EQ(UsbTransferStatus::CANCELLED, completion.status()); } TEST_F(UsbDeviceHandleTest, CancelOnDisconnect) { @@ -360,7 +361,7 @@ TEST_F(UsbDeviceHandleTest, CancelOnDisconnect) { } std::unique_ptr<UsbTestGadget> gadget = - UsbTestGadget::Claim(io_thread_->task_runner()); + UsbTestGadget::Claim(io_thread_.task_runner()); ASSERT_TRUE(gadget.get()); ASSERT_TRUE(gadget->SetType(UsbTestGadget::ECHO)); @@ -375,14 +376,14 @@ TEST_F(UsbDeviceHandleTest, CancelOnDisconnect) { scoped_refptr<net::IOBufferWithSize> buffer(new net::IOBufferWithSize(512)); TestCompletionCallback completion; - handle->GenericTransfer(USB_DIRECTION_INBOUND, 0x82, buffer.get(), + handle->GenericTransfer(UsbTransferDirection::INBOUND, 0x82, buffer.get(), buffer->size(), 5000, // 5 second timeout completion.callback()); ASSERT_TRUE(gadget->Disconnect()); completion.WaitForResult(); - ASSERT_EQ(USB_TRANSFER_DISCONNECT, completion.status()); + ASSERT_EQ(UsbTransferStatus::DISCONNECT, completion.status()); handle->Close(); } @@ -393,7 +394,7 @@ TEST_F(UsbDeviceHandleTest, Timeout) { } std::unique_ptr<UsbTestGadget> gadget = - UsbTestGadget::Claim(io_thread_->task_runner()); + UsbTestGadget::Claim(io_thread_.task_runner()); ASSERT_TRUE(gadget.get()); ASSERT_TRUE(gadget->SetType(UsbTestGadget::ECHO)); @@ -408,13 +409,13 @@ TEST_F(UsbDeviceHandleTest, Timeout) { scoped_refptr<net::IOBufferWithSize> buffer(new net::IOBufferWithSize(512)); TestCompletionCallback completion; - handle->GenericTransfer(USB_DIRECTION_INBOUND, 0x82, buffer.get(), + handle->GenericTransfer(UsbTransferDirection::INBOUND, 0x82, buffer.get(), buffer->size(), 10, // 10 millisecond timeout completion.callback()); completion.WaitForResult(); - ASSERT_EQ(USB_TRANSFER_TIMEOUT, completion.status()); + ASSERT_EQ(UsbTransferStatus::TIMEOUT, completion.status()); handle->Close(); } @@ -424,7 +425,7 @@ TEST_F(UsbDeviceHandleTest, CloseReentrancy) { return; std::unique_ptr<UsbTestGadget> gadget = - UsbTestGadget::Claim(io_thread_->task_runner()); + UsbTestGadget::Claim(io_thread_.task_runner()); ASSERT_TRUE(gadget.get()); ASSERT_TRUE(gadget->SetType(UsbTestGadget::ECHO)); @@ -438,9 +439,9 @@ TEST_F(UsbDeviceHandleTest, CloseReentrancy) { ASSERT_TRUE(claim_interface.WaitForResult()); base::RunLoop run_loop; - auto buffer = base::MakeShared<net::IOBufferWithSize>(512); + auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(512); handle->GenericTransfer( - USB_DIRECTION_INBOUND, 0x82, buffer.get(), buffer->size(), + UsbTransferDirection::INBOUND, 0x82, buffer.get(), buffer->size(), 10, // 10 millisecond timeout base::Bind(&ExpectTimeoutAndClose, handle, run_loop.QuitClosure())); // Drop handle so that the completion callback holds the last reference. diff --git a/chromium/device/usb/usb_device_handle_usbfs.cc b/chromium/device/usb/usb_device_handle_usbfs.cc index 047fb24b4bb..37b3bb1c132 100644 --- a/chromium/device/usb/usb_device_handle_usbfs.cc +++ b/chromium/device/usb/usb_device_handle_usbfs.cc @@ -32,41 +32,41 @@ namespace device { namespace { -uint8_t ConvertEndpointDirection(UsbEndpointDirection direction) { +uint8_t ConvertEndpointDirection(UsbTransferDirection direction) { switch (direction) { - case USB_DIRECTION_INBOUND: + case UsbTransferDirection::INBOUND: return USB_DIR_IN; - case USB_DIRECTION_OUTBOUND: + case UsbTransferDirection::OUTBOUND: return USB_DIR_OUT; } NOTREACHED(); return 0; } -uint8_t ConvertRequestType(UsbDeviceHandle::TransferRequestType request_type) { +uint8_t ConvertRequestType(UsbControlTransferType request_type) { switch (request_type) { - case UsbDeviceHandle::STANDARD: + case UsbControlTransferType::STANDARD: return USB_TYPE_STANDARD; - case UsbDeviceHandle::CLASS: + case UsbControlTransferType::CLASS: return USB_TYPE_CLASS; - case UsbDeviceHandle::VENDOR: + case UsbControlTransferType::VENDOR: return USB_TYPE_VENDOR; - case UsbDeviceHandle::RESERVED: + case UsbControlTransferType::RESERVED: return USB_TYPE_RESERVED; } NOTREACHED(); return 0; } -uint8_t ConvertRecipient(UsbDeviceHandle::TransferRecipient recipient) { +uint8_t ConvertRecipient(UsbControlTransferRecipient recipient) { switch (recipient) { - case UsbDeviceHandle::DEVICE: + case UsbControlTransferRecipient::DEVICE: return USB_RECIP_DEVICE; - case UsbDeviceHandle::INTERFACE: + case UsbControlTransferRecipient::INTERFACE: return USB_RECIP_INTERFACE; - case UsbDeviceHandle::ENDPOINT: + case UsbControlTransferRecipient::ENDPOINT: return USB_RECIP_ENDPOINT; - case UsbDeviceHandle::OTHER: + case UsbControlTransferRecipient::OTHER: return USB_RECIP_OTHER; } NOTREACHED(); @@ -74,9 +74,9 @@ uint8_t ConvertRecipient(UsbDeviceHandle::TransferRecipient recipient) { } scoped_refptr<net::IOBuffer> BuildControlTransferBuffer( - UsbEndpointDirection direction, - UsbDeviceHandle::TransferRequestType request_type, - UsbDeviceHandle::TransferRecipient recipient, + UsbTransferDirection direction, + UsbControlTransferType request_type, + UsbControlTransferRecipient recipient, uint8_t request, uint16_t value, uint16_t index, @@ -100,13 +100,13 @@ scoped_refptr<net::IOBuffer> BuildControlTransferBuffer( uint8_t ConvertTransferType(UsbTransferType type) { switch (type) { - case USB_TRANSFER_CONTROL: + case UsbTransferType::CONTROL: return USBDEVFS_URB_TYPE_CONTROL; - case USB_TRANSFER_ISOCHRONOUS: + case UsbTransferType::ISOCHRONOUS: return USBDEVFS_URB_TYPE_ISO; - case USB_TRANSFER_BULK: + case UsbTransferType::BULK: return USBDEVFS_URB_TYPE_BULK; - case USB_TRANSFER_INTERRUPT: + case UsbTransferType::INTERRUPT: return USBDEVFS_URB_TYPE_INTERRUPT; } NOTREACHED(); @@ -116,19 +116,19 @@ uint8_t ConvertTransferType(UsbTransferType type) { UsbTransferStatus ConvertTransferResult(int rc) { switch (rc) { case 0: - return USB_TRANSFER_COMPLETED; + return UsbTransferStatus::COMPLETED; case EPIPE: - return USB_TRANSFER_STALLED; + return UsbTransferStatus::STALLED; case ENODEV: case ESHUTDOWN: case EPROTO: - return USB_TRANSFER_DISCONNECT; + return UsbTransferStatus::DISCONNECT; default: // TODO(reillyg): Add a specific error message whenever one of the cases // above fails to match. USB_LOG(ERROR) << "Unknown system error: " << logging::SystemErrorCodeToString(rc); - return USB_TRANSFER_ERROR; + return UsbTransferStatus::TRANSFER_ERROR; } } @@ -436,7 +436,7 @@ void UsbDeviceHandleUsbfs::Close() { // reference to this object so hold a reference for the rest of this method. scoped_refptr<UsbDeviceHandleUsbfs> self(this); for (const auto& transfer : transfers_) - CancelTransfer(transfer.get(), USB_TRANSFER_CANCELLED); + CancelTransfer(transfer.get(), UsbTransferStatus::CANCELLED); // On the |task_runner_| thread check |device_| to see if the handle is // closed. On the |blocking_task_runner_| thread check |fd_.is_valid()| to @@ -562,20 +562,22 @@ void UsbDeviceHandleUsbfs::ClearHalt(uint8_t endpoint_address, base::Unretained(helper_.get()), endpoint_address, callback)); } -void UsbDeviceHandleUsbfs::ControlTransfer(UsbEndpointDirection direction, - TransferRequestType request_type, - TransferRecipient recipient, - uint8_t request, - uint16_t value, - uint16_t index, - scoped_refptr<net::IOBuffer> buffer, - size_t length, - unsigned int timeout, - const TransferCallback& callback) { +void UsbDeviceHandleUsbfs::ControlTransfer( + UsbTransferDirection direction, + UsbControlTransferType request_type, + UsbControlTransferRecipient recipient, + uint8_t request, + uint16_t value, + uint16_t index, + scoped_refptr<net::IOBuffer> buffer, + size_t length, + unsigned int timeout, + const TransferCallback& callback) { DCHECK(sequence_checker_.CalledOnValidSequence()); if (!device_) { task_runner_->PostTask( - FROM_HERE, base::Bind(callback, USB_TRANSFER_DISCONNECT, nullptr, 0)); + FROM_HERE, + base::Bind(callback, UsbTransferStatus::DISCONNECT, nullptr, 0)); return; } @@ -631,7 +633,7 @@ void UsbDeviceHandleUsbfs::IsochronousTransferOut( packet_lengths, timeout, callback); } -void UsbDeviceHandleUsbfs::GenericTransfer(UsbEndpointDirection direction, +void UsbDeviceHandleUsbfs::GenericTransfer(UsbTransferDirection direction, uint8_t endpoint_number, scoped_refptr<net::IOBuffer> buffer, size_t length, @@ -707,7 +709,8 @@ void UsbDeviceHandleUsbfs::IsochronousTransferInternal( const IsochronousTransferCallback& callback) { DCHECK(sequence_checker_.CalledOnValidSequence()); if (!device_) { - ReportIsochronousError(packet_lengths, callback, USB_TRANSFER_DISCONNECT); + ReportIsochronousError(packet_lengths, callback, + UsbTransferStatus::DISCONNECT); return; } @@ -715,7 +718,8 @@ void UsbDeviceHandleUsbfs::IsochronousTransferInternal( if (it == endpoints_.end()) { USB_LOG(USER) << "Endpoint address " << static_cast<int>(endpoint_address) << " is not part of a claimed interface."; - ReportIsochronousError(packet_lengths, callback, USB_TRANSFER_ERROR); + ReportIsochronousError(packet_lengths, callback, + UsbTransferStatus::TRANSFER_ERROR); return; } @@ -744,7 +748,7 @@ void UsbDeviceHandleUsbfs::IsochronousTransferInternal( } void UsbDeviceHandleUsbfs::GenericTransferInternal( - UsbEndpointDirection direction, + UsbTransferDirection direction, uint8_t endpoint_number, scoped_refptr<net::IOBuffer> buffer, size_t length, @@ -754,7 +758,8 @@ void UsbDeviceHandleUsbfs::GenericTransferInternal( DCHECK(sequence_checker_.CalledOnValidSequence()); if (!device_) { callback_runner->PostTask( - FROM_HERE, base::Bind(callback, USB_TRANSFER_DISCONNECT, nullptr, 0)); + FROM_HERE, + base::Bind(callback, UsbTransferStatus::DISCONNECT, nullptr, 0)); return; } @@ -765,7 +770,8 @@ void UsbDeviceHandleUsbfs::GenericTransferInternal( USB_LOG(USER) << "Endpoint address " << static_cast<int>(endpoint_address) << " is not part of a claimed interface."; callback_runner->PostTask( - FROM_HERE, base::Bind(callback, USB_TRANSFER_ERROR, nullptr, 0)); + FROM_HERE, + base::Bind(callback, UsbTransferStatus::TRANSFER_ERROR, nullptr, 0)); return; } @@ -898,7 +904,7 @@ void UsbDeviceHandleUsbfs::SetUpTimeoutCallback(Transfer* transfer, } void UsbDeviceHandleUsbfs::OnTimeout(Transfer* transfer) { - CancelTransfer(transfer, USB_TRANSFER_TIMEOUT); + CancelTransfer(transfer, UsbTransferStatus::TIMEOUT); } std::unique_ptr<UsbDeviceHandleUsbfs::Transfer> diff --git a/chromium/device/usb/usb_device_handle_usbfs.h b/chromium/device/usb/usb_device_handle_usbfs.h index 34070c1b3f5..e8aa0637383 100644 --- a/chromium/device/usb/usb_device_handle_usbfs.h +++ b/chromium/device/usb/usb_device_handle_usbfs.h @@ -50,9 +50,9 @@ class UsbDeviceHandleUsbfs : public UsbDeviceHandle { const ResultCallback& callback) override; void ResetDevice(const ResultCallback& callback) override; void ClearHalt(uint8_t endpoint, const ResultCallback& callback) override; - void ControlTransfer(UsbEndpointDirection direction, - TransferRequestType request_type, - TransferRecipient recipient, + void ControlTransfer(UsbTransferDirection direction, + UsbControlTransferType request_type, + UsbControlTransferRecipient recipient, uint8_t request, uint16_t value, uint16_t index, @@ -73,7 +73,7 @@ class UsbDeviceHandleUsbfs : public UsbDeviceHandle { const IsochronousTransferCallback& callback) override; // To support DevTools this function may be called from any thread and on // completion |callback| will be run on that thread. - void GenericTransfer(UsbEndpointDirection direction, + void GenericTransfer(UsbTransferDirection direction, uint8_t endpoint_number, scoped_refptr<net::IOBuffer> buffer, size_t length, @@ -119,7 +119,7 @@ class UsbDeviceHandleUsbfs : public UsbDeviceHandle { unsigned int timeout, const IsochronousTransferCallback& callback); void GenericTransferInternal( - UsbEndpointDirection direction, + UsbTransferDirection direction, uint8_t endpoint_number, scoped_refptr<net::IOBuffer> buffer, size_t length, diff --git a/chromium/device/usb/usb_device_handle_win.cc b/chromium/device/usb/usb_device_handle_win.cc index 74a7de63bd7..f8a54a28a38 100644 --- a/chromium/device/usb/usb_device_handle_win.cc +++ b/chromium/device/usb/usb_device_handle_win.cc @@ -158,9 +158,9 @@ void UsbDeviceHandleWin::ClearHalt(uint8_t endpoint, } } -void UsbDeviceHandleWin::ControlTransfer(UsbEndpointDirection direction, - TransferRequestType request_type, - TransferRecipient recipient, +void UsbDeviceHandleWin::ControlTransfer(UsbTransferDirection direction, + UsbControlTransferType request_type, + UsbControlTransferRecipient recipient, uint8_t request, uint16_t value, uint16_t index, @@ -172,14 +172,15 @@ void UsbDeviceHandleWin::ControlTransfer(UsbEndpointDirection direction, if (!device_) { task_runner_->PostTask( - FROM_HERE, base::Bind(callback, USB_TRANSFER_DISCONNECT, nullptr, 0)); + FROM_HERE, + base::Bind(callback, UsbTransferStatus::DISCONNECT, nullptr, 0)); return; } if (hub_handle_.IsValid()) { - if (direction == USB_DIRECTION_INBOUND && - request_type == TransferRequestType::STANDARD && - recipient == TransferRecipient::DEVICE && + if (direction == UsbTransferDirection::INBOUND && + request_type == UsbControlTransferType::STANDARD && + recipient == UsbControlTransferRecipient::DEVICE && request == USB_REQUEST_GET_DESCRIPTOR) { if ((value >> 8) == USB_DEVICE_DESCRIPTOR_TYPE) { auto* node_connection_info = new USB_NODE_CONNECTION_INFORMATION_EX; @@ -225,13 +226,15 @@ void UsbDeviceHandleWin::ControlTransfer(UsbEndpointDirection direction, // Unsupported transfer for hub. task_runner_->PostTask( - FROM_HERE, base::Bind(callback, USB_TRANSFER_ERROR, nullptr, 0)); + FROM_HERE, + base::Bind(callback, UsbTransferStatus::TRANSFER_ERROR, nullptr, 0)); return; } // Regular control transfers unimplemented. - task_runner_->PostTask(FROM_HERE, - base::Bind(callback, USB_TRANSFER_ERROR, nullptr, 0)); + task_runner_->PostTask( + FROM_HERE, + base::Bind(callback, UsbTransferStatus::TRANSFER_ERROR, nullptr, 0)); } void UsbDeviceHandleWin::IsochronousTransferIn( @@ -251,7 +254,7 @@ void UsbDeviceHandleWin::IsochronousTransferOut( DCHECK(thread_checker_.CalledOnValidThread()); } -void UsbDeviceHandleWin::GenericTransfer(UsbEndpointDirection direction, +void UsbDeviceHandleWin::GenericTransfer(UsbTransferDirection direction, uint8_t endpoint_number, scoped_refptr<net::IOBuffer> buffer, size_t length, @@ -310,7 +313,7 @@ void UsbDeviceHandleWin::GotNodeConnectionInformation( if (win32_result != ERROR_SUCCESS) { SetLastError(win32_result); USB_PLOG(ERROR) << "Failed to get node connection information"; - callback.Run(USB_TRANSFER_ERROR, nullptr, 0); + callback.Run(UsbTransferStatus::TRANSFER_ERROR, nullptr, 0); return; } @@ -318,7 +321,7 @@ void UsbDeviceHandleWin::GotNodeConnectionInformation( bytes_transferred = std::min(sizeof(USB_DEVICE_DESCRIPTOR), buffer_length); memcpy(buffer->data(), &node_connection_info->DeviceDescriptor, bytes_transferred); - callback.Run(USB_TRANSFER_COMPLETED, buffer, bytes_transferred); + callback.Run(UsbTransferStatus::COMPLETED, buffer, bytes_transferred); } void UsbDeviceHandleWin::GotDescriptorFromNodeConnection( @@ -334,7 +337,7 @@ void UsbDeviceHandleWin::GotDescriptorFromNodeConnection( if (win32_result != ERROR_SUCCESS) { SetLastError(win32_result); USB_PLOG(ERROR) << "Failed to read descriptor from node connection"; - callback.Run(USB_TRANSFER_ERROR, nullptr, 0); + callback.Run(UsbTransferStatus::TRANSFER_ERROR, nullptr, 0); return; } @@ -343,7 +346,8 @@ void UsbDeviceHandleWin::GotDescriptorFromNodeConnection( memcpy(original_buffer->data(), request_buffer->data() + sizeof(USB_DESCRIPTOR_REQUEST), bytes_transferred); - callback.Run(USB_TRANSFER_COMPLETED, original_buffer, bytes_transferred); + callback.Run(UsbTransferStatus::COMPLETED, original_buffer, + bytes_transferred); } } // namespace device diff --git a/chromium/device/usb/usb_device_handle_win.h b/chromium/device/usb/usb_device_handle_win.h index 69e6e28e315..75b65f644f5 100644 --- a/chromium/device/usb/usb_device_handle_win.h +++ b/chromium/device/usb/usb_device_handle_win.h @@ -46,9 +46,9 @@ class UsbDeviceHandleWin : public UsbDeviceHandle { void ResetDevice(const ResultCallback& callback) override; void ClearHalt(uint8_t endpoint, const ResultCallback& callback) override; - void ControlTransfer(UsbEndpointDirection direction, - TransferRequestType request_type, - TransferRecipient recipient, + void ControlTransfer(UsbTransferDirection direction, + UsbControlTransferType request_type, + UsbControlTransferRecipient recipient, uint8_t request, uint16_t value, uint16_t index, @@ -70,7 +70,7 @@ class UsbDeviceHandleWin : public UsbDeviceHandle { unsigned int timeout, const IsochronousTransferCallback& callback) override; - void GenericTransfer(UsbEndpointDirection direction, + void GenericTransfer(UsbTransferDirection direction, uint8_t endpoint_number, scoped_refptr<net::IOBuffer> buffer, size_t length, diff --git a/chromium/device/usb/usb_device_impl.cc b/chromium/device/usb/usb_device_impl.cc index b686efc3dbd..bdda9ca9ee3 100644 --- a/chromium/device/usb/usb_device_impl.cc +++ b/chromium/device/usb/usb_device_impl.cc @@ -15,6 +15,7 @@ #include "base/sequenced_task_runner.h" #include "base/single_thread_task_runner.h" #include "base/stl_util.h" +#include "base/threading/thread_restrictions.h" #include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" #include "components/device_event_log/device_event_log.h" @@ -22,15 +23,14 @@ #include "device/usb/usb_descriptors.h" #include "device/usb/usb_device_handle_impl.h" #include "device/usb/usb_error.h" +#include "device/usb/usb_service.h" #include "third_party/libusb/src/libusb/libusb.h" namespace device { -UsbDeviceImpl::UsbDeviceImpl( - scoped_refptr<UsbContext> context, - PlatformUsbDevice platform_device, - const libusb_device_descriptor& descriptor, - scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) +UsbDeviceImpl::UsbDeviceImpl(scoped_refptr<UsbContext> context, + PlatformUsbDevice platform_device, + const libusb_device_descriptor& descriptor) : UsbDevice(descriptor.bcdUSB, descriptor.bDeviceClass, descriptor.bDeviceSubClass, @@ -42,9 +42,7 @@ UsbDeviceImpl::UsbDeviceImpl( base::string16(), base::string16()), platform_device_(platform_device), - context_(context), - task_runner_(base::ThreadTaskRunnerHandle::Get()), - blocking_task_runner_(blocking_task_runner) { + context_(context) { CHECK(platform_device) << "platform_device cannot be NULL"; libusb_ref_device(platform_device); ReadAllConfigurations(); @@ -59,9 +57,12 @@ UsbDeviceImpl::~UsbDeviceImpl() { void UsbDeviceImpl::Open(const OpenCallback& callback) { DCHECK(thread_checker_.CalledOnValidThread()); - blocking_task_runner_->PostTask( + scoped_refptr<base::SequencedTaskRunner> blocking_task_runner = + UsbService::CreateBlockingTaskRunner(); + blocking_task_runner->PostTask( FROM_HERE, - base::Bind(&UsbDeviceImpl::OpenOnBlockingThread, this, callback)); + base::Bind(&UsbDeviceImpl::OpenOnBlockingThread, this, callback, + base::ThreadTaskRunnerHandle::Get(), blocking_task_runner)); } void UsbDeviceImpl::ReadAllConfigurations() { @@ -99,24 +100,31 @@ void UsbDeviceImpl::RefreshActiveConfiguration() { ActiveConfigurationChanged(config_value); } -void UsbDeviceImpl::OpenOnBlockingThread(const OpenCallback& callback) { +void UsbDeviceImpl::OpenOnBlockingThread( + const OpenCallback& callback, + scoped_refptr<base::TaskRunner> task_runner, + scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) { + base::ThreadRestrictions::AssertIOAllowed(); PlatformUsbDeviceHandle handle; const int rv = libusb_open(platform_device_, &handle); if (LIBUSB_SUCCESS == rv) { - task_runner_->PostTask( - FROM_HERE, base::Bind(&UsbDeviceImpl::Opened, this, handle, callback)); + task_runner->PostTask( + FROM_HERE, base::Bind(&UsbDeviceImpl::Opened, this, handle, callback, + blocking_task_runner)); } else { USB_LOG(EVENT) << "Failed to open device: " << ConvertPlatformUsbErrorToString(rv); - task_runner_->PostTask(FROM_HERE, base::Bind(callback, nullptr)); + task_runner->PostTask(FROM_HERE, base::Bind(callback, nullptr)); } } -void UsbDeviceImpl::Opened(PlatformUsbDeviceHandle platform_handle, - const OpenCallback& callback) { +void UsbDeviceImpl::Opened( + PlatformUsbDeviceHandle platform_handle, + const OpenCallback& callback, + scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) { DCHECK(thread_checker_.CalledOnValidThread()); scoped_refptr<UsbDeviceHandle> device_handle = new UsbDeviceHandleImpl( - context_, this, platform_handle, blocking_task_runner_); + context_, this, platform_handle, blocking_task_runner); handles().push_back(device_handle.get()); callback.Run(device_handle); } diff --git a/chromium/device/usb/usb_device_impl.h b/chromium/device/usb/usb_device_impl.h index 7457501636c..0447f885d2c 100644 --- a/chromium/device/usb/usb_device_impl.h +++ b/chromium/device/usb/usb_device_impl.h @@ -19,7 +19,6 @@ #include "build/build_config.h" #include "device/usb/usb_descriptors.h" #include "device/usb/usb_device.h" -#include "device/usb/webusb_descriptors.h" struct libusb_device; struct libusb_device_descriptor; @@ -55,10 +54,6 @@ class UsbDeviceImpl : public UsbDevice { void set_serial_number(const base::string16& value) { serial_number_ = value; } - void set_webusb_allowed_origins( - std::unique_ptr<WebUsbAllowedOrigins> allowed_origins) { - webusb_allowed_origins_ = std::move(allowed_origins); - } void set_webusb_landing_page(const GURL& url) { webusb_landing_page_ = url; } PlatformUsbDevice platform_device() const { return platform_device_; } @@ -70,8 +65,7 @@ class UsbDeviceImpl : public UsbDevice { // Called by UsbServiceImpl only; UsbDeviceImpl(scoped_refptr<UsbContext> context, PlatformUsbDevice platform_device, - const libusb_device_descriptor& descriptor, - scoped_refptr<base::SequencedTaskRunner> blocking_task_runner); + const libusb_device_descriptor& descriptor); ~UsbDeviceImpl() override; @@ -84,9 +78,13 @@ class UsbDeviceImpl : public UsbDevice { private: void GetAllConfigurations(); - void OpenOnBlockingThread(const OpenCallback& callback); + void OpenOnBlockingThread( + const OpenCallback& callback, + scoped_refptr<base::TaskRunner> task_runner, + scoped_refptr<base::SequencedTaskRunner> blocking_task_runner); void Opened(PlatformUsbDeviceHandle platform_handle, - const OpenCallback& callback); + const OpenCallback& callback, + scoped_refptr<base::SequencedTaskRunner> blocking_task_runner); base::ThreadChecker thread_checker_; PlatformUsbDevice platform_device_; @@ -95,9 +93,6 @@ class UsbDeviceImpl : public UsbDevice { // Retain the context so that it will not be released before UsbDevice. scoped_refptr<UsbContext> context_; - scoped_refptr<base::SequencedTaskRunner> task_runner_; - scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_; - DISALLOW_COPY_AND_ASSIGN(UsbDeviceImpl); }; diff --git a/chromium/device/usb/usb_device_linux.cc b/chromium/device/usb/usb_device_linux.cc index 08a3329162a..dc423de1020 100644 --- a/chromium/device/usb/usb_device_linux.cc +++ b/chromium/device/usb/usb_device_linux.cc @@ -18,7 +18,7 @@ #include "components/device_event_log/device_event_log.h" #include "device/usb/usb_descriptors.h" #include "device/usb/usb_device_handle_usbfs.h" -#include "device/usb/usb_error.h" +#include "device/usb/usb_service.h" #if defined(OS_CHROMEOS) #include "chromeos/dbus/dbus_thread_manager.h" @@ -27,21 +27,17 @@ namespace device { -UsbDeviceLinux::UsbDeviceLinux( - const std::string& device_path, - const UsbDeviceDescriptor& descriptor, - const std::string& manufacturer_string, - const std::string& product_string, - const std::string& serial_number, - uint8_t active_configuration, - scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) +UsbDeviceLinux::UsbDeviceLinux(const std::string& device_path, + const UsbDeviceDescriptor& descriptor, + const std::string& manufacturer_string, + const std::string& product_string, + const std::string& serial_number, + uint8_t active_configuration) : UsbDevice(descriptor, base::UTF8ToUTF16(manufacturer_string), base::UTF8ToUTF16(product_string), base::UTF8ToUTF16(serial_number)), - device_path_(device_path), - task_runner_(base::ThreadTaskRunnerHandle::Get()), - blocking_task_runner_(blocking_task_runner) { + device_path_(device_path) { ActiveConfigurationChanged(active_configuration); } @@ -50,7 +46,7 @@ UsbDeviceLinux::~UsbDeviceLinux() {} #if defined(OS_CHROMEOS) void UsbDeviceLinux::CheckUsbAccess(const ResultCallback& callback) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(sequence_checker_.CalledOnValidSequence()); chromeos::PermissionBrokerClient* client = chromeos::DBusThreadManager::Get()->GetPermissionBrokerClient(); DCHECK(client) << "Could not get permission broker client."; @@ -60,7 +56,7 @@ void UsbDeviceLinux::CheckUsbAccess(const ResultCallback& callback) { #endif // defined(OS_CHROMEOS) void UsbDeviceLinux::Open(const OpenCallback& callback) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(sequence_checker_.CalledOnValidSequence()); #if defined(OS_CHROMEOS) chromeos::PermissionBrokerClient* client = @@ -71,9 +67,12 @@ void UsbDeviceLinux::Open(const OpenCallback& callback) { base::Bind(&UsbDeviceLinux::OnOpenRequestComplete, this, callback), base::Bind(&UsbDeviceLinux::OnOpenRequestError, this, callback)); #else - blocking_task_runner_->PostTask( + scoped_refptr<base::SequencedTaskRunner> blocking_task_runner = + UsbService::CreateBlockingTaskRunner(); + blocking_task_runner->PostTask( FROM_HERE, - base::Bind(&UsbDeviceLinux::OpenOnBlockingThread, this, callback)); + base::Bind(&UsbDeviceLinux::OpenOnBlockingThread, this, callback, + base::ThreadTaskRunnerHandle::Get(), blocking_task_runner)); #endif // defined(OS_CHROMEOS) } @@ -86,7 +85,7 @@ void UsbDeviceLinux::OnOpenRequestComplete(const OpenCallback& callback, callback.Run(nullptr); return; } - Opened(std::move(fd), callback); + Opened(std::move(fd), callback, UsbService::CreateBlockingTaskRunner()); } void UsbDeviceLinux::OnOpenRequestError(const OpenCallback& callback, @@ -99,23 +98,30 @@ void UsbDeviceLinux::OnOpenRequestError(const OpenCallback& callback, #else -void UsbDeviceLinux::OpenOnBlockingThread(const OpenCallback& callback) { +void UsbDeviceLinux::OpenOnBlockingThread( + const OpenCallback& callback, + scoped_refptr<base::SequencedTaskRunner> task_runner, + scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) { base::ScopedFD fd(HANDLE_EINTR(open(device_path_.c_str(), O_RDWR))); if (fd.is_valid()) { - task_runner_->PostTask(FROM_HERE, base::Bind(&UsbDeviceLinux::Opened, this, - base::Passed(&fd), callback)); + task_runner->PostTask( + FROM_HERE, base::Bind(&UsbDeviceLinux::Opened, this, base::Passed(&fd), + callback, blocking_task_runner)); } else { USB_PLOG(EVENT) << "Failed to open " << device_path_; - task_runner_->PostTask(FROM_HERE, base::Bind(callback, nullptr)); + task_runner->PostTask(FROM_HERE, base::Bind(callback, nullptr)); } } #endif // defined(OS_CHROMEOS) -void UsbDeviceLinux::Opened(base::ScopedFD fd, const OpenCallback& callback) { - DCHECK(thread_checker_.CalledOnValidThread()); +void UsbDeviceLinux::Opened( + base::ScopedFD fd, + const OpenCallback& callback, + scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) { + DCHECK(sequence_checker_.CalledOnValidSequence()); scoped_refptr<UsbDeviceHandle> device_handle = - new UsbDeviceHandleUsbfs(this, std::move(fd), blocking_task_runner_); + new UsbDeviceHandleUsbfs(this, std::move(fd), blocking_task_runner); handles().push_back(device_handle.get()); callback.Run(device_handle); } diff --git a/chromium/device/usb/usb_device_linux.h b/chromium/device/usb/usb_device_linux.h index 92a19c37faf..6b6888f074a 100644 --- a/chromium/device/usb/usb_device_linux.h +++ b/chromium/device/usb/usb_device_linux.h @@ -12,10 +12,9 @@ #include "base/files/scoped_file.h" #include "base/macros.h" -#include "base/threading/thread_checker.h" +#include "base/sequence_checker.h" #include "build/build_config.h" #include "device/usb/usb_device.h" -#include "device/usb/webusb_descriptors.h" namespace base { class SequencedTaskRunner; @@ -37,10 +36,6 @@ class UsbDeviceLinux : public UsbDevice { // These functions are used during enumeration only. The values must not // change during the object's lifetime. - void set_webusb_allowed_origins( - std::unique_ptr<WebUsbAllowedOrigins> allowed_origins) { - webusb_allowed_origins_ = std::move(allowed_origins); - } void set_webusb_landing_page(const GURL& url) { webusb_landing_page_ = url; } protected: @@ -52,8 +47,7 @@ class UsbDeviceLinux : public UsbDevice { const std::string& manufacturer_string, const std::string& product_string, const std::string& serial_number, - uint8_t active_configuration, - scoped_refptr<base::SequencedTaskRunner> blocking_task_runner); + uint8_t active_configuration); ~UsbDeviceLinux() override; @@ -64,17 +58,19 @@ class UsbDeviceLinux : public UsbDevice { const std::string& error_name, const std::string& error_message); #else - void OpenOnBlockingThread(const OpenCallback& callback); + void OpenOnBlockingThread( + const OpenCallback& callback, + scoped_refptr<base::SequencedTaskRunner> task_runner, + scoped_refptr<base::SequencedTaskRunner> blocking_task_runner); #endif // defined(OS_CHROMEOS) - void Opened(base::ScopedFD fd, const OpenCallback& callback); + void Opened(base::ScopedFD fd, + const OpenCallback& callback, + scoped_refptr<base::SequencedTaskRunner> blocking_task_runner); - base::ThreadChecker thread_checker_; + base::SequenceChecker sequence_checker_; const std::string device_path_; - scoped_refptr<base::SequencedTaskRunner> task_runner_; - scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_; - DISALLOW_COPY_AND_ASSIGN(UsbDeviceLinux); }; diff --git a/chromium/device/usb/usb_service.cc b/chromium/device/usb/usb_service.cc index b560cd0c364..5aaf9879748 100644 --- a/chromium/device/usb/usb_service.cc +++ b/chromium/device/usb/usb_service.cc @@ -8,6 +8,7 @@ #include "base/feature_list.h" #include "base/location.h" #include "base/memory/ptr_util.h" +#include "base/task_scheduler/post_task.h" #include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" #include "components/device_event_log/device_event_log.h" @@ -42,31 +43,34 @@ void UsbService::Observer::OnDeviceRemovedCleanup( void UsbService::Observer::WillDestroyUsbService() {} +// Declare storage for this constexpr. +constexpr base::TaskTraits UsbService::kBlockingTaskTraits; + // static -std::unique_ptr<UsbService> UsbService::Create( - scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) { +std::unique_ptr<UsbService> UsbService::Create() { #if defined(OS_ANDROID) - return base::WrapUnique(new UsbServiceAndroid(blocking_task_runner)); + return base::WrapUnique(new UsbServiceAndroid()); #elif defined(USE_UDEV) - return base::WrapUnique(new UsbServiceLinux(blocking_task_runner)); + return base::WrapUnique(new UsbServiceLinux()); #elif defined(OS_WIN) if (base::FeatureList::IsEnabled(kNewUsbBackend)) - return base::WrapUnique(new UsbServiceWin(blocking_task_runner)); + return base::WrapUnique(new UsbServiceWin()); else - return base::WrapUnique(new UsbServiceImpl(blocking_task_runner)); + return base::WrapUnique(new UsbServiceImpl()); #elif defined(OS_MACOSX) - return base::WrapUnique(new UsbServiceImpl(blocking_task_runner)); + return base::WrapUnique(new UsbServiceImpl()); #else return nullptr; #endif } +// static +scoped_refptr<base::SequencedTaskRunner> +UsbService::CreateBlockingTaskRunner() { + return base::CreateSequencedTaskRunnerWithTraits(kBlockingTaskTraits); +} + UsbService::~UsbService() { -#if DCHECK_IS_ON() - DCHECK(did_shutdown_); -#endif - for (const auto& map_entry : devices_) - map_entry.second->OnDisconnect(); for (auto& observer : observer_list_) observer.WillDestroyUsbService(); } @@ -86,20 +90,6 @@ scoped_refptr<UsbDevice> UsbService::GetDevice(const std::string& guid) { return it->second; } -void UsbService::Shutdown() { - for (const auto& map_entry : devices_) { - // Swap out this list as UsbDevice::HandleClosed() will try to modify it. - std::list<UsbDeviceHandle*> handles; - handles.swap(map_entry.second->handles()); - for (auto* handle : handles) - handle->Close(); - } -#if DCHECK_IS_ON() - DCHECK(!did_shutdown_); - did_shutdown_ = true; -#endif -} - void UsbService::GetDevices(const GetDevicesCallback& callback) { std::vector<scoped_refptr<UsbDevice>> devices; devices.reserve(devices_.size()); diff --git a/chromium/device/usb/usb_service.h b/chromium/device/usb/usb_service.h index 15977dd1c54..79a1eff101f 100644 --- a/chromium/device/usb/usb_service.h +++ b/chromium/device/usb/usb_service.h @@ -18,6 +18,7 @@ #include "base/observer_list.h" #include "base/sequenced_task_runner.h" #include "base/single_thread_task_runner.h" +#include "base/task_scheduler/task_traits.h" #include "base/threading/non_thread_safe.h" namespace device { @@ -49,20 +50,22 @@ class UsbService : public base::NonThreadSafe { virtual void WillDestroyUsbService(); }; - // The file task runner reference is used for blocking I/O operations. + // These task traits are to be used for posting blocking tasks to the task + // scheduler. + static constexpr base::TaskTraits kBlockingTaskTraits = { + base::MayBlock(), base::TaskPriority::USER_VISIBLE, + base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}; + // Returns nullptr when initialization fails. - static std::unique_ptr<UsbService> Create( - scoped_refptr<base::SequencedTaskRunner> blocking_task_runner); + static std::unique_ptr<UsbService> Create(); + + // Creates a SequencedTaskRunner with kBlockingTaskTraits. + static scoped_refptr<base::SequencedTaskRunner> CreateBlockingTaskRunner(); virtual ~UsbService(); scoped_refptr<UsbDevice> GetDevice(const std::string& guid); - // Shuts down the UsbService. Must be called before destroying the UsbService - // when tasks can still be posted to the |blocking_task_runner| provided to - // Create(). - virtual void Shutdown(); - // Enumerates available devices. virtual void GetDevices(const GetDevicesCallback& callback); @@ -100,10 +103,6 @@ class UsbService : public base::NonThreadSafe { std::unordered_set<std::string> testing_devices_; base::ObserverList<Observer, true> observer_list_; -#if DCHECK_IS_ON() - bool did_shutdown_ = false; -#endif - DISALLOW_COPY_AND_ASSIGN(UsbService); }; diff --git a/chromium/device/usb/usb_service_android.cc b/chromium/device/usb/usb_service_android.cc index 102b33cb6a3..e29880d400b 100644 --- a/chromium/device/usb/usb_service_android.cc +++ b/chromium/device/usb/usb_service_android.cc @@ -7,7 +7,6 @@ #include <string> #include <vector> -#include "base/android/context_utils.h" #include "base/bind.h" #include "base/location.h" #include "base/sequenced_task_runner.h" @@ -26,21 +25,19 @@ bool UsbServiceAndroid::RegisterJNI(JNIEnv* env) { return RegisterNativesImpl(env); // Generated in ChromeUsbService_jni.h } -UsbServiceAndroid::UsbServiceAndroid( - scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) - : UsbService(blocking_task_runner), weak_factory_(this) { +UsbServiceAndroid::UsbServiceAndroid() + : UsbService(nullptr), weak_factory_(this) { JNIEnv* env = AttachCurrentThread(); j_object_.Reset( - Java_ChromeUsbService_create(env, base::android::GetApplicationContext(), - reinterpret_cast<jlong>(this))); + Java_ChromeUsbService_create(env, reinterpret_cast<jlong>(this))); ScopedJavaLocalRef<jobjectArray> devices = Java_ChromeUsbService_getDevices(env, j_object_); jsize length = env->GetArrayLength(devices.obj()); for (jsize i = 0; i < length; ++i) { ScopedJavaLocalRef<jobject> usb_device( env, env->GetObjectArrayElement(devices.obj(), i)); - scoped_refptr<UsbDeviceAndroid> device(UsbDeviceAndroid::Create( - env, weak_factory_.GetWeakPtr(), blocking_task_runner, usb_device)); + scoped_refptr<UsbDeviceAndroid> device = + UsbDeviceAndroid::Create(env, weak_factory_.GetWeakPtr(), usb_device); AddDevice(device); } } @@ -53,8 +50,8 @@ UsbServiceAndroid::~UsbServiceAndroid() { void UsbServiceAndroid::DeviceAttached(JNIEnv* env, const JavaRef<jobject>& caller, const JavaRef<jobject>& usb_device) { - scoped_refptr<UsbDeviceAndroid> device(UsbDeviceAndroid::Create( - env, weak_factory_.GetWeakPtr(), blocking_task_runner(), usb_device)); + scoped_refptr<UsbDeviceAndroid> device = + UsbDeviceAndroid::Create(env, weak_factory_.GetWeakPtr(), usb_device); AddDevice(device); NotifyDeviceAdded(device); } diff --git a/chromium/device/usb/usb_service_android.h b/chromium/device/usb/usb_service_android.h index 6fef48f9bc7..ae1ec5a3f22 100644 --- a/chromium/device/usb/usb_service_android.h +++ b/chromium/device/usb/usb_service_android.h @@ -5,21 +5,19 @@ #ifndef DEVICE_USB_USB_SERVICE_ANDROID_H_ #define DEVICE_USB_USB_SERVICE_ANDROID_H_ -#include <string> +#include <jni.h> + #include <unordered_map> #include "base/android/scoped_java_ref.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" -#include "device/usb/usb_device_android.h" #include "device/usb/usb_service.h" -namespace base { -class SequencedTaskRunner; -} - namespace device { +class UsbDeviceAndroid; + // USB service implementation for Android. This is a stub implementation that // does not return any devices. class UsbServiceAndroid : public UsbService { @@ -27,8 +25,7 @@ class UsbServiceAndroid : public UsbService { // Register C++ methods exposed to Java using JNI. static bool RegisterJNI(JNIEnv* env); - UsbServiceAndroid( - scoped_refptr<base::SequencedTaskRunner> blocking_task_runner); + UsbServiceAndroid(); ~UsbServiceAndroid() override; // Methods called by Java. diff --git a/chromium/device/usb/usb_service_impl.cc b/chromium/device/usb/usb_service_impl.cc index 2408eb4b32e..13cb14c95e3 100644 --- a/chromium/device/usb/usb_service_impl.cc +++ b/chromium/device/usb/usb_service_impl.cc @@ -15,10 +15,12 @@ #include "base/bind.h" #include "base/location.h" #include "base/memory/weak_ptr.h" +#include "base/sequenced_task_runner.h" #include "base/single_thread_task_runner.h" #include "base/stl_util.h" #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" +#include "base/task_scheduler/post_task.h" #include "build/build_config.h" #include "components/device_event_log/device_event_log.h" #include "device/usb/usb_device_handle.h" @@ -153,13 +155,10 @@ void SaveStringsAndRunContinuation( void OnReadBosDescriptor(scoped_refptr<UsbDeviceHandle> device_handle, const base::Closure& barrier, - std::unique_ptr<WebUsbAllowedOrigins> allowed_origins, const GURL& landing_page) { scoped_refptr<UsbDeviceImpl> device = static_cast<UsbDeviceImpl*>(device_handle->GetDevice().get()); - if (allowed_origins) - device->set_webusb_allowed_origins(std::move(allowed_origins)); if (landing_page.is_valid()) device->set_webusb_landing_page(landing_page); @@ -216,15 +215,14 @@ void OnDeviceOpenedReadDescriptors( } // namespace -UsbServiceImpl::UsbServiceImpl( - scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_in) - : UsbService(std::move(blocking_task_runner_in)), +UsbServiceImpl::UsbServiceImpl() + : UsbService(nullptr), #if defined(OS_WIN) device_observer_(this), #endif weak_factory_(this) { - blocking_task_runner()->PostTask( - FROM_HERE, + base::PostTaskWithTraits( + FROM_HERE, kBlockingTaskTraits, base::Bind(&InitializeUsbContextOnBlockingThread, task_runner(), base::Bind(&UsbServiceImpl::OnUsbContext, weak_factory_.GetWeakPtr()))); @@ -324,11 +322,11 @@ void UsbServiceImpl::RefreshDevices() { pending_path_enumerations_.pop(); } - blocking_task_runner()->PostTask( - FROM_HERE, - base::Bind(&GetDeviceListOnBlockingThread, device_path, context_, - task_runner(), base::Bind(&UsbServiceImpl::OnDeviceList, - weak_factory_.GetWeakPtr()))); + base::PostTaskWithTraits(FROM_HERE, kBlockingTaskTraits, + base::Bind(&GetDeviceListOnBlockingThread, + device_path, context_, task_runner(), + base::Bind(&UsbServiceImpl::OnDeviceList, + weak_factory_.GetWeakPtr()))); } void UsbServiceImpl::OnDeviceList(libusb_device** platform_devices, @@ -437,8 +435,8 @@ void UsbServiceImpl::EnumerateDevice(PlatformUsbDevice platform_device, return; } - scoped_refptr<UsbDeviceImpl> device(new UsbDeviceImpl( - context_, platform_device, descriptor, blocking_task_runner())); + scoped_refptr<UsbDeviceImpl> device( + new UsbDeviceImpl(context_, platform_device, descriptor)); base::Closure add_device = base::Bind(&UsbServiceImpl::AddDevice, weak_factory_.GetWeakPtr(), refresh_complete, device); diff --git a/chromium/device/usb/usb_service_impl.h b/chromium/device/usb/usb_service_impl.h index c644842aeba..0014dd31ff0 100644 --- a/chromium/device/usb/usb_service_impl.h +++ b/chromium/device/usb/usb_service_impl.h @@ -25,10 +25,6 @@ struct libusb_device; struct libusb_context; -namespace base { -class SequencedTaskRunner; -} - namespace device { typedef struct libusb_device* PlatformUsbDevice; @@ -42,8 +38,7 @@ class UsbServiceImpl : #endif // OS_WIN public UsbService { public: - explicit UsbServiceImpl( - scoped_refptr<base::SequencedTaskRunner> blocking_task_runner); + UsbServiceImpl(); ~UsbServiceImpl() override; private: diff --git a/chromium/device/usb/usb_service_linux.cc b/chromium/device/usb/usb_service_linux.cc index 394da74c400..9bd90153014 100644 --- a/chromium/device/usb/usb_service_linux.cc +++ b/chromium/device/usb/usb_service_linux.cc @@ -17,14 +17,14 @@ #include "base/memory/ptr_util.h" #include "base/memory/weak_ptr.h" #include "base/scoped_observer.h" -#include "base/single_thread_task_runner.h" #include "base/stl_util.h" #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" +#include "base/threading/sequenced_task_runner_handle.h" #include "base/threading/thread_restrictions.h" #include "build/build_config.h" #include "components/device_event_log/device_event_log.h" -#include "device/base/device_monitor_linux.h" +#include "device/udev_linux/udev_watcher.h" #include "device/usb/usb_device_handle.h" #include "device/usb/usb_device_linux.h" #include "device/usb/webusb_descriptors.h" @@ -40,13 +40,10 @@ const uint8_t kDeviceClassHub = 0x09; void OnReadDescriptors(const base::Callback<void(bool)>& callback, scoped_refptr<UsbDeviceHandle> device_handle, - std::unique_ptr<WebUsbAllowedOrigins> allowed_origins, const GURL& landing_page) { UsbDeviceLinux* device = static_cast<UsbDeviceLinux*>(device_handle->GetDevice().get()); - if (allowed_origins) - device->set_webusb_allowed_origins(std::move(allowed_origins)); if (landing_page.is_valid()) device->set_webusb_landing_page(landing_page); @@ -67,65 +64,65 @@ void OnDeviceOpenedToReadDescriptors( } // namespace -class UsbServiceLinux::FileThreadHelper : public DeviceMonitorLinux::Observer { +class UsbServiceLinux::FileThreadHelper : public UdevWatcher::Observer { public: - FileThreadHelper(base::WeakPtr<UsbServiceLinux> service, - scoped_refptr<base::SingleThreadTaskRunner> task_runner); + FileThreadHelper(base::WeakPtr<UsbServiceLinux> service); ~FileThreadHelper() override; void Start(); private: - // DeviceMonitorLinux::Observer: - void OnDeviceAdded(udev_device* udev_device) override; - void OnDeviceRemoved(udev_device* device) override; + // UdevWatcher::Observer + void OnDeviceAdded(ScopedUdevDevicePtr device) override; + void OnDeviceRemoved(ScopedUdevDevicePtr device) override; - base::ThreadChecker thread_checker_; - ScopedObserver<DeviceMonitorLinux, DeviceMonitorLinux::Observer> observer_; + std::unique_ptr<UdevWatcher> watcher_; - // |service_| can only be checked for validity on |task_runner_|'s thread. + // |service_| can only be checked for validity on |task_runner_|'s sequence. base::WeakPtr<UsbServiceLinux> service_; - scoped_refptr<base::SingleThreadTaskRunner> task_runner_; + scoped_refptr<base::SequencedTaskRunner> task_runner_; + + base::SequenceChecker sequence_checker_; DISALLOW_COPY_AND_ASSIGN(FileThreadHelper); }; UsbServiceLinux::FileThreadHelper::FileThreadHelper( - base::WeakPtr<UsbServiceLinux> service, - scoped_refptr<base::SingleThreadTaskRunner> task_runner) - : observer_(this), service_(service), task_runner_(std::move(task_runner)) { - thread_checker_.DetachFromThread(); + base::WeakPtr<UsbServiceLinux> service) + : service_(service), task_runner_(base::SequencedTaskRunnerHandle::Get()) { + // Detaches from the sequence on which this object was created. It will be + // bound to its owning sequence when Start() is called. + sequence_checker_.DetachFromSequence(); } UsbServiceLinux::FileThreadHelper::~FileThreadHelper() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(sequence_checker_.CalledOnValidSequence()); } // static void UsbServiceLinux::FileThreadHelper::Start() { + DCHECK(sequence_checker_.CalledOnValidSequence()); base::ThreadRestrictions::AssertIOAllowed(); - DCHECK(thread_checker_.CalledOnValidThread()); - DeviceMonitorLinux* monitor = DeviceMonitorLinux::GetInstance(); - observer_.Add(monitor); - monitor->Enumerate( - base::Bind(&FileThreadHelper::OnDeviceAdded, base::Unretained(this))); + watcher_ = UdevWatcher::StartWatching(this); + watcher_->EnumerateExistingDevices(); task_runner_->PostTask(FROM_HERE, base::Bind(&UsbServiceLinux::HelperStarted, service_)); } void UsbServiceLinux::FileThreadHelper::OnDeviceAdded( - udev_device* udev_device) { - const char* subsystem = udev_device_get_subsystem(udev_device); + ScopedUdevDevicePtr device) { + DCHECK(sequence_checker_.CalledOnValidSequence()); + const char* subsystem = udev_device_get_subsystem(device.get()); if (!subsystem || strcmp(subsystem, "usb") != 0) return; - const char* value = udev_device_get_devnode(udev_device); + const char* value = udev_device_get_devnode(device.get()); if (!value) return; std::string device_path = value; - const char* sysfs_path = udev_device_get_syspath(udev_device); + const char* sysfs_path = udev_device_get_syspath(device.get()); if (!sysfs_path) return; @@ -147,22 +144,22 @@ void UsbServiceLinux::FileThreadHelper::OnDeviceAdded( } std::string manufacturer; - value = udev_device_get_sysattr_value(udev_device, "manufacturer"); + value = udev_device_get_sysattr_value(device.get(), "manufacturer"); if (value) manufacturer = value; std::string product; - value = udev_device_get_sysattr_value(udev_device, "product"); + value = udev_device_get_sysattr_value(device.get(), "product"); if (value) product = value; std::string serial_number; - value = udev_device_get_sysattr_value(udev_device, "serial"); + value = udev_device_get_sysattr_value(device.get(), "serial"); if (value) serial_number = value; unsigned active_configuration = 0; - value = udev_device_get_sysattr_value(udev_device, "bConfigurationValue"); + value = udev_device_get_sysattr_value(device.get(), "bConfigurationValue"); if (value) base::StringToUint(value, &active_configuration); @@ -172,9 +169,10 @@ void UsbServiceLinux::FileThreadHelper::OnDeviceAdded( serial_number, active_configuration)); } -void UsbServiceLinux::FileThreadHelper::OnDeviceRemoved(udev_device* device) { - DCHECK(thread_checker_.CalledOnValidThread()); - const char* device_path = udev_device_get_devnode(device); +void UsbServiceLinux::FileThreadHelper::OnDeviceRemoved( + ScopedUdevDevicePtr device) { + DCHECK(sequence_checker_.CalledOnValidSequence()); + const char* device_path = udev_device_get_devnode(device.get()); if (device_path) { task_runner_->PostTask( FROM_HERE, base::Bind(&UsbServiceLinux::OnDeviceRemoved, service_, @@ -182,25 +180,16 @@ void UsbServiceLinux::FileThreadHelper::OnDeviceRemoved(udev_device* device) { } } -UsbServiceLinux::UsbServiceLinux( - scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_in) - : UsbService(std::move(blocking_task_runner_in)), weak_factory_(this) { - helper_ = base::MakeUnique<FileThreadHelper>(weak_factory_.GetWeakPtr(), - task_runner()); +UsbServiceLinux::UsbServiceLinux() + : UsbService(CreateBlockingTaskRunner()), weak_factory_(this) { + helper_ = base::MakeUnique<FileThreadHelper>(weak_factory_.GetWeakPtr()); blocking_task_runner()->PostTask( FROM_HERE, base::Bind(&FileThreadHelper::Start, base::Unretained(helper_.get()))); } UsbServiceLinux::~UsbServiceLinux() { - DCHECK(!helper_); -} - -void UsbServiceLinux::Shutdown() { - const bool did_post_task = - blocking_task_runner()->DeleteSoon(FROM_HERE, helper_.release()); - DCHECK(did_post_task); - UsbService::Shutdown(); + blocking_task_runner()->DeleteSoon(FROM_HERE, helper_.release()); } void UsbServiceLinux::GetDevices(const GetDevicesCallback& callback) { @@ -230,9 +219,9 @@ void UsbServiceLinux::OnDeviceAdded(const std::string& device_path, if (!enumeration_ready()) ++first_enumeration_countdown_; - scoped_refptr<UsbDeviceLinux> device(new UsbDeviceLinux( - device_path, descriptor, manufacturer, product, serial_number, - active_configuration, blocking_task_runner())); + scoped_refptr<UsbDeviceLinux> device( + new UsbDeviceLinux(device_path, descriptor, manufacturer, product, + serial_number, active_configuration)); devices_by_path_[device->device_path()] = device; if (device->usb_version() >= kUsbVersion2_1) { device->Open(base::Bind(&OnDeviceOpenedToReadDescriptors, diff --git a/chromium/device/usb/usb_service_linux.h b/chromium/device/usb/usb_service_linux.h index 02fcafcf959..b334de39b0e 100644 --- a/chromium/device/usb/usb_service_linux.h +++ b/chromium/device/usb/usb_service_linux.h @@ -10,10 +10,6 @@ #include "base/memory/weak_ptr.h" #include "device/usb/usb_service.h" -namespace base { -class SequencedTaskRunner; -} - namespace device { struct UsbDeviceDescriptor; @@ -21,12 +17,10 @@ class UsbDeviceLinux; class UsbServiceLinux : public UsbService { public: - explicit UsbServiceLinux( - scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_in); + UsbServiceLinux(); ~UsbServiceLinux() override; // device::UsbService implementation - void Shutdown() override; void GetDevices(const GetDevicesCallback& callback) override; private: diff --git a/chromium/device/usb/usb_service_unittest.cc b/chromium/device/usb/usb_service_unittest.cc index 559e52a82fa..d7bb7472514 100644 --- a/chromium/device/usb/usb_service_unittest.cc +++ b/chromium/device/usb/usb_service_unittest.cc @@ -5,10 +5,10 @@ #include <memory> #include "base/bind.h" -#include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/strings/utf_string_conversions.h" #include "base/test/scoped_feature_list.h" +#include "base/test/scoped_task_environment.h" #include "base/test/test_io_thread.h" #include "device/base/features.h" #include "device/test/test_device_client.h" @@ -24,35 +24,30 @@ namespace { class UsbServiceTest : public ::testing::Test { public: - void SetUp() override { - message_loop_.reset(new base::MessageLoopForUI); - io_thread_.reset(new base::TestIOThread(base::TestIOThread::kAutoStart)); - device_client_.reset(new TestDeviceClient(io_thread_->task_runner())); - } + UsbServiceTest() + : scoped_task_environment_( + base::test::ScopedTaskEnvironment::MainThreadType::UI), + io_thread_(base::TestIOThread::kAutoStart) {} protected: - std::unique_ptr<base::MessageLoop> message_loop_; - std::unique_ptr<base::TestIOThread> io_thread_; - std::unique_ptr<TestDeviceClient> device_client_; + base::test::ScopedTaskEnvironment scoped_task_environment_; + base::TestIOThread io_thread_; + TestDeviceClient device_client_; }; void OnGetDevices(const base::Closure& quit_closure, const std::vector<scoped_refptr<UsbDevice>>& devices) { + // Since there's no guarantee that any devices are connected at the moment + // this test doesn't assume anything about the result but it at least verifies + // that devices can be enumerated without the application crashing. quit_closure.Run(); } -void OnOpen(scoped_refptr<UsbDeviceHandle>* output, - const base::Closure& quit_closure, - scoped_refptr<UsbDeviceHandle> input) { - *output = input; - quit_closure.Run(); -} +} // namespace TEST_F(UsbServiceTest, GetDevices) { - // Since there's no guarantee that any devices are connected at the moment - // this test doesn't assume anything about the result but it at least verifies - // that devices can be enumerated without the application crashing. - UsbService* service = device_client_->GetUsbService(); + // The USB service is not available on all platforms. + UsbService* service = DeviceClient::Get()->GetUsbService(); if (service) { base::RunLoop loop; service->GetDevices(base::Bind(&OnGetDevices, loop.QuitClosure())); @@ -64,7 +59,7 @@ TEST_F(UsbServiceTest, GetDevices) { TEST_F(UsbServiceTest, GetDevicesNewBackend) { base::test::ScopedFeatureList features; features.InitAndEnableFeature(device::kNewUsbBackend); - UsbService* service = device_client_->GetUsbService(); + UsbService* service = DeviceClient::Get()->GetUsbService(); if (service) { base::RunLoop loop; service->GetDevices(base::Bind(&OnGetDevices, loop.QuitClosure())); @@ -77,7 +72,7 @@ TEST_F(UsbServiceTest, ClaimGadget) { if (!UsbTestGadget::IsTestEnabled()) return; std::unique_ptr<UsbTestGadget> gadget = - UsbTestGadget::Claim(io_thread_->task_runner()); + UsbTestGadget::Claim(io_thread_.task_runner()); ASSERT_TRUE(gadget); scoped_refptr<UsbDevice> device = gadget->GetDevice(); @@ -90,32 +85,10 @@ TEST_F(UsbServiceTest, DisconnectAndReconnect) { if (!UsbTestGadget::IsTestEnabled()) return; std::unique_ptr<UsbTestGadget> gadget = - UsbTestGadget::Claim(io_thread_->task_runner()); + UsbTestGadget::Claim(io_thread_.task_runner()); ASSERT_TRUE(gadget); ASSERT_TRUE(gadget->Disconnect()); ASSERT_TRUE(gadget->Reconnect()); } -TEST_F(UsbServiceTest, Shutdown) { - if (!UsbTestGadget::IsTestEnabled()) - return; - - std::unique_ptr<UsbTestGadget> gadget = - UsbTestGadget::Claim(io_thread_->task_runner()); - ASSERT_TRUE(gadget); - - base::RunLoop loop; - scoped_refptr<UsbDeviceHandle> device_handle; - gadget->GetDevice()->Open( - base::Bind(&OnOpen, &device_handle, loop.QuitClosure())); - loop.Run(); - ASSERT_TRUE(device_handle); - - // Shut down the USB service while the device handle is still open. - device_client_.reset(); - EXPECT_FALSE(device_handle->GetDevice()); -} - -} // namespace - } // namespace device diff --git a/chromium/device/usb/usb_service_win.cc b/chromium/device/usb/usb_service_win.cc index 8cc9c0c9a2e..e85b32d34b2 100644 --- a/chromium/device/usb/usb_service_win.cc +++ b/chromium/device/usb/usb_service_win.cc @@ -170,12 +170,12 @@ bool GetHubDevicePath(const std::string& instance_id, } // namespace -class UsbServiceWin::BlockingThreadHelper { +class UsbServiceWin::BlockingTaskHelper { public: - explicit BlockingThreadHelper(base::WeakPtr<UsbServiceWin> service) + explicit BlockingTaskHelper(base::WeakPtr<UsbServiceWin> service) : service_task_runner_(base::ThreadTaskRunnerHandle::Get()), service_(service) {} - ~BlockingThreadHelper() {} + ~BlockingTaskHelper() {} void EnumerateDevices() { ScopedDevInfo dev_info( @@ -276,9 +276,8 @@ class UsbServiceWin::BlockingThreadHelper { base::WeakPtr<UsbServiceWin> service_; }; -UsbServiceWin::UsbServiceWin( - scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) - : UsbService(blocking_task_runner), +UsbServiceWin::UsbServiceWin() + : UsbService(CreateBlockingTaskRunner()), device_observer_(this), weak_factory_(this) { DeviceMonitorWin* device_monitor = @@ -286,13 +285,15 @@ UsbServiceWin::UsbServiceWin( if (device_monitor) device_observer_.Add(device_monitor); - helper_ = new BlockingThreadHelper(weak_factory_.GetWeakPtr()); - blocking_task_runner->PostTask( - FROM_HERE, base::Bind(&BlockingThreadHelper::EnumerateDevices, - base::Unretained(helper_))); + helper_ = base::MakeUnique<BlockingTaskHelper>(weak_factory_.GetWeakPtr()); + blocking_task_runner()->PostTask( + FROM_HERE, base::Bind(&BlockingTaskHelper::EnumerateDevices, + base::Unretained(helper_.get()))); } -UsbServiceWin::~UsbServiceWin() {} +UsbServiceWin::~UsbServiceWin() { + blocking_task_runner()->DeleteSoon(FROM_HERE, helper_.release()); +} void UsbServiceWin::GetDevices(const GetDevicesCallback& callback) { DCHECK(CalledOnValidThread()); @@ -305,8 +306,8 @@ void UsbServiceWin::GetDevices(const GetDevicesCallback& callback) { void UsbServiceWin::OnDeviceAdded(const GUID& class_guid, const std::string& device_path) { blocking_task_runner()->PostTask( - FROM_HERE, base::Bind(&BlockingThreadHelper::EnumerateDevicePath, - base::Unretained(helper_), device_path)); + FROM_HERE, base::Bind(&BlockingTaskHelper::EnumerateDevicePath, + base::Unretained(helper_.get()), device_path)); } void UsbServiceWin::OnDeviceRemoved(const GUID& class_guid, diff --git a/chromium/device/usb/usb_service_win.h b/chromium/device/usb/usb_service_win.h index 58f4bb2bc89..50e2aaa86ee 100644 --- a/chromium/device/usb/usb_service_win.h +++ b/chromium/device/usb/usb_service_win.h @@ -13,20 +13,15 @@ #include "device/base/device_monitor_win.h" #include "device/usb/usb_device_win.h" -namespace base { -class SequencedTaskRunner; -} - namespace device { class UsbServiceWin : public DeviceMonitorWin::Observer, public UsbService { public: - explicit UsbServiceWin( - scoped_refptr<base::SequencedTaskRunner> blocking_task_runner); + UsbServiceWin(); ~UsbServiceWin() override; private: - class BlockingThreadHelper; + class BlockingTaskHelper; // device::UsbService implementation void GetDevices(const GetDevicesCallback& callback) override; @@ -55,7 +50,7 @@ class UsbServiceWin : public DeviceMonitorWin::Observer, public UsbService { uint32_t first_enumeration_countdown_ = 0; std::list<GetDevicesCallback> enumeration_callbacks_; - BlockingThreadHelper* helper_; + std::unique_ptr<BlockingTaskHelper> helper_; std::unordered_map<std::string, scoped_refptr<UsbDeviceWin>> devices_by_path_; ScopedObserver<DeviceMonitorWin, DeviceMonitorWin::Observer> device_observer_; diff --git a/chromium/device/usb/webusb_descriptors.cc b/chromium/device/usb/webusb_descriptors.cc index 7cf3140619d..051c193a377 100644 --- a/chromium/device/usb/webusb_descriptors.cc +++ b/chromium/device/usb/webusb_descriptors.cc @@ -4,14 +4,6 @@ #include "device/usb/webusb_descriptors.h" -#include <stddef.h> - -#include <iterator> -#include <map> -#include <memory> -#include <set> - -#include "base/barrier_closure.h" #include "base/bind.h" #include "base/callback.h" #include "base/logging.h" @@ -37,7 +29,6 @@ const uint8_t kPlatformDevCapabilityType = 0x05; // These constants are defined by the WebUSB specification: // http://wicg.github.io/webusb/ -const uint8_t kGetAllowedOriginsRequest = 0x01; const uint8_t kGetUrlRequest = 0x02; const uint8_t kWebUsbCapabilityUUID[16] = { @@ -45,275 +36,39 @@ const uint8_t kWebUsbCapabilityUUID[16] = { 0x38, 0xB6, 0x08, 0x34, 0xA9, 0x09, 0xA0, 0x47, 0x8B, 0xFD, 0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65}; -const int kControlTransferTimeout = 60000; // 1 minute +const int kControlTransferTimeoutMs = 2000; // 2 seconds using ReadWebUsbDescriptorsCallback = - base::Callback<void(std::unique_ptr<WebUsbAllowedOrigins> allowed_origins, - const GURL& landing_page)>; - -using ReadWebUsbAllowedOriginsCallback = - base::Callback<void(std::unique_ptr<WebUsbAllowedOrigins> allowed_origins)>; - -// Parses a WebUSB Function Subset Header: -// http://wicg.github.io/webusb/#dfn-function-subset-header -// -// 0 1 2 3 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | length | type | 1st interface | origin[0] | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | origin[1] | ... -// +-+-+-+-+-+-+-+-+-+-+-+------ -bool ParseFunction(WebUsbFunctionSubset* function, - std::vector<uint8_t>::const_iterator* it, - std::vector<uint8_t>::const_iterator end) { - const uint8_t kDescriptorType = 0x02; - const uint8_t kDescriptorMinLength = 3; - - // If this isn't the end of the buffer then there must be at least one byte - // available, the length of the descriptor. - if (*it == end) - return false; - uint8_t length = (*it)[0]; - - // Is this a valid Function Subset Header? It must be long enough, fit within - // the buffer and have the right descriptor type. - if (length < kDescriptorMinLength || std::distance(*it, end) < length || - (*it)[1] != kDescriptorType) { - return false; - } - - function->first_interface = (*it)[2]; - - // Everything after the mandatory fields are origin indicies. - std::advance(*it, kDescriptorMinLength); - uint8_t num_origins = length - kDescriptorMinLength; - function->origin_ids.reserve(num_origins); - for (size_t i = 0; i < num_origins; ++i) { - uint8_t index = *(*it)++; - if (index == 0) - return false; - function->origin_ids.push_back(index); - } - - return true; -} - -// Parses a WebUSB Configuration Subset Header: -// http://wicg.github.io/webusb/#dfn-configuration-subset-header -// -// 0 1 2 3 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | length | type | config value | num functions | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | origin[0] | origin[1] | ... -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+------ -bool ParseConfiguration(WebUsbConfigurationSubset* configuration, - std::vector<uint8_t>::const_iterator* it, - std::vector<uint8_t>::const_iterator end) { - const uint8_t kDescriptorType = 0x01; - const uint8_t kDescriptorMinLength = 4; - - // If this isn't the end of the buffer then there must be at least one byte - // available, the length of the descriptor. - if (*it == end) - return false; - uint8_t length = (*it)[0]; - - // Is this a valid Configuration Subset Header? It must be long enough, fit - // within the buffer and have the right descriptor type. - if (length < kDescriptorMinLength || std::distance(*it, end) < length || - (*it)[1] != kDescriptorType) { - return false; - } - - configuration->configuration_value = (*it)[2]; - uint8_t num_functions = (*it)[3]; - - // The next |length - 4| bytes after the mandatory fields are origin indicies. - std::advance(*it, kDescriptorMinLength); - uint8_t num_origins = length - kDescriptorMinLength; - configuration->origin_ids.reserve(num_origins); - for (size_t i = 0; i < num_origins; ++i) { - uint8_t index = *(*it)++; - if (index == 0) - return false; - configuration->origin_ids.push_back(index); - } - - // |num_functions| function descriptors then follow the descriptor. - for (size_t i = 0; i < num_functions; ++i) { - WebUsbFunctionSubset function; - if (!ParseFunction(&function, it, end)) - return false; - configuration->functions.push_back(function); - } - - return true; -} - -void OnDoneReadingUrls(std::unique_ptr<WebUsbAllowedOrigins> allowed_origins, - uint8_t landing_page_id, - std::unique_ptr<std::map<uint8_t, GURL>> url_map, - const ReadWebUsbDescriptorsCallback& callback) { - if (allowed_origins) { - for (uint8_t origin_id : allowed_origins->origin_ids) { - const auto& it = url_map->find(origin_id); - if (it != url_map->end()) - allowed_origins->origins.push_back(it->second.GetOrigin()); - } - - for (auto& configuration : allowed_origins->configurations) { - for (uint8_t origin_id : configuration.origin_ids) { - const auto& it = url_map->find(origin_id); - if (it != url_map->end()) - configuration.origins.push_back(it->second.GetOrigin()); - } - - for (auto& function : configuration.functions) { - for (uint8_t origin_id : function.origin_ids) { - const auto& it = url_map->find(origin_id); - if (it != url_map->end()) - function.origins.push_back(it->second.GetOrigin()); - } - } - } - } - - GURL landing_page; - if (landing_page_id != 0) - landing_page = (*url_map)[landing_page_id]; - - callback.Run(std::move(allowed_origins), landing_page); -} - -void OnReadUrlDescriptor(std::map<uint8_t, GURL>* url_map, - uint8_t index, - const base::Closure& callback, - UsbTransferStatus status, - scoped_refptr<net::IOBuffer> buffer, - size_t length) { - if (status != USB_TRANSFER_COMPLETED) { - USB_LOG(EVENT) << "Failed to read WebUSB URL descriptor: " << index; - callback.Run(); + base::Callback<void(const GURL& landing_page)>; + +void OnReadLandingPage(uint8_t landing_page_id, + const ReadWebUsbDescriptorsCallback& callback, + UsbTransferStatus status, + scoped_refptr<net::IOBuffer> buffer, + size_t length) { + if (status != UsbTransferStatus::COMPLETED) { + USB_LOG(EVENT) << "Failed to read WebUSB URL descriptor: " + << static_cast<int>(landing_page_id); + callback.Run(GURL()); return; } GURL url; - if (ParseWebUsbUrlDescriptor( - std::vector<uint8_t>(buffer->data(), buffer->data() + length), - &url)) { - (*url_map)[index] = url; - } - callback.Run(); -} - -// Reads the descriptor with |index| from the device, adds the value to -// |url_map| and then runs |callback|. -void ReadUrlDescriptor(scoped_refptr<UsbDeviceHandle> device_handle, - uint8_t vendor_code, - std::map<uint8_t, GURL>* url_map, - uint8_t index, - const base::Closure& callback) { - scoped_refptr<IOBufferWithSize> buffer = new IOBufferWithSize(255); - device_handle->ControlTransfer( - USB_DIRECTION_INBOUND, UsbDeviceHandle::VENDOR, UsbDeviceHandle::DEVICE, - vendor_code, index, kGetUrlRequest, buffer, buffer->size(), - kControlTransferTimeout, - base::Bind(&OnReadUrlDescriptor, url_map, index, callback)); -} - -// Reads URL descriptors from the device so that it can fill |allowed_origins| -// with the GURLs matching the indices already collected. -void ReadUrlDescriptors(scoped_refptr<UsbDeviceHandle> device_handle, - uint8_t vendor_code, - uint8_t landing_page_id, - const ReadWebUsbDescriptorsCallback& callback, - std::unique_ptr<WebUsbAllowedOrigins> allowed_origins) { - std::set<uint8_t> to_request; - if (landing_page_id != 0) - to_request.insert(landing_page_id); - - if (allowed_origins) { - to_request.insert(allowed_origins->origin_ids.begin(), - allowed_origins->origin_ids.end()); - for (auto& config : allowed_origins->configurations) { - to_request.insert(config.origin_ids.begin(), config.origin_ids.end()); - for (auto& function : config.functions) { - to_request.insert(function.origin_ids.begin(), - function.origin_ids.end()); - } - } - } - - std::unique_ptr<std::map<uint8_t, GURL>> url_map( - new std::map<uint8_t, GURL>()); - std::map<uint8_t, GURL>* url_map_ptr = url_map.get(); - base::Closure barrier = base::BarrierClosure( - static_cast<int>(to_request.size()), - base::Bind(&OnDoneReadingUrls, base::Passed(&allowed_origins), - landing_page_id, base::Passed(&url_map), callback)); - - for (uint8_t index : to_request) - ReadUrlDescriptor(device_handle, vendor_code, url_map_ptr, index, barrier); -} - -void OnReadWebUsbAllowedOrigins( - const ReadWebUsbAllowedOriginsCallback& callback, - UsbTransferStatus status, - scoped_refptr<net::IOBuffer> buffer, - size_t length) { - if (status != USB_TRANSFER_COMPLETED) { - USB_LOG(EVENT) << "Failed to read WebUSB allowed origins."; - callback.Run(nullptr); - return; - } - - std::unique_ptr<WebUsbAllowedOrigins> allowed_origins( - new WebUsbAllowedOrigins()); - if (allowed_origins->Parse( - std::vector<uint8_t>(buffer->data(), buffer->data() + length))) { - callback.Run(std::move(allowed_origins)); - } else { - callback.Run(nullptr); - } -} - -void OnReadWebUsbAllowedOriginsHeader( - scoped_refptr<UsbDeviceHandle> device_handle, - const ReadWebUsbAllowedOriginsCallback& callback, - uint8_t vendor_code, - UsbTransferStatus status, - scoped_refptr<net::IOBuffer> buffer, - size_t length) { - if (status != USB_TRANSFER_COMPLETED || length != 4) { - USB_LOG(EVENT) << "Failed to read WebUSB allowed origins header."; - callback.Run(nullptr); - return; - } - - const uint8_t* data = reinterpret_cast<uint8_t*>(buffer->data()); - uint16_t new_length = data[2] | (data[3] << 8); - scoped_refptr<IOBufferWithSize> new_buffer = new IOBufferWithSize(new_length); - device_handle->ControlTransfer( - USB_DIRECTION_INBOUND, UsbDeviceHandle::VENDOR, UsbDeviceHandle::DEVICE, - vendor_code, 0, kGetAllowedOriginsRequest, new_buffer, new_buffer->size(), - kControlTransferTimeout, - base::Bind(&OnReadWebUsbAllowedOrigins, callback)); + ParseWebUsbUrlDescriptor( + std::vector<uint8_t>(buffer->data(), buffer->data() + length), &url); + callback.Run(url); } -void ReadWebUsbAllowedOrigins( - scoped_refptr<UsbDeviceHandle> device_handle, - uint8_t vendor_code, - const ReadWebUsbAllowedOriginsCallback& callback) { - scoped_refptr<IOBufferWithSize> buffer = new IOBufferWithSize(4); +void ReadLandingPage(uint8_t vendor_code, + uint8_t landing_page_id, + scoped_refptr<UsbDeviceHandle> device_handle, + const ReadWebUsbDescriptorsCallback& callback) { + auto buffer = base::MakeRefCounted<IOBufferWithSize>(255); device_handle->ControlTransfer( - USB_DIRECTION_INBOUND, UsbDeviceHandle::VENDOR, UsbDeviceHandle::DEVICE, - vendor_code, 0, kGetAllowedOriginsRequest, buffer, buffer->size(), - kControlTransferTimeout, - base::Bind(&OnReadWebUsbAllowedOriginsHeader, device_handle, callback, - vendor_code)); + UsbTransferDirection::INBOUND, UsbControlTransferType::VENDOR, + UsbControlTransferRecipient::DEVICE, vendor_code, landing_page_id, + kGetUrlRequest, buffer, buffer->size(), kControlTransferTimeoutMs, + base::Bind(&OnReadLandingPage, landing_page_id, callback)); } void OnReadBosDescriptor(scoped_refptr<UsbDeviceHandle> device_handle, @@ -321,23 +76,25 @@ void OnReadBosDescriptor(scoped_refptr<UsbDeviceHandle> device_handle, UsbTransferStatus status, scoped_refptr<net::IOBuffer> buffer, size_t length) { - if (status != USB_TRANSFER_COMPLETED) { + if (status != UsbTransferStatus::COMPLETED) { USB_LOG(EVENT) << "Failed to read BOS descriptor."; - callback.Run(nullptr, GURL()); + callback.Run(GURL()); return; } WebUsbPlatformCapabilityDescriptor descriptor; if (!descriptor.ParseFromBosDescriptor( std::vector<uint8_t>(buffer->data(), buffer->data() + length))) { - callback.Run(nullptr, GURL()); + callback.Run(GURL()); return; } - ReadWebUsbAllowedOrigins( - device_handle, descriptor.vendor_code, - base::Bind(&ReadUrlDescriptors, device_handle, descriptor.vendor_code, - descriptor.landing_page_id, callback)); + if (descriptor.landing_page_id) { + ReadLandingPage(descriptor.vendor_code, descriptor.landing_page_id, + device_handle, callback); + } else { + callback.Run(GURL()); + } } void OnReadBosDescriptorHeader(scoped_refptr<UsbDeviceHandle> device_handle, @@ -345,9 +102,9 @@ void OnReadBosDescriptorHeader(scoped_refptr<UsbDeviceHandle> device_handle, UsbTransferStatus status, scoped_refptr<net::IOBuffer> buffer, size_t length) { - if (status != USB_TRANSFER_COMPLETED || length != 5) { + if (status != UsbTransferStatus::COMPLETED || length != 5) { USB_LOG(EVENT) << "Failed to read BOS descriptor header."; - callback.Run(nullptr, GURL()); + callback.Run(GURL()); return; } @@ -355,87 +112,15 @@ void OnReadBosDescriptorHeader(scoped_refptr<UsbDeviceHandle> device_handle, uint16_t new_length = data[2] | (data[3] << 8); scoped_refptr<IOBufferWithSize> new_buffer = new IOBufferWithSize(new_length); device_handle->ControlTransfer( - USB_DIRECTION_INBOUND, UsbDeviceHandle::STANDARD, UsbDeviceHandle::DEVICE, - kGetDescriptorRequest, kBosDescriptorType << 8, 0, new_buffer, - new_buffer->size(), kControlTransferTimeout, + UsbTransferDirection::INBOUND, UsbControlTransferType::STANDARD, + UsbControlTransferRecipient::DEVICE, kGetDescriptorRequest, + kBosDescriptorType << 8, 0, new_buffer, new_buffer->size(), + kControlTransferTimeoutMs, base::Bind(&OnReadBosDescriptor, device_handle, callback)); } } // namespace -WebUsbFunctionSubset::WebUsbFunctionSubset() : first_interface(0) {} - -WebUsbFunctionSubset::WebUsbFunctionSubset(const WebUsbFunctionSubset& other) = - default; - -WebUsbFunctionSubset::~WebUsbFunctionSubset() {} - -WebUsbConfigurationSubset::WebUsbConfigurationSubset() - : configuration_value(0) {} - -WebUsbConfigurationSubset::WebUsbConfigurationSubset( - const WebUsbConfigurationSubset& other) = default; - -WebUsbConfigurationSubset::~WebUsbConfigurationSubset() {} - -WebUsbAllowedOrigins::WebUsbAllowedOrigins() {} - -WebUsbAllowedOrigins::~WebUsbAllowedOrigins() {} - -// Parses a WebUSB Allowed Origins Header: -// http://wicg.github.io/webusb/#dfn-allowed-origins-header -// -// 0 1 2 3 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | length | type | total length | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | num configs | origin[0] | origin[1] | ... -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+------ -bool WebUsbAllowedOrigins::Parse(const std::vector<uint8_t>& bytes) { - const uint8_t kDescriptorType = 0x00; - const uint8_t kDescriptorMinLength = 5; - - // The buffer must be at least the length of this descriptor's mandatory - // fields. - if (bytes.size() < kDescriptorMinLength) - return false; - - // Validate that the length of this descriptor and the total length of the - // entire block of descriptors is consistent with the length of the buffer. - uint8_t length = bytes[0]; - uint16_t total_length = bytes[2] + (bytes[3] << 8); - if (length < 5 || length > bytes.size() || // bLength - bytes[1] != kDescriptorType || // bDescriptorType - total_length < length || total_length > bytes.size()) { // wTotalLength - return false; - } - - std::vector<uint8_t>::const_iterator it = bytes.begin(); - uint8_t num_configurations = bytes[4]; - - // The next |length - 5| bytes after the mandatory fields are origin indicies. - std::advance(it, kDescriptorMinLength); - uint8_t num_origins = length - kDescriptorMinLength; - origin_ids.reserve(num_origins); - for (size_t i = 0; i < num_origins; ++i) { - uint8_t index = *it++; - if (index == 0) - return false; - origin_ids.push_back(index); - } - - // |num_configurations| configuration descriptors then follow the descriptor. - for (size_t i = 0; i < num_configurations; ++i) { - WebUsbConfigurationSubset configuration; - if (!ParseConfiguration(&configuration, &it, bytes.end())) - return false; - configurations.push_back(configuration); - } - - return true; -} - WebUsbPlatformCapabilityDescriptor::WebUsbPlatformCapabilityDescriptor() : version(0), vendor_code(0) {} @@ -565,42 +250,13 @@ bool ParseWebUsbUrlDescriptor(const std::vector<uint8_t>& bytes, GURL* output) { void ReadWebUsbDescriptors(scoped_refptr<UsbDeviceHandle> device_handle, const ReadWebUsbDescriptorsCallback& callback) { - scoped_refptr<IOBufferWithSize> buffer = new IOBufferWithSize(5); + auto buffer = base::MakeRefCounted<IOBufferWithSize>(5); device_handle->ControlTransfer( - USB_DIRECTION_INBOUND, UsbDeviceHandle::STANDARD, UsbDeviceHandle::DEVICE, - kGetDescriptorRequest, kBosDescriptorType << 8, 0, buffer, buffer->size(), - kControlTransferTimeout, + UsbTransferDirection::INBOUND, UsbControlTransferType::STANDARD, + UsbControlTransferRecipient::DEVICE, kGetDescriptorRequest, + kBosDescriptorType << 8, 0, buffer, buffer->size(), + kControlTransferTimeoutMs, base::Bind(&OnReadBosDescriptorHeader, device_handle, callback)); } -bool FindInWebUsbAllowedOrigins( - const device::WebUsbAllowedOrigins* allowed_origins, - const GURL& origin, - base::Optional<uint8_t> config_value, - base::Optional<uint8_t> first_interface) { - if (!allowed_origins) - return false; - - if (base::ContainsValue(allowed_origins->origins, origin)) - return true; - - for (const auto& config : allowed_origins->configurations) { - if (config_value && *config_value != config.configuration_value) - continue; - - if (base::ContainsValue(config.origins, origin)) - return true; - - for (const auto& function : config.functions) { - if (first_interface && *first_interface != function.first_interface) - continue; - - if (base::ContainsValue(function.origins, origin)) - return true; - } - } - - return false; -} - } // namespace device diff --git a/chromium/device/usb/webusb_descriptors.h b/chromium/device/usb/webusb_descriptors.h index 34a7d614ca0..026a0f9150e 100644 --- a/chromium/device/usb/webusb_descriptors.h +++ b/chromium/device/usb/webusb_descriptors.h @@ -7,50 +7,16 @@ #include <stdint.h> -#include <memory> #include <vector> #include "base/callback_forward.h" #include "base/memory/ref_counted.h" -#include "base/optional.h" #include "url/gurl.h" namespace device { class UsbDeviceHandle; -struct WebUsbFunctionSubset { - WebUsbFunctionSubset(); - WebUsbFunctionSubset(const WebUsbFunctionSubset& other); - ~WebUsbFunctionSubset(); - - uint8_t first_interface; - std::vector<uint8_t> origin_ids; - std::vector<GURL> origins; -}; - -struct WebUsbConfigurationSubset { - WebUsbConfigurationSubset(); - WebUsbConfigurationSubset(const WebUsbConfigurationSubset& other); - ~WebUsbConfigurationSubset(); - - uint8_t configuration_value; - std::vector<uint8_t> origin_ids; - std::vector<GURL> origins; - std::vector<WebUsbFunctionSubset> functions; -}; - -struct WebUsbAllowedOrigins { - WebUsbAllowedOrigins(); - ~WebUsbAllowedOrigins(); - - bool Parse(const std::vector<uint8_t>& bytes); - - std::vector<uint8_t> origin_ids; - std::vector<GURL> origins; - std::vector<WebUsbConfigurationSubset> configurations; -}; - struct WebUsbPlatformCapabilityDescriptor { WebUsbPlatformCapabilityDescriptor(); ~WebUsbPlatformCapabilityDescriptor(); @@ -67,17 +33,7 @@ bool ParseWebUsbUrlDescriptor(const std::vector<uint8_t>& bytes, GURL* output); void ReadWebUsbDescriptors( scoped_refptr<UsbDeviceHandle> device_handle, - const base::Callback< - void(std::unique_ptr<WebUsbAllowedOrigins> allowed_origins, - const GURL& landing_page)>& callback); - -// Check if the origin is allowed to access a given device, optionally filtering -// by configuration and function. -bool FindInWebUsbAllowedOrigins( - const device::WebUsbAllowedOrigins* allowed_origins, - const GURL& origin, - base::Optional<uint8_t> configuration_value, - base::Optional<uint8_t> first_interface); + const base::Callback<void(const GURL& landing_page)>& callback); } // device diff --git a/chromium/device/usb/webusb_descriptors_fuzzer.cc b/chromium/device/usb/webusb_descriptors_fuzzer.cc index 465b63ee049..c1f62e5a6a4 100644 --- a/chromium/device/usb/webusb_descriptors_fuzzer.cc +++ b/chromium/device/usb/webusb_descriptors_fuzzer.cc @@ -22,8 +22,7 @@ TestCase* test_case = new TestCase(); namespace device { -void Done(std::unique_ptr<WebUsbAllowedOrigins> allowed_origins, - const GURL& landing_page) {} +void Done(const GURL& landing_page) {} extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { scoped_refptr<UsbDeviceHandle> device_handle = diff --git a/chromium/device/usb/webusb_descriptors_unittest.cc b/chromium/device/usb/webusb_descriptors_unittest.cc index 8350a6d107d..ecdafe5c147 100644 --- a/chromium/device/usb/webusb_descriptors_unittest.cc +++ b/chromium/device/usb/webusb_descriptors_unittest.cc @@ -37,65 +37,18 @@ const uint8_t kExampleBosDescriptor[] = { 0x9C, 0xD2, 0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F, 0x00, 0x00, 0x03, 0x06, 0x00, 0x00, 0x01, 0x00}; -const uint8_t kExampleAllowedOrigins[] = { - // Allowed origins header. - 0x07, 0x00, 0x12, 0x00, 0x01, 0x01, 0x02, - // Configuration subset header. { - 0x06, 0x01, 0x01, 0x01, 0x03, 0x04, - // Function subset header. { - 0x05, 0x02, 0x01, 0x05, 0x06 - // } - // } -}; - const uint8_t kExampleUrlDescriptor1[] = { 0x19, 0x03, 0x01, 'e', 'x', 'a', 'm', 'p', 'l', 'e', '.', 'c', 'o', 'm', '/', 'i', 'n', 'd', 'e', 'x', '.', 'h', 't', 'm', 'l'}; -const uint8_t kExampleUrlDescriptor2[] = {0x11, 0x03, 0x01, 'e', 'x', 'a', - 'm', 'p', 'l', 'e', '.', 'c', - 'o', 'm', ':', '8', '1'}; - -const uint8_t kExampleUrlDescriptor3[] = {0x11, 0x03, 0x01, 'e', 'x', 'a', - 'm', 'p', 'l', 'e', '.', 'c', - 'o', 'm', ':', '8', '2'}; - -const uint8_t kExampleUrlDescriptor4[] = {0x11, 0x03, 0x01, 'e', 'x', 'a', - 'm', 'p', 'l', 'e', '.', 'c', - 'o', 'm', ':', '8', '3'}; - -const uint8_t kExampleUrlDescriptor5[] = {0x11, 0x03, 0x01, 'e', 'x', 'a', - 'm', 'p', 'l', 'e', '.', 'c', - 'o', 'm', ':', '8', '4'}; - -const uint8_t kExampleUrlDescriptor6[] = {0x11, 0x03, 0x01, 'e', 'x', 'a', - 'm', 'p', 'l', 'e', '.', 'c', - 'o', 'm', ':', '8', '5'}; - ACTION_P2(InvokeCallback, data, length) { size_t transferred_length = std::min(length, arg7); memcpy(arg6->data(), data, transferred_length); - arg9.Run(USB_TRANSFER_COMPLETED, arg6, transferred_length); + arg9.Run(UsbTransferStatus::COMPLETED, arg6, transferred_length); } -void ExpectAllowedOriginsAndLandingPage( - std::unique_ptr<WebUsbAllowedOrigins> allowed_origins, - const GURL& landing_page) { +void ExpectLandingPage(const GURL& landing_page) { EXPECT_EQ(GURL("https://example.com/index.html"), landing_page); - ASSERT_TRUE(allowed_origins); - ASSERT_EQ(2u, allowed_origins->origins.size()); - EXPECT_EQ(GURL("https://example.com"), allowed_origins->origins[0]); - EXPECT_EQ(GURL("https://example.com:81"), allowed_origins->origins[1]); - ASSERT_EQ(1u, allowed_origins->configurations.size()); - EXPECT_EQ(GURL("https://example.com:82"), - allowed_origins->configurations[0].origins[0]); - EXPECT_EQ(GURL("https://example.com:83"), - allowed_origins->configurations[0].origins[1]); - ASSERT_EQ(1u, allowed_origins->configurations[0].functions.size()); - EXPECT_EQ(GURL("https://example.com:84"), - allowed_origins->configurations[0].functions[0].origins[0]); - EXPECT_EQ(GURL("https://example.com:85"), - allowed_origins->configurations[0].functions[0].origins[1]); } class WebUsbDescriptorsTest : public ::testing::Test {}; @@ -246,112 +199,6 @@ TEST_F(WebUsbDescriptorsTest, WebUsbPlatformCapabilityDescriptorOutOfDate) { std::vector<uint8_t>(kBuffer, kBuffer + sizeof(kBuffer)))); } -TEST_F(WebUsbDescriptorsTest, AllowedOrigins) { - WebUsbAllowedOrigins descriptor; - - ASSERT_TRUE(descriptor.Parse(std::vector<uint8_t>( - kExampleAllowedOrigins, - kExampleAllowedOrigins + sizeof(kExampleAllowedOrigins)))); - EXPECT_EQ(2u, descriptor.origin_ids.size()); - EXPECT_EQ(1, descriptor.origin_ids[0]); - EXPECT_EQ(2, descriptor.origin_ids[1]); - EXPECT_EQ(1u, descriptor.configurations.size()); - - const WebUsbConfigurationSubset& config1 = descriptor.configurations[0]; - EXPECT_EQ(2u, config1.origin_ids.size()); - EXPECT_EQ(3, config1.origin_ids[0]); - EXPECT_EQ(4, config1.origin_ids[1]); - EXPECT_EQ(1u, config1.functions.size()); - - const WebUsbFunctionSubset& function1 = config1.functions[0]; - EXPECT_EQ(2u, function1.origin_ids.size()); - EXPECT_EQ(5, function1.origin_ids[0]); - EXPECT_EQ(6, function1.origin_ids[1]); -} - -TEST_F(WebUsbDescriptorsTest, ShortDescriptorSetHeader) { - // bLength less than 5, which makes this descriptor invalid. - static const uint8_t kBuffer[] = {0x04, 0x00, 0x05, 0x00, 0x00}; - WebUsbAllowedOrigins descriptor; - ASSERT_FALSE(descriptor.Parse( - std::vector<uint8_t>(kBuffer, kBuffer + sizeof(kBuffer)))); -} - -TEST_F(WebUsbDescriptorsTest, LongDescriptorSetHeader) { - // bLength is longer than the buffer size. - static const uint8_t kBuffer[] = {0x06, 0x00, 0x05, 0x00, 0x00}; - WebUsbAllowedOrigins descriptor; - ASSERT_FALSE(descriptor.Parse( - std::vector<uint8_t>(kBuffer, kBuffer + sizeof(kBuffer)))); -} - -TEST_F(WebUsbDescriptorsTest, ShortDescriptorSet) { - // wTotalLength is shorter than bLength, making the header inconsistent. - static const uint8_t kBuffer[] = {0x05, 0x00, 0x04, 0x00, 0x00}; - WebUsbAllowedOrigins descriptor; - ASSERT_FALSE(descriptor.Parse( - std::vector<uint8_t>(kBuffer, kBuffer + sizeof(kBuffer)))); -} - -TEST_F(WebUsbDescriptorsTest, LongDescriptorSet) { - // wTotalLength is longer than the buffer size. - static const uint8_t kBuffer[] = {0x05, 0x00, 0x06, 0x00, 0x00}; - WebUsbAllowedOrigins descriptor; - ASSERT_FALSE(descriptor.Parse( - std::vector<uint8_t>(kBuffer, kBuffer + sizeof(kBuffer)))); -} - -TEST_F(WebUsbDescriptorsTest, TooManyConfigurations) { - static const uint8_t kBuffer[] = {0x05, 0x00, 0x05, 0x00, 0x01}; - WebUsbAllowedOrigins descriptor; - ASSERT_FALSE(descriptor.Parse( - std::vector<uint8_t>(kBuffer, kBuffer + sizeof(kBuffer)))); -} - -TEST_F(WebUsbDescriptorsTest, ShortConfiguration) { - // The configuration's bLength is less than 4, making it invalid. - static const uint8_t kBuffer[] = {0x05, 0x00, 0x08, 0x00, - 0x01, 0x03, 0x01, 0x01}; - WebUsbAllowedOrigins descriptor; - ASSERT_FALSE(descriptor.Parse( - std::vector<uint8_t>(kBuffer, kBuffer + sizeof(kBuffer)))); -} - -TEST_F(WebUsbDescriptorsTest, LongConfiguration) { - // The configuration's bLength is longer than the buffer. - static const uint8_t kBuffer[] = {0x05, 0x00, 0x09, 0x00, 0x01, - 0x05, 0x01, 0x01, 0x00}; - WebUsbAllowedOrigins descriptor; - ASSERT_FALSE(descriptor.Parse( - std::vector<uint8_t>(kBuffer, kBuffer + sizeof(kBuffer)))); -} - -TEST_F(WebUsbDescriptorsTest, TooManyFunctions) { - static const uint8_t kBuffer[] = {0x05, 0x00, 0x09, 0x00, 0x01, - 0x04, 0x01, 0x01, 0x01}; - WebUsbAllowedOrigins descriptor; - ASSERT_FALSE(descriptor.Parse( - std::vector<uint8_t>(kBuffer, kBuffer + sizeof(kBuffer)))); -} - -TEST_F(WebUsbDescriptorsTest, ShortFunction) { - // The function's bLength is less than 3, making it invalid. - static const uint8_t kBuffer[] = {0x05, 0x00, 0x0B, 0x00, 0x01, 0x04, - 0x01, 0x01, 0x01, 0x02, 0x02}; - WebUsbAllowedOrigins descriptor; - ASSERT_FALSE(descriptor.Parse( - std::vector<uint8_t>(kBuffer, kBuffer + sizeof(kBuffer)))); -} - -TEST_F(WebUsbDescriptorsTest, LongFunction) { - // The function's bLength is longer than the buffer. - static const uint8_t kBuffer[] = {0x05, 0x00, 0x0C, 0x00, 0x01, 0x04, - 0x01, 0x01, 0x01, 0x04, 0x02, 0x01}; - WebUsbAllowedOrigins descriptor; - ASSERT_FALSE(descriptor.Parse( - std::vector<uint8_t>(kBuffer, kBuffer + sizeof(kBuffer)))); -} - TEST_F(WebUsbDescriptorsTest, UrlDescriptor) { GURL url; ASSERT_TRUE(ParseWebUsbUrlDescriptor( @@ -407,58 +254,22 @@ TEST_F(WebUsbDescriptorsTest, ReadDescriptors) { new MockUsbDeviceHandle(nullptr)); EXPECT_CALL(*device_handle, - ControlTransfer(USB_DIRECTION_INBOUND, UsbDeviceHandle::STANDARD, - UsbDeviceHandle::DEVICE, 0x06, 0x0F00, 0x0000, _, - _, _, _)) + ControlTransfer(UsbTransferDirection::INBOUND, + UsbControlTransferType::STANDARD, + UsbControlTransferRecipient::DEVICE, 0x06, 0x0F00, + 0x0000, _, _, _, _)) .Times(2) .WillRepeatedly( InvokeCallback(kExampleBosDescriptor, sizeof(kExampleBosDescriptor))); EXPECT_CALL(*device_handle, - ControlTransfer(USB_DIRECTION_INBOUND, UsbDeviceHandle::VENDOR, - UsbDeviceHandle::DEVICE, 0x42, 0x0000, 0x0001, _, - _, _, _)) - .Times(2) - .WillRepeatedly(InvokeCallback(kExampleAllowedOrigins, - sizeof(kExampleAllowedOrigins))); - EXPECT_CALL(*device_handle, - ControlTransfer(USB_DIRECTION_INBOUND, UsbDeviceHandle::VENDOR, - UsbDeviceHandle::DEVICE, 0x42, 0x0001, 0x0002, _, - _, _, _)) + ControlTransfer(UsbTransferDirection::INBOUND, + UsbControlTransferType::VENDOR, + UsbControlTransferRecipient::DEVICE, 0x42, 0x0001, + 0x0002, _, _, _, _)) .WillOnce(InvokeCallback(kExampleUrlDescriptor1, sizeof(kExampleUrlDescriptor1))); - EXPECT_CALL(*device_handle, - ControlTransfer(USB_DIRECTION_INBOUND, UsbDeviceHandle::VENDOR, - UsbDeviceHandle::DEVICE, 0x42, 0x0002, 0x0002, _, - _, _, _)) - .WillOnce(InvokeCallback(kExampleUrlDescriptor2, - sizeof(kExampleUrlDescriptor2))); - EXPECT_CALL(*device_handle, - ControlTransfer(USB_DIRECTION_INBOUND, UsbDeviceHandle::VENDOR, - UsbDeviceHandle::DEVICE, 0x42, 0x0003, 0x0002, _, - _, _, _)) - .WillOnce(InvokeCallback(kExampleUrlDescriptor3, - sizeof(kExampleUrlDescriptor3))); - EXPECT_CALL(*device_handle, - ControlTransfer(USB_DIRECTION_INBOUND, UsbDeviceHandle::VENDOR, - UsbDeviceHandle::DEVICE, 0x42, 0x0004, 0x0002, _, - _, _, _)) - .WillOnce(InvokeCallback(kExampleUrlDescriptor4, - sizeof(kExampleUrlDescriptor4))); - EXPECT_CALL(*device_handle, - ControlTransfer(USB_DIRECTION_INBOUND, UsbDeviceHandle::VENDOR, - UsbDeviceHandle::DEVICE, 0x42, 0x0005, 0x0002, _, - _, _, _)) - .WillOnce(InvokeCallback(kExampleUrlDescriptor5, - sizeof(kExampleUrlDescriptor5))); - EXPECT_CALL(*device_handle, - ControlTransfer(USB_DIRECTION_INBOUND, UsbDeviceHandle::VENDOR, - UsbDeviceHandle::DEVICE, 0x42, 0x0006, 0x0002, _, - _, _, _)) - .WillOnce(InvokeCallback(kExampleUrlDescriptor6, - sizeof(kExampleUrlDescriptor6))); - - ReadWebUsbDescriptors(device_handle, - base::Bind(&ExpectAllowedOriginsAndLandingPage)); + + ReadWebUsbDescriptors(device_handle, base::Bind(&ExpectLandingPage)); } } // namespace diff --git a/chromium/device/vibration/BUILD.gn b/chromium/device/vibration/BUILD.gn deleted file mode 100644 index d9a9913a214..00000000000 --- a/chromium/device/vibration/BUILD.gn +++ /dev/null @@ -1,34 +0,0 @@ -# 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. - -import("//build/config/features.gni") -import("//mojo/public/tools/bindings/mojom.gni") - -# On android, VibrationManager mojo interface is implemented directly in Java. -if (!is_android) { - component("vibration") { - output_name = "device_vibration" - - sources = [ - "vibration_export.h", - "vibration_manager_impl.h", - "vibration_manager_impl_default.cc", - ] - - defines = [ "DEVICE_VIBRATION_IMPLEMENTATION" ] - - deps = [ - ":mojo_bindings", - "//base", - "//base/third_party/dynamic_annotations", - "//mojo/public/cpp/bindings", - ] - } -} - -mojom("mojo_bindings") { - sources = [ - "vibration_manager.mojom", - ] -} diff --git a/chromium/device/vibration/OWNERS b/chromium/device/vibration/OWNERS deleted file mode 100644 index 1eb30872c04..00000000000 --- a/chromium/device/vibration/OWNERS +++ /dev/null @@ -1,6 +0,0 @@ -timvolodine@chromium.org - -per-file *.mojom=set noparent -per-file *.mojom=file://ipc/SECURITY_OWNERS - -# COMPONENT: Blink>Vibration diff --git a/chromium/device/vibration/android/BUILD.gn b/chromium/device/vibration/android/BUILD.gn deleted file mode 100644 index 5b3ae0a0a33..00000000000 --- a/chromium/device/vibration/android/BUILD.gn +++ /dev/null @@ -1,26 +0,0 @@ -# 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. - -import("//build/config/android/config.gni") -import("//build/config/android/rules.gni") - -generate_jni("vibration_jni_headers") { - sources = [ - "java/src/org/chromium/device/vibration/VibrationManagerImpl.java", - ] - jni_package = "vibration" -} - -android_library("vibration_manager_java") { - java_files = - [ "java/src/org/chromium/device/vibration/VibrationManagerImpl.java" ] - - deps = [ - "//base:base_java", - "//device/vibration:mojo_bindings_java", - "//mojo/public/java:bindings_java", - "//mojo/public/java:system_java", - "//services/service_manager/public/java:service_manager_java", - ] -} diff --git a/chromium/device/vibration/vibration_export.h b/chromium/device/vibration/vibration_export.h deleted file mode 100644 index 64b85fb81bb..00000000000 --- a/chromium/device/vibration/vibration_export.h +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) 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 DEVICE_VIBRATION_DEVICE_VIBRATION_EXPORT_H_ -#define DEVICE_VIBRATION_DEVICE_VIBRATION_EXPORT_H_ - -#if defined(COMPONENT_BUILD) -#if defined(WIN32) - -#if defined(DEVICE_VIBRATION_IMPLEMENTATION) -#define DEVICE_VIBRATION_EXPORT __declspec(dllexport) -#else -#define DEVICE_VIBRATION_EXPORT __declspec(dllimport) -#endif // defined(DEVICE_VIBRATION_IMPLEMENTATION) - -#else // defined(WIN32) -#if defined(DEVICE_VIBRATION_IMPLEMENTATION) -#define DEVICE_VIBRATION_EXPORT __attribute__((visibility("default"))) -#else -#define DEVICE_VIBRATION_EXPORT -#endif -#endif - -#else // defined(COMPONENT_BUILD) -#define DEVICE_VIBRATION_EXPORT -#endif - -#endif // DEVICE_VIBRATION_DEVICE_VIBRATION_EXPORT_H_ diff --git a/chromium/device/vibration/vibration_manager.mojom b/chromium/device/vibration/vibration_manager.mojom deleted file mode 100644 index a933301134c..00000000000 --- a/chromium/device/vibration/vibration_manager.mojom +++ /dev/null @@ -1,11 +0,0 @@ -// 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. - -module device.mojom; - -interface VibrationManager { - // TODO(mvanouwerkerk): Add something like StructTraits to validate arguments. - Vibrate(int64 milliseconds) => (); - Cancel() => (); -}; diff --git a/chromium/device/vibration/vibration_manager_impl.h b/chromium/device/vibration/vibration_manager_impl.h deleted file mode 100644 index 75260a20ed1..00000000000 --- a/chromium/device/vibration/vibration_manager_impl.h +++ /dev/null @@ -1,24 +0,0 @@ -// 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 DEVICE_VIBRATION_VIBRATION_MANAGER_IMPL_H_ -#define DEVICE_VIBRATION_VIBRATION_MANAGER_IMPL_H_ - -#include "device/vibration/vibration_export.h" -#include "device/vibration/vibration_manager.mojom.h" - -namespace device { - -class VibrationManagerImpl { - public: - DEVICE_VIBRATION_EXPORT static void Create( - mojo::InterfaceRequest<mojom::VibrationManager> request); - - DEVICE_VIBRATION_EXPORT static int64_t milli_seconds_for_testing_; - DEVICE_VIBRATION_EXPORT static bool cancelled_for_testing_; -}; - -} // namespace device - -#endif // DEVICE_VIBRATION_VIBRATION_MANAGER_IMPL_H_ diff --git a/chromium/device/vibration/vibration_manager_impl_default.cc b/chromium/device/vibration/vibration_manager_impl_default.cc deleted file mode 100644 index c073f69a1f0..00000000000 --- a/chromium/device/vibration/vibration_manager_impl_default.cc +++ /dev/null @@ -1,43 +0,0 @@ -// 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 <stdint.h> -#include <utility> - -#include "base/memory/ptr_util.h" -#include "device/vibration/vibration_manager_impl.h" -#include "mojo/public/cpp/bindings/strong_binding.h" - -namespace device { - -int64_t VibrationManagerImpl::milli_seconds_for_testing_ = -1; -bool VibrationManagerImpl::cancelled_for_testing_ = false; - -namespace { - -class VibrationManagerEmptyImpl : public mojom::VibrationManager { - public: - VibrationManagerEmptyImpl() {} - ~VibrationManagerEmptyImpl() override {} - - void Vibrate(int64_t milliseconds, const VibrateCallback& callback) override { - VibrationManagerImpl::milli_seconds_for_testing_ = milliseconds; - callback.Run(); - } - - void Cancel(const CancelCallback& callback) override { - VibrationManagerImpl::cancelled_for_testing_ = true; - callback.Run(); - } -}; - -} // namespace - -// static -void VibrationManagerImpl::Create(mojom::VibrationManagerRequest request) { - mojo::MakeStrongBinding(base::MakeUnique<VibrationManagerEmptyImpl>(), - std::move(request)); -} - -} // namespace device diff --git a/chromium/device/vr/BUILD.gn b/chromium/device/vr/BUILD.gn index 2e40989ddf2..be3ea9b7d32 100644 --- a/chromium/device/vr/BUILD.gn +++ b/chromium/device/vr/BUILD.gn @@ -2,42 +2,25 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("features.gni") -import("//build/buildflag_header.gni") +import("features/features.gni") import("//mojo/public/tools/bindings/mojom.gni") if (is_android) { import("//build/config/android/rules.gni") # For generate_jni(). } -# Generate a buildflag header for compile-time checking of WebVR support. -buildflag_header("features") { - header = "features.h" - flags = [ - "ENABLE_VR=$enable_vr", - "ENABLE_OPENVR=$enable_openvr", - ] -} - -component("vr") { - output_name = "device_vr" - - sources = [ - "vr_export.h", - ] - defines = [ "DEVICE_VR_IMPLEMENTATION" ] - deps = [ - ":features", - ":mojo_bindings", - ] +if (enable_vr) { + component("vr") { + output_name = "device_vr" - if (!enable_vr) { - sources += [ - # We need to include an empty .cc file so that mac and windows don't fall over when trying to - # compile this when webvr is disabled. - "empty.cc", + sources = [ + "vr_export.h", + ] + defines = [ "DEVICE_VR_IMPLEMENTATION" ] + deps = [ + ":mojo_bindings", + "features", ] - } else { sources += [ "vr_device.cc", "vr_device.h", @@ -46,7 +29,6 @@ component("vr") { "vr_device_provider.h", "vr_display_impl.cc", "vr_display_impl.h", - "vr_export.h", "vr_math.cc", "vr_math.h", "vr_service_impl.cc", @@ -63,6 +45,9 @@ component("vr") { if (is_android && (current_cpu == "arm" || current_cpu == "arm64")) { sources += [ + "android/gvr/cardboard_gamepad_data_fetcher.cc", + "android/gvr/cardboard_gamepad_data_fetcher.h", + "android/gvr/cardboard_gamepad_data_provider.h", "android/gvr/gvr_delegate.cc", "android/gvr/gvr_delegate.h", "android/gvr/gvr_delegate_provider.cc", @@ -78,6 +63,7 @@ component("vr") { deps += [ "//device/gamepad", + "//device/gamepad/public/cpp:shared_with_blink", "//third_party/WebKit/public:blink_headers", ] ldflags = [ "-landroid" ] @@ -86,16 +72,21 @@ component("vr") { } if (enable_openvr) { - deps += [ "//third_party/openvr:openvr" ] + deps += [ + "//device/gamepad", + "//third_party/openvr:openvr", + ] sources += [ "openvr/openvr_device.cc", + "openvr/openvr_device.h", "openvr/openvr_device_provider.cc", + "openvr/openvr_device_provider.h", + "openvr/openvr_gamepad_data_fetcher.cc", + "openvr/openvr_gamepad_data_fetcher.h", ] } } -} -if (enable_vr) { static_library("fakes") { testonly = true @@ -117,9 +108,20 @@ if (enable_vr) { "//mojo/public/cpp/bindings", ] } +} else { + source_set("vr") { + # We need to include an empty .cc file so that mac and windows don't fall over when trying to + # compile this when webvr is disabled. + sources = [ + "empty.cc", + ] + } } -mojom("mojo_bindings") { +mojom_component("mojo_bindings") { + output_prefix = "device_vr_mojo_bindings" + macro_prefix = "DEVICE_VR_MOJO_BINDINGS" + sources = [ "vr_service.mojom", ] @@ -129,7 +131,6 @@ mojom("mojo_bindings") { "//mojo/common:common_custom_types", ] - export_class_attribute = "DEVICE_VR_EXPORT" - export_define = "DEVICE_VR_IMPLEMENTATION=1" - export_header = "device/vr/vr_export.h" + # TODO(crbug.com/714018): Convert the implementation to use OnceCallback. + use_once_callback = false } diff --git a/chromium/device/vr/DEPS b/chromium/device/vr/DEPS index c1e426fb2d8..eca72cd833e 100644 --- a/chromium/device/vr/DEPS +++ b/chromium/device/vr/DEPS @@ -1,7 +1,7 @@ include_rules = [ + "+device/gamepad/public/cpp/gamepads.h", "+gpu/command_buffer/common/mailbox_holder.h", "+jni", - "+third_party/WebKit/public/platform/WebGamepads.h", "+third_party/WebKit/public/platform/modules/vr/vr_service.mojom.h", "+third_party/gvr-android-sdk/src", "+third_party/openvr/src/headers/openvr.h", diff --git a/chromium/device/vr/android/gvr/cardboard_gamepad_data_fetcher.cc b/chromium/device/vr/android/gvr/cardboard_gamepad_data_fetcher.cc new file mode 100644 index 00000000000..4ad10d9624e --- /dev/null +++ b/chromium/device/vr/android/gvr/cardboard_gamepad_data_fetcher.cc @@ -0,0 +1,111 @@ +// Copyright 2017 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 "device/vr/android/gvr/cardboard_gamepad_data_fetcher.h" + +#include "base/memory/ptr_util.h" +#include "base/strings/utf_string_conversions.h" +#include "device/gamepad/public/cpp/gamepads.h" +#include "device/vr/android/gvr/cardboard_gamepad_data_provider.h" +#include "device/vr/vr_types.h" + +namespace device { + +namespace { + +void CopyToUString(UChar* dest, size_t dest_length, base::string16 src) { + static_assert(sizeof(base::string16::value_type) == sizeof(UChar), + "Mismatched string16/WebUChar size."); + + const size_t str_to_copy = std::min(src.size(), dest_length - 1); + memcpy(dest, src.data(), str_to_copy * sizeof(base::string16::value_type)); + dest[str_to_copy] = 0; +} + +} // namespace + +CardboardGamepadDataFetcher::Factory::Factory( + CardboardGamepadDataProvider* data_provider, + unsigned int display_id) + : data_provider_(data_provider), display_id_(display_id) { + DVLOG(1) << __FUNCTION__ << "=" << this; +} + +CardboardGamepadDataFetcher::Factory::~Factory() { + DVLOG(1) << __FUNCTION__ << "=" << this; +} + +std::unique_ptr<GamepadDataFetcher> +CardboardGamepadDataFetcher::Factory::CreateDataFetcher() { + return base::MakeUnique<CardboardGamepadDataFetcher>(data_provider_, + display_id_); +} + +GamepadSource CardboardGamepadDataFetcher::Factory::source() { + return GAMEPAD_SOURCE_CARDBOARD; +} + +CardboardGamepadDataFetcher::CardboardGamepadDataFetcher( + CardboardGamepadDataProvider* data_provider, + unsigned int display_id) + : display_id_(display_id) { + // Called on UI thread. + DVLOG(1) << __FUNCTION__ << "=" << this; + data_provider->RegisterCardboardGamepadDataFetcher(this); +} + +CardboardGamepadDataFetcher::~CardboardGamepadDataFetcher() { + DVLOG(1) << __FUNCTION__ << "=" << this; +} + +GamepadSource CardboardGamepadDataFetcher::source() { + return GAMEPAD_SOURCE_CARDBOARD; +} + +void CardboardGamepadDataFetcher::OnAddedToProvider() { + PauseHint(false); +} + +void CardboardGamepadDataFetcher::SetGamepadData(CardboardGamepadData data) { + // Called from UI thread. + gamepad_data_ = data; +} + +void CardboardGamepadDataFetcher::GetGamepadData(bool devices_changed_hint) { + // Called from gamepad polling thread. + PadState* state = GetPadState(0); + if (!state) + return; + + CardboardGamepadData provided_data = gamepad_data_; + + Gamepad& pad = state->data; + if (state->active_state == GAMEPAD_NEWLY_ACTIVE) { + // This is the first time we've seen this device, so do some one-time + // initialization + pad.connected = true; + CopyToUString(pad.id, Gamepad::kIdLengthCap, + base::UTF8ToUTF16("Cardboard Button")); + CopyToUString(pad.mapping, Gamepad::kMappingLengthCap, + base::UTF8ToUTF16("")); + pad.buttons_length = 1; + pad.axes_length = 0; + + pad.display_id = display_id_; + + pad.hand = GamepadHand::kNone; + } + + pad.timestamp = provided_data.timestamp; + + bool pressed = provided_data.is_screen_touching; + pad.buttons[0].touched = pressed; + pad.buttons[0].pressed = pressed; + pad.buttons[0].value = pressed ? 1.0f : 0.0f; + pad.pose.not_null = false; +} + +void CardboardGamepadDataFetcher::PauseHint(bool paused) {} + +} // namespace device diff --git a/chromium/device/vr/android/gvr/cardboard_gamepad_data_fetcher.h b/chromium/device/vr/android/gvr/cardboard_gamepad_data_fetcher.h new file mode 100644 index 00000000000..0b6193faf8d --- /dev/null +++ b/chromium/device/vr/android/gvr/cardboard_gamepad_data_fetcher.h @@ -0,0 +1,51 @@ +// Copyright 2017 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 DEVICE_VR_ANDROID_CARDBOARD_GAMEPAD_DATA_FETCHER_H_ +#define DEVICE_VR_ANDROID_CARDBOARD_GAMEPAD_DATA_FETCHER_H_ + +#include <string> + +#include "device/gamepad/gamepad_data_fetcher.h" +#include "device/vr/android/gvr/cardboard_gamepad_data_provider.h" +#include "device/vr/vr_export.h" + +namespace device { + +class DEVICE_VR_EXPORT CardboardGamepadDataFetcher : public GamepadDataFetcher { + public: + class Factory : public GamepadDataFetcherFactory { + public: + Factory(CardboardGamepadDataProvider*, unsigned int display_id); + ~Factory() override; + std::unique_ptr<GamepadDataFetcher> CreateDataFetcher() override; + GamepadSource source() override; + + private: + CardboardGamepadDataProvider* data_provider_; + unsigned int display_id_; + }; + + CardboardGamepadDataFetcher(CardboardGamepadDataProvider*, + unsigned int display_id); + ~CardboardGamepadDataFetcher() override; + + GamepadSource source() override; + + void GetGamepadData(bool devices_changed_hint) override; + void PauseHint(bool paused) override; + void OnAddedToProvider() override; + + // Called from CardboardGamepadDataProvider + void SetGamepadData(CardboardGamepadData); + + private: + unsigned int display_id_; + CardboardGamepadData gamepad_data_; + + DISALLOW_COPY_AND_ASSIGN(CardboardGamepadDataFetcher); +}; + +} // namespace device +#endif // DEVICE_VR_ANDROID_CARDBOARD_GAMEPAD_DATA_FETCHER_H_ diff --git a/chromium/device/vr/android/gvr/cardboard_gamepad_data_provider.h b/chromium/device/vr/android/gvr/cardboard_gamepad_data_provider.h new file mode 100644 index 00000000000..1b5d5e9e8aa --- /dev/null +++ b/chromium/device/vr/android/gvr/cardboard_gamepad_data_provider.h @@ -0,0 +1,56 @@ +// Copyright 2017 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 DEVICE_VR_ANDROID_CARDBOARD_GAMEPAD_DATA_PROVIDER_H +#define DEVICE_VR_ANDROID_CARDBOARD_GAMEPAD_DATA_PROVIDER_H + +#include "device/vr/vr_types.h" + +namespace device { + +class CardboardGamepadDataFetcher; + +// Filled in by vr_shell and consumed by CardboardGamepadDataFetcher. +struct CardboardGamepadData { + int64_t timestamp; + bool is_screen_touching; +}; + +// This class exposes Cardboard controller (screen touch) data to the gamepad +// API. Data is reported by VrShell, which implements the +// CardboardGamepadDataProvider interface. +// +// More specifically, here's the lifecycle, assuming VrShell +// implements GvrGamepadDataProvider: +// +// - VrShell creates CardboardGamepadDataFetcherFactory during initialization if +// a cardboard is in use, or when WebVR presentation starts. +// +// - CardboardGamepadDataFetcherFactory creates CardboardGamepadDataFetcher. +// +// - CardboardGamepadDataFetcher registers itself with VrShell via +// VrShell::RegisterCardboardGamepadDataFetcher. +// +// - While presenting, VrShell::OnTouch calls +// CardboardGamepadDataFetcher->SetGamepadData to push button state, +// CardboardGamepadDataFetcher::GetGamepadData returns this when polled. +// +// - VrShell starts executing its destructor or WebVR presentation ends. +// +// - VrShell destructor unregisters CardboardGamepadDataFetcherFactory. +// +// - CardboardGamepadDataFetcherFactory destructor destroys +// CardboardGamepadDataFetcher. +// +class CardboardGamepadDataProvider { + public: + // Called by the gamepad data fetcher constructor to register itself + // for receiving data via SetGamepadData. The fetcher must remain + // alive while the provider is calling SetGamepadData on it. + virtual void RegisterCardboardGamepadDataFetcher( + CardboardGamepadDataFetcher*) = 0; +}; + +} // namespace device +#endif // DEVICE_VR_ANDROID_CARDBOARD_GAMEPAD_DATA_PROVIDER_H diff --git a/chromium/device/vr/android/gvr/gvr_delegate.cc b/chromium/device/vr/android/gvr/gvr_delegate.cc index 9b05efcefee..ceb673c389c 100644 --- a/chromium/device/vr/android/gvr/gvr_delegate.cc +++ b/chromium/device/vr/android/gvr/gvr_delegate.cc @@ -118,9 +118,10 @@ mojom::VRPosePtr GvrDelegate::VRPosePtrFromGvrPose(const vr::Mat4f& head_mat) { /* static */ void GvrDelegate::GetGvrPoseWithNeckModel(gvr::GvrApi* gvr_api, - vr::Mat4f* out) { + vr::Mat4f* out, + int64_t prediction_time) { gvr::ClockTimePoint target_time = gvr::GvrApi::GetTimePointNow(); - target_time.monotonic_system_time_nanos += kPredictionTimeWithoutVsyncNanos; + target_time.monotonic_system_time_nanos += prediction_time; gvr::Mat4f head_mat = gvr_api->ApplyNeckModel( gvr_api->GetHeadSpaceFromStartSpaceRotation(target_time), 1.0f); @@ -129,11 +130,18 @@ void GvrDelegate::GetGvrPoseWithNeckModel(gvr::GvrApi* gvr_api, } /* static */ +void GvrDelegate::GetGvrPoseWithNeckModel(gvr::GvrApi* gvr_api, + vr::Mat4f* out) { + GetGvrPoseWithNeckModel(gvr_api, out, kPredictionTimeWithoutVsyncNanos); +} + +/* static */ mojom::VRPosePtr GvrDelegate::GetVRPosePtrWithNeckModel( gvr::GvrApi* gvr_api, - vr::Mat4f* head_mat_out) { + vr::Mat4f* head_mat_out, + int64_t prediction_time) { gvr::ClockTimePoint target_time = gvr::GvrApi::GetTimePointNow(); - target_time.monotonic_system_time_nanos += kPredictionTimeWithoutVsyncNanos; + target_time.monotonic_system_time_nanos += prediction_time; gvr::Mat4f gvr_head_mat = gvr_api->ApplyNeckModel( gvr_api->GetHeadSpaceFromStartSpaceRotation(target_time), 1.0f); @@ -166,6 +174,14 @@ mojom::VRPosePtr GvrDelegate::GetVRPosePtrWithNeckModel( } /* static */ +mojom::VRPosePtr GvrDelegate::GetVRPosePtrWithNeckModel( + gvr::GvrApi* gvr_api, + vr::Mat4f* head_mat_out) { + return GetVRPosePtrWithNeckModel(gvr_api, head_mat_out, + kPredictionTimeWithoutVsyncNanos); +} + +/* static */ gfx::Size GvrDelegate::GetRecommendedWebVrSize(gvr::GvrApi* gvr_api) { // Pick a reasonable default size for the WebVR transfer surface // based on a downscaled 1:1 render resolution. This size will also diff --git a/chromium/device/vr/android/gvr/gvr_delegate.h b/chromium/device/vr/android/gvr/gvr_delegate.h index d51581937f0..e7a2ae2902b 100644 --- a/chromium/device/vr/android/gvr/gvr_delegate.h +++ b/chromium/device/vr/android/gvr/gvr_delegate.h @@ -22,8 +22,14 @@ namespace device { class DEVICE_VR_EXPORT GvrDelegate { public: static mojom::VRPosePtr VRPosePtrFromGvrPose(const vr::Mat4f& head_mat); + static void GetGvrPoseWithNeckModel(gvr::GvrApi* gvr_api, + vr::Mat4f* out, + int64_t prediction_time); static void GetGvrPoseWithNeckModel(gvr::GvrApi* gvr_api, vr::Mat4f* out); static mojom::VRPosePtr GetVRPosePtrWithNeckModel(gvr::GvrApi* gvr_api, + vr::Mat4f* head_mat_out, + int64_t prediction_time); + static mojom::VRPosePtr GetVRPosePtrWithNeckModel(gvr::GvrApi* gvr_api, vr::Mat4f* head_mat_out); static gfx::Size GetRecommendedWebVrSize(gvr::GvrApi* gvr_api); static mojom::VRDisplayInfoPtr CreateVRDisplayInfo(gvr::GvrApi* gvr_api, diff --git a/chromium/device/vr/android/gvr/gvr_device.cc b/chromium/device/vr/android/gvr/gvr_device.cc index 17a824a47d4..e86d2f1d7a5 100644 --- a/chromium/device/vr/android/gvr/gvr_device.cc +++ b/chromium/device/vr/android/gvr/gvr_device.cc @@ -36,7 +36,13 @@ void GvrDevice::CreateVRDisplayInfo( void GvrDevice::RequestPresent(mojom::VRSubmitFrameClientPtr submit_client, const base::Callback<void(bool)>& callback) { - gvr_provider_->RequestPresent(std::move(submit_client), callback); + GvrDelegateProvider* delegate_provider = gvr_provider_->GetDelegateProvider(); + if (!delegate_provider) + return callback.Run(false); + + // RequestWebVRPresent is async as we may trigger a DON flow that pauses + // Chrome. + delegate_provider->RequestWebVRPresent(std::move(submit_client), callback); } void GvrDevice::SetSecureOrigin(bool secure_origin) { @@ -47,7 +53,9 @@ void GvrDevice::SetSecureOrigin(bool secure_origin) { } void GvrDevice::ExitPresent() { - gvr_provider_->ExitPresent(); + GvrDelegateProvider* delegate_provider = gvr_provider_->GetDelegateProvider(); + if (delegate_provider) + delegate_provider->ExitWebVRPresent(); OnExitPresent(); } diff --git a/chromium/device/vr/android/gvr/gvr_device_provider.cc b/chromium/device/vr/android/gvr/gvr_device_provider.cc index e993d6d2134..99550786864 100644 --- a/chromium/device/vr/android/gvr/gvr_device_provider.cc +++ b/chromium/device/vr/android/gvr/gvr_device_provider.cc @@ -4,19 +4,9 @@ #include "device/vr/android/gvr/gvr_device_provider.h" -#include <jni.h> - -#include "base/android/context_utils.h" -#include "base/android/jni_android.h" -#include "base/android/jni_utils.h" -#include "base/android/scoped_java_ref.h" #include "device/vr/android/gvr/gvr_delegate_provider.h" #include "device/vr/android/gvr/gvr_device.h" #include "device/vr/vr_device.h" -#include "device/vr/vr_device_manager.h" -#include "device/vr/vr_service.mojom.h" -#include "third_party/gvr-android-sdk/src/libraries/headers/vr/gvr/capi/include/gvr.h" -#include "third_party/gvr-android-sdk/src/libraries/headers/vr/gvr/capi/include/gvr_controller.h" namespace device { @@ -51,25 +41,6 @@ void GvrDeviceProvider::Initialize(GvrDelegateProvider* provider) { provider->SetDeviceProvider(this); } -void GvrDeviceProvider::RequestPresent( - mojom::VRSubmitFrameClientPtr submit_client, - const base::Callback<void(bool)>& callback) { - GvrDelegateProvider* delegate_provider = GetDelegateProvider(); - if (!delegate_provider) - return callback.Run(false); - - // RequestWebVRPresent is async as we may trigger a DON flow that pauses - // Chrome. - delegate_provider->RequestWebVRPresent(std::move(submit_client), callback); -} - -// VR presentation exit requested by the API. -void GvrDeviceProvider::ExitPresent() { - GvrDelegateProvider* delegate_provider = GetDelegateProvider(); - if (delegate_provider) - delegate_provider->ExitWebVRPresent(); -} - void GvrDeviceProvider::SetListeningForActivate(bool listening) { GvrDelegateProvider* delegate_provider = GetDelegateProvider(); if (!delegate_provider) diff --git a/chromium/device/vr/android/gvr/gvr_device_provider.h b/chromium/device/vr/android/gvr/gvr_device_provider.h index d215e603b89..57d23238308 100644 --- a/chromium/device/vr/android/gvr/gvr_device_provider.h +++ b/chromium/device/vr/android/gvr/gvr_device_provider.h @@ -7,11 +7,9 @@ #include <memory> -#include "base/callback.h" #include "base/macros.h" #include "device/vr/vr_device_provider.h" #include "device/vr/vr_export.h" -#include "device/vr/vr_service.mojom.h" namespace device { @@ -28,11 +26,6 @@ class DEVICE_VR_EXPORT GvrDeviceProvider : public VRDeviceProvider { void SetListeningForActivate(bool listening) override; - // Called from GvrDevice. - void RequestPresent(mojom::VRSubmitFrameClientPtr submit_client, - const base::Callback<void(bool)>& callback); - void ExitPresent(); - device::GvrDelegateProvider* GetDelegateProvider(); GvrDevice* Device() { return vr_device_.get(); } diff --git a/chromium/device/vr/android/gvr/gvr_gamepad_data_fetcher.cc b/chromium/device/vr/android/gvr/gvr_gamepad_data_fetcher.cc index a18b6c6cae3..a308caf13d5 100644 --- a/chromium/device/vr/android/gvr/gvr_gamepad_data_fetcher.cc +++ b/chromium/device/vr/android/gvr/gvr_gamepad_data_fetcher.cc @@ -6,18 +6,16 @@ #include "base/memory/ptr_util.h" #include "base/strings/utf_string_conversions.h" +#include "device/gamepad/public/cpp/gamepads.h" #include "device/vr/android/gvr/gvr_gamepad_data_provider.h" #include "device/vr/vr_types.h" -#include "third_party/WebKit/public/platform/WebGamepads.h" namespace device { namespace { -void CopyToWebUString(blink::WebUChar* dest, - size_t dest_length, - base::string16 src) { - static_assert(sizeof(base::string16::value_type) == sizeof(blink::WebUChar), +void CopyToUString(UChar* dest, size_t dest_length, base::string16 src) { + static_assert(sizeof(base::string16::value_type) == sizeof(UChar), "Mismatched string16/WebUChar size."); const size_t str_to_copy = std::min(src.size(), dest_length - 1); @@ -27,8 +25,6 @@ void CopyToWebUString(blink::WebUChar* dest, } // namespace -using namespace blink; - GvrGamepadDataFetcher::Factory::Factory(GvrGamepadDataProvider* data_provider, unsigned int display_id) : data_provider_(data_provider), display_id_(display_id) { @@ -51,10 +47,10 @@ GamepadSource GvrGamepadDataFetcher::Factory::source() { GvrGamepadDataFetcher::GvrGamepadDataFetcher( GvrGamepadDataProvider* data_provider, unsigned int display_id) - : display_id_(display_id) { + : display_id_(display_id), gamepad_data_({}) { // Called on UI thread. DVLOG(1) << __FUNCTION__ << "=" << this; - data_provider->RegisterGamepadDataFetcher(this); + data_provider->RegisterGvrGamepadDataFetcher(this); } GvrGamepadDataFetcher::~GvrGamepadDataFetcher() { @@ -85,24 +81,24 @@ void GvrGamepadDataFetcher::GetGamepadData(bool devices_changed_hint) { // TODO(bajones): ensure consistency? GvrGamepadData provided_data = gamepad_data_; - WebGamepad& pad = state->data; + Gamepad& pad = state->data; if (state->active_state == GAMEPAD_NEWLY_ACTIVE) { // This is the first time we've seen this device, so do some one-time // initialization - pad.connected = true; - CopyToWebUString(pad.id, WebGamepad::kIdLengthCap, - base::UTF8ToUTF16("Daydream Controller")); - CopyToWebUString(pad.mapping, WebGamepad::kMappingLengthCap, - base::UTF8ToUTF16("")); + CopyToUString(pad.id, Gamepad::kIdLengthCap, + base::UTF8ToUTF16("Daydream Controller")); + CopyToUString(pad.mapping, Gamepad::kMappingLengthCap, + base::UTF8ToUTF16("")); pad.buttons_length = 1; pad.axes_length = 2; pad.display_id = display_id_; pad.hand = - provided_data.right_handed ? kGamepadHandRight : kGamepadHandLeft; + provided_data.right_handed ? GamepadHand::kRight : GamepadHand::kLeft; } + pad.connected = provided_data.connected; pad.timestamp = provided_data.timestamp; if (provided_data.is_touching) { diff --git a/chromium/device/vr/android/gvr/gvr_gamepad_data_provider.h b/chromium/device/vr/android/gvr/gvr_gamepad_data_provider.h index fcfcf68b94d..d32cee019a0 100644 --- a/chromium/device/vr/android/gvr/gvr_gamepad_data_provider.h +++ b/chromium/device/vr/android/gvr/gvr_gamepad_data_provider.h @@ -22,6 +22,7 @@ struct GvrGamepadData { bool is_touching; bool controller_button_pressed; bool right_handed; + bool connected; }; // This class exposes GVR controller data to the gamepad API. Data is @@ -60,7 +61,7 @@ class GvrGamepadDataProvider { // Called by the gamepad data fetcher constructor to register itself // for receiving data via SetGamepadData. The fetcher must remain // alive while the provider is calling SetGamepadData on it. - virtual void RegisterGamepadDataFetcher(GvrGamepadDataFetcher*) = 0; + virtual void RegisterGvrGamepadDataFetcher(GvrGamepadDataFetcher*) = 0; }; } // namespace device diff --git a/chromium/device/vr/features/BUILD.gn b/chromium/device/vr/features/BUILD.gn new file mode 100644 index 00000000000..e8afb4a3c2c --- /dev/null +++ b/chromium/device/vr/features/BUILD.gn @@ -0,0 +1,15 @@ +# Copyright 2016 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. + +import("features.gni") +import("//build/buildflag_header.gni") + +# Generate a buildflag header for compile-time checking of WebVR support. +buildflag_header("features") { + header = "features.h" + flags = [ + "ENABLE_VR=$enable_vr", + "ENABLE_OPENVR=$enable_openvr", + ] +} diff --git a/chromium/device/vr/features.gni b/chromium/device/vr/features/features.gni index cc619fcbb1d..f4c31029d87 100644 --- a/chromium/device/vr/features.gni +++ b/chromium/device/vr/features/features.gni @@ -2,11 +2,14 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/chromecast_build.gni") + declare_args() { # Enable WebVR support by default on Android # Still requires command line flag to access API # TODO(bshe): Enable for other architecture too. Currently we only support arm # and arm64. - enable_vr = is_android && (current_cpu == "arm" || current_cpu == "arm64") + enable_vr = is_android && (current_cpu == "arm" || current_cpu == "arm64") && + !is_chromecast enable_openvr = false } diff --git a/chromium/device/vr/openvr/openvr_device.cc b/chromium/device/vr/openvr/openvr_device.cc index 88f7f4a4fd0..41cb2c5a219 100644 --- a/chromium/device/vr/openvr/openvr_device.cc +++ b/chromium/device/vr/openvr/openvr_device.cc @@ -24,27 +24,74 @@ device::mojom::VRFieldOfViewPtr openVRFovToWebVRFov(vr::IVRSystem* vr_system, return out; } +std::vector<float> HmdVector3ToWebVR(const vr::HmdVector3_t& vec) { + std::vector<float> out; + out.resize(3); + out[0] = vec.v[0]; + out[1] = vec.v[1]; + out[2] = vec.v[2]; + return out; +} + +std::string GetOpenVRString(vr::IVRSystem* vr_system, + vr::TrackedDeviceProperty prop) { + std::string out; + + vr::TrackedPropertyError error = vr::TrackedProp_Success; + char openvr_string[vr::k_unMaxPropertyStringSize]; + vr_system->GetStringTrackedDeviceProperty( + vr::k_unTrackedDeviceIndex_Hmd, prop, openvr_string, + vr::k_unMaxPropertyStringSize, &error); + + if (error == vr::TrackedProp_Success) + out = openvr_string; + + return out; +} + +std::vector<float> HmdMatrix34ToWebVRTransformMatrix( + const vr::HmdMatrix34_t& mat) { + std::vector<float> transform; + transform.resize(16); + transform[0] = mat.m[0][0]; + transform[1] = mat.m[1][0]; + transform[2] = mat.m[2][0]; + transform[3] = 0.0f; + transform[4] = mat.m[0][1]; + transform[5] = mat.m[1][1]; + transform[6] = mat.m[2][1]; + transform[7] = 0.0f; + transform[8] = mat.m[0][2]; + transform[9] = mat.m[1][2]; + transform[10] = mat.m[2][2]; + transform[11] = 0.0f; + transform[12] = mat.m[0][3]; + transform[13] = mat.m[1][3]; + transform[14] = mat.m[2][3]; + transform[15] = 1.0f; + return transform; +} + } // namespace namespace device { -OpenVRDevice::OpenVRDevice() {} +OpenVRDevice::OpenVRDevice(vr::IVRSystem* vr) + : vr_system_(vr), weak_ptr_factory_(this), is_polling_events_(false) {} OpenVRDevice::~OpenVRDevice() {} void OpenVRDevice::CreateVRDisplayInfo( const base::Callback<void(mojom::VRDisplayInfoPtr)>& on_created) { - vr::EVRInitError init_error; - auto vr_system = - vr::VR_Init(&init_error, vr::EVRApplicationType::VRApplication_Scene); - - if (init_error != vr::VRInitError_None) { - LOG(ERROR) << vr::VR_GetVRInitErrorAsEnglishDescription(init_error); + if (!vr_system_) { on_created.Run(nullptr); return; } mojom::VRDisplayInfoPtr device = mojom::VRDisplayInfo::New(); device->index = id(); + device->displayName = + GetOpenVRString(vr_system_, vr::Prop_ManufacturerName_String) + " " + + GetOpenVRString(vr_system_, vr::Prop_ModelNumber_String); device->capabilities = mojom::VRDisplayCapabilities::New(); device->capabilities->hasPosition = true; device->capabilities->hasExternalDisplay = true; @@ -55,11 +102,11 @@ void OpenVRDevice::CreateVRDisplayInfo( mojom::VREyeParametersPtr& left_eye = device->leftEye; mojom::VREyeParametersPtr& right_eye = device->rightEye; - left_eye->fieldOfView = openVRFovToWebVRFov(vr_system, vr::Eye_Left); - right_eye->fieldOfView = openVRFovToWebVRFov(vr_system, vr::Eye_Left); + left_eye->fieldOfView = openVRFovToWebVRFov(vr_system_, vr::Eye_Left); + right_eye->fieldOfView = openVRFovToWebVRFov(vr_system_, vr::Eye_Left); vr::TrackedPropertyError error = vr::TrackedProp_Success; - float ipd = vr_system->GetFloatTrackedDeviceProperty( + float ipd = vr_system_->GetFloatTrackedDeviceProperty( vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_UserIpdMeters_Float, &error); if (error != vr::TrackedProp_Success) @@ -75,13 +122,35 @@ void OpenVRDevice::CreateVRDisplayInfo( right_eye->offset[2] = 0.0; uint32_t width, height; - vr_system->GetRecommendedRenderTargetSize(&width, &height); + vr_system_->GetRecommendedRenderTargetSize(&width, &height); left_eye->renderWidth = width; left_eye->renderHeight = height; right_eye->renderWidth = left_eye->renderWidth; right_eye->renderHeight = left_eye->renderHeight; - render_loop_ = std::make_unique<OpenVRRenderLoop>(vr_system); + device->stageParameters = mojom::VRStageParameters::New(); + vr::HmdMatrix34_t mat = + vr_system_->GetSeatedZeroPoseToStandingAbsoluteTrackingPose(); + device->stageParameters->standingTransform = + HmdMatrix34ToWebVRTransformMatrix(mat); + + vr::IVRChaperone* chaperone = vr::VRChaperone(); + if (chaperone) { + chaperone->GetPlayAreaSize(&device->stageParameters->sizeX, + &device->stageParameters->sizeZ); + } else { + device->stageParameters->sizeX = 0.0f; + device->stageParameters->sizeZ = 0.0f; + } + + // If it is the first initialization, OpenVRRenderLoop instance needs to be + // created and the polling event callback needs to be registered. + if (!render_loop_) { + render_loop_ = std::make_unique<OpenVRRenderLoop>(vr_system_); + + render_loop_->RegisterPollingEventCallback(base::Bind( + &OpenVRDevice::OnPollingEvents, weak_ptr_factory_.GetWeakPtr())); + } on_created.Run(std::move(device)); } @@ -119,8 +188,11 @@ void OpenVRDevice::GetVRVSyncProvider(mojom::VRVSyncProviderRequest request) { OpenVRDevice::OpenVRRenderLoop::OpenVRRenderLoop(vr::IVRSystem* vr_system) : vr_system_(vr_system), + main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()), binding_(this), - base::SimpleThread("OpenVRRenderLoop") {} + base::SimpleThread("OpenVRRenderLoop") { + DCHECK(main_thread_task_runner_); +} void OpenVRDevice::OpenVRRenderLoop::Bind( mojom::VRVSyncProviderRequest request) { @@ -150,7 +222,7 @@ device::mojom::VRPosePtr OpenVRDevice::OpenVRRenderLoop::getPose() { vr::TrackedDevicePose_t poses[vr::k_unMaxTrackedDeviceCount]; vr_system_->GetDeviceToAbsoluteTrackingPose( - vr::TrackingUniverseStanding, 0.0f, poses, vr::k_unMaxTrackedDeviceCount); + vr::TrackingUniverseSeated, 0.0f, poses, vr::k_unMaxTrackedDeviceCount); const auto& hmdPose = poses[vr::k_unTrackedDeviceIndex_Hmd]; if (hmdPose.bPoseIsValid && hmdPose.bDeviceIsConnected) { const auto& transform = hmdPose.mDeviceToAbsoluteTracking; @@ -164,16 +236,75 @@ device::mojom::VRPosePtr OpenVRDevice::OpenVRRenderLoop::getPose() { pose->position.value()[0] = m[0][3]; pose->position.value()[1] = m[1][3]; pose->position.value()[2] = m[2][3]; + + pose->linearVelocity = HmdVector3ToWebVR(hmdPose.vVelocity); + pose->angularVelocity = HmdVector3ToWebVR(hmdPose.vAngularVelocity); } return std::move(pose); } +// Only deal with events that will cause displayInfo changes for now. +void OpenVRDevice::OnPollingEvents() { + if (!vr_system_ || is_polling_events_) + return; + + // Polling events through vr_system_ has started. + is_polling_events_ = true; + + vr::VREvent_t event; + bool is_changed = false; + while (vr_system_->PollNextEvent(&event, sizeof(event))) { + if (event.trackedDeviceIndex != vr::k_unTrackedDeviceIndex_Hmd && + event.trackedDeviceIndex != vr::k_unTrackedDeviceIndexInvalid) { + continue; + } + + switch (event.eventType) { + case vr::VREvent_TrackedDeviceUpdated: + case vr::VREvent_IpdChanged: + case vr::VREvent_ChaperoneDataHasChanged: + case vr::VREvent_ChaperoneSettingsHaveChanged: + case vr::VREvent_ChaperoneUniverseHasChanged: + is_changed = true; + break; + + default: + break; + } + } + + // Polling events through vr_system_ has finished. + is_polling_events_ = false; + + if (is_changed) { + OnChanged(); + } +} + +// Register a callback function to deal with system events. +void OpenVRDevice::OpenVRRenderLoop::RegisterPollingEventCallback( + const base::Callback<void()>& onPollingEvents) { + if (onPollingEvents.is_null()) + return; + + on_polling_events_ = onPollingEvents; +} + +void OpenVRDevice::OpenVRRenderLoop::UnregisterPollingEventCallback() { + on_polling_events_.Reset(); +} + void OpenVRDevice::OpenVRRenderLoop::GetVSync( const mojom::VRVSyncProvider::GetVSyncCallback& callback) { static int16_t next_frame = 0; int16_t frame = next_frame++; + // VSync could be used as a signal to poll events. + if (!on_polling_events_.is_null()) { + main_thread_task_runner_->PostTask(FROM_HERE, on_polling_events_); + } + // TODO(BillOrr): Give real values when VSync loop is hooked up. This is the // presentation time for the frame. Just returning a default value for now // since we don't have VSync hooked up. diff --git a/chromium/device/vr/openvr/openvr_device.h b/chromium/device/vr/openvr/openvr_device.h index 136f5667fd2..f4b2d1d7258 100644 --- a/chromium/device/vr/openvr/openvr_device.h +++ b/chromium/device/vr/openvr/openvr_device.h @@ -18,7 +18,7 @@ namespace device { class OpenVRDevice : public VRDevice { public: - OpenVRDevice(); + OpenVRDevice(vr::IVRSystem* vr); ~OpenVRDevice() override; // VRDevice @@ -39,12 +39,19 @@ class OpenVRDevice : public VRDevice { int16_t source_height) override; void GetVRVSyncProvider(mojom::VRVSyncProviderRequest request) override; + void OnPollingEvents(); + private: class OpenVRRenderLoop : public base::SimpleThread, device::mojom::VRVSyncProvider { public: OpenVRRenderLoop(vr::IVRSystem* vr); + void RegisterPollingEventCallback( + const base::Callback<void()>& onPollingEvents); + + void UnregisterPollingEventCallback(); + void Bind(mojom::VRVSyncProviderRequest request); mojom::VRPosePtr getPose(); @@ -56,6 +63,7 @@ class OpenVRDevice : public VRDevice { callback) override; scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_; + base::Callback<void()> on_polling_events_; vr::IVRSystem* vr_system_; mojo::Binding<device::mojom::VRVSyncProvider> binding_; }; @@ -68,6 +76,12 @@ class OpenVRDevice : public VRDevice { mojom::VRSubmitFrameClientPtr submit_client_; + vr::IVRSystem* vr_system_; + + bool is_polling_events_; + + base::WeakPtrFactory<OpenVRDevice> weak_ptr_factory_; + DISALLOW_COPY_AND_ASSIGN(OpenVRDevice); }; diff --git a/chromium/device/vr/openvr/openvr_device_provider.cc b/chromium/device/vr/openvr/openvr_device_provider.cc index aee062f1463..d16f10dfced 100644 --- a/chromium/device/vr/openvr/openvr_device_provider.cc +++ b/chromium/device/vr/openvr/openvr_device_provider.cc @@ -3,22 +3,43 @@ // found in the LICENSE file. #include "device/vr/openvr/openvr_device_provider.h" + +#include "device/gamepad/gamepad_data_fetcher_manager.h" #include "device/vr/openvr/openvr_device.h" +#include "device/vr/openvr/openvr_gamepad_data_fetcher.h" #include "third_party/openvr/src/headers/openvr.h" namespace device { -OpenVRDeviceProvider::OpenVRDeviceProvider() {} +OpenVRDeviceProvider::OpenVRDeviceProvider() + : initialized_(false), vr_system_(nullptr) {} OpenVRDeviceProvider::~OpenVRDeviceProvider() {} void OpenVRDeviceProvider::GetDevices(std::vector<VRDevice*>* devices) { - if (vr::VR_IsRuntimeInstalled() && vr::VR_IsHmdPresent()) { - devices->push_back(new OpenVRDevice()); + if (initialized_) { + VRDevice* device = new OpenVRDevice(vr_system_); + devices->push_back(device); + GamepadDataFetcherManager::GetInstance()->AddFactory( + new OpenVRGamepadDataFetcher::Factory(device->id(), vr_system_)); } } -void OpenVRDeviceProvider::Initialize() {} +void OpenVRDeviceProvider::Initialize() { + if (!initialized_ && vr::VR_IsRuntimeInstalled() && vr::VR_IsHmdPresent()) { + vr::EVRInitError init_error = vr::VRInitError_None; + vr_system_ = + vr::VR_Init(&init_error, vr::EVRApplicationType::VRApplication_Scene); + + if (init_error != vr::VRInitError_None) { + LOG(ERROR) << vr::VR_GetVRInitErrorAsEnglishDescription(init_error); + vr_system_ = nullptr; + return; + } + + initialized_ = true; + } +} void OpenVRDeviceProvider::SetListeningForActivate(bool listening) {} diff --git a/chromium/device/vr/openvr/openvr_device_provider.h b/chromium/device/vr/openvr/openvr_device_provider.h index 7ef17b6efac..45c3f78a4a1 100644 --- a/chromium/device/vr/openvr/openvr_device_provider.h +++ b/chromium/device/vr/openvr/openvr_device_provider.h @@ -12,6 +12,10 @@ #include "device/vr/vr_device_provider.h" #include "device/vr/vr_export.h" +namespace vr { +class IVRSystem; +} // namespace vr + namespace device { class OpenVRDeviceProvider : public VRDeviceProvider { @@ -25,6 +29,9 @@ class OpenVRDeviceProvider : public VRDeviceProvider { void SetListeningForActivate(bool listening) override; private: + bool initialized_; + vr::IVRSystem* vr_system_; + DISALLOW_COPY_AND_ASSIGN(OpenVRDeviceProvider); }; diff --git a/chromium/device/vr/openvr/openvr_gamepad_data_fetcher.cc b/chromium/device/vr/openvr/openvr_gamepad_data_fetcher.cc new file mode 100644 index 00000000000..d165b442fce --- /dev/null +++ b/chromium/device/vr/openvr/openvr_gamepad_data_fetcher.cc @@ -0,0 +1,228 @@ +// Copyright 2017 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 "device/vr/openvr/openvr_gamepad_data_fetcher.h" + +#include <memory> + +#include "base/logging.h" +#include "base/strings/utf_string_conversions.h" +#include "device/gamepad/public/cpp/gamepads.h" +#include "third_party/openvr/src/headers/openvr.h" +#include "ui/gfx/transform.h" +#include "ui/gfx/transform_util.h" + +namespace device { + +namespace { + +void SetGamepadButton(Gamepad* pad, + const vr::VRControllerState_t& controller_state, + uint64_t supported_buttons, + vr::EVRButtonId button_id) { + uint64_t button_mask = vr::ButtonMaskFromId(button_id); + if ((supported_buttons & button_mask) != 0) { + bool button_pressed = (controller_state.ulButtonPressed & button_mask) != 0; + bool button_touched = (controller_state.ulButtonTouched & button_mask) != 0; + pad->buttons[pad->buttons_length].touched = button_touched; + pad->buttons[pad->buttons_length].pressed = button_pressed; + pad->buttons[pad->buttons_length].value = button_pressed ? 1.0 : 0.0; + pad->buttons_length++; + } +} + +} // namespace + +OpenVRGamepadDataFetcher::Factory::Factory(unsigned int display_id, + vr::IVRSystem* vr) + : display_id_(display_id), vr_system_(vr) { + DVLOG(1) << __FUNCTION__ << "=" << this; +} + +OpenVRGamepadDataFetcher::Factory::~Factory() { + DVLOG(1) << __FUNCTION__ << "=" << this; +} + +std::unique_ptr<GamepadDataFetcher> +OpenVRGamepadDataFetcher::Factory::CreateDataFetcher() { + return base::MakeUnique<OpenVRGamepadDataFetcher>(display_id_, vr_system_); +} + +GamepadSource OpenVRGamepadDataFetcher::Factory::source() { + return GAMEPAD_SOURCE_OPENVR; +} + +OpenVRGamepadDataFetcher::OpenVRGamepadDataFetcher(unsigned int display_id, + vr::IVRSystem* vr) + : display_id_(display_id), vr_system_(vr) { + DVLOG(1) << __FUNCTION__ << "=" << this; +} + +OpenVRGamepadDataFetcher::~OpenVRGamepadDataFetcher() { + DVLOG(1) << __FUNCTION__ << "=" << this; +} + +GamepadSource OpenVRGamepadDataFetcher::source() { + return GAMEPAD_SOURCE_OPENVR; +} + +void OpenVRGamepadDataFetcher::OnAddedToProvider() {} + +void OpenVRGamepadDataFetcher::GetGamepadData(bool devices_changed_hint) { + if (!vr_system_) + return; + + vr::TrackedDevicePose_t tracked_devices_poses[vr::k_unMaxTrackedDeviceCount]; + vr_system_->GetDeviceToAbsoluteTrackingPose(vr::TrackingUniverseSeated, 0.0f, + tracked_devices_poses, + vr::k_unMaxTrackedDeviceCount); + + for (uint32_t i = 0; i < vr::k_unMaxTrackedDeviceCount; ++i) { + if (vr_system_->GetTrackedDeviceClass(i) != + vr::TrackedDeviceClass_Controller) + continue; + + PadState* state = GetPadState(i); + if (!state) + continue; + + Gamepad& pad = state->data; + + vr::VRControllerState_t controller_state; + if (vr_system_->GetControllerState(i, &controller_state, + sizeof(controller_state))) { + pad.timestamp = controller_state.unPacketNum; + pad.connected = true; + + pad.pose.not_null = true; + + pad.pose.has_orientation = true; + pad.pose.has_position = true; + + vr::TrackedPropertyError error = vr::TrackedProp_Success; + char attached_device_id[vr::k_unMaxPropertyStringSize]; + vr_system_->GetStringTrackedDeviceProperty( + i, vr::Prop_AttachedDeviceId_String, attached_device_id, + vr::k_unMaxPropertyStringSize, &error); + + if (error == vr::TrackedProp_Success) { + swprintf(pad.id, Gamepad::kIdLengthCap, + base::UTF8ToUTF16(attached_device_id).c_str()); + } else { + swprintf(pad.id, Gamepad::kIdLengthCap, L"OpenVR Controller"); + } + swprintf(pad.mapping, Gamepad::kMappingLengthCap, L""); + + pad.display_id = display_id_; + + vr::ETrackedControllerRole hand = + vr_system_->GetControllerRoleForTrackedDeviceIndex(i); + + switch (hand) { + case vr::TrackedControllerRole_Invalid: + pad.hand = GamepadHand::kNone; + break; + case vr::TrackedControllerRole_LeftHand: + pad.hand = GamepadHand::kLeft; + break; + case vr::TrackedControllerRole_RightHand: + pad.hand = GamepadHand::kRight; + break; + } + + uint64_t supported_buttons = vr_system_->GetUint64TrackedDeviceProperty( + i, vr::Prop_SupportedButtons_Uint64); + + pad.buttons_length = 0; + pad.axes_length = 0; + + for (int j = 0; j < vr::k_unControllerStateAxisCount; ++j) { + int32_t axis_type = vr_system_->GetInt32TrackedDeviceProperty( + i, static_cast<vr::TrackedDeviceProperty>(vr::Prop_Axis0Type_Int32 + + j)); + switch (axis_type) { + case vr::k_eControllerAxis_Joystick: + case vr::k_eControllerAxis_TrackPad: + pad.axes[pad.axes_length++] = controller_state.rAxis[j].x; + pad.axes[pad.axes_length++] = controller_state.rAxis[j].y; + + SetGamepadButton( + &pad, controller_state, supported_buttons, + static_cast<vr::EVRButtonId>(vr::k_EButton_Axis0 + j)); + + break; + case vr::k_eControllerAxis_Trigger: + pad.buttons[pad.buttons_length].value = controller_state.rAxis[j].x; + + uint64_t button_mask = vr::ButtonMaskFromId( + static_cast<vr::EVRButtonId>(vr::k_EButton_Axis0 + j)); + if ((supported_buttons & button_mask) != 0) { + pad.buttons[pad.buttons_length].pressed = + (controller_state.ulButtonPressed & button_mask) != 0; + } + + pad.buttons_length++; + break; + } + } + + SetGamepadButton(&pad, controller_state, supported_buttons, + vr::k_EButton_A); + SetGamepadButton(&pad, controller_state, supported_buttons, + vr::k_EButton_Grip); + SetGamepadButton(&pad, controller_state, supported_buttons, + vr::k_EButton_ApplicationMenu); + SetGamepadButton(&pad, controller_state, supported_buttons, + vr::k_EButton_DPad_Left); + SetGamepadButton(&pad, controller_state, supported_buttons, + vr::k_EButton_DPad_Up); + SetGamepadButton(&pad, controller_state, supported_buttons, + vr::k_EButton_DPad_Right); + SetGamepadButton(&pad, controller_state, supported_buttons, + vr::k_EButton_DPad_Down); + } + + const vr::TrackedDevicePose_t& pose = tracked_devices_poses[i]; + if (pose.bPoseIsValid) { + const vr::HmdMatrix34_t& mat = pose.mDeviceToAbsoluteTracking; + gfx::Transform transform( + mat.m[0][0], mat.m[0][1], mat.m[0][2], mat.m[0][3], mat.m[1][0], + mat.m[1][1], mat.m[1][2], mat.m[1][3], mat.m[2][0], mat.m[2][1], + mat.m[2][2], mat.m[2][3], 0, 0, 0, 1); + + gfx::DecomposedTransform decomposed_transform; + gfx::DecomposeTransform(&decomposed_transform, transform); + + pad.pose.orientation.not_null = true; + pad.pose.orientation.x = decomposed_transform.quaternion[0]; + pad.pose.orientation.y = decomposed_transform.quaternion[1]; + pad.pose.orientation.z = decomposed_transform.quaternion[2]; + pad.pose.orientation.w = decomposed_transform.quaternion[3]; + + pad.pose.position.not_null = true; + pad.pose.position.x = decomposed_transform.translate[0]; + pad.pose.position.y = decomposed_transform.translate[1]; + pad.pose.position.z = decomposed_transform.translate[2]; + + pad.pose.angular_velocity.not_null = true; + pad.pose.angular_velocity.x = pose.vAngularVelocity.v[0]; + pad.pose.angular_velocity.y = pose.vAngularVelocity.v[1]; + pad.pose.angular_velocity.z = pose.vAngularVelocity.v[2]; + + pad.pose.linear_velocity.not_null = true; + pad.pose.linear_velocity.x = pose.vVelocity.v[0]; + pad.pose.linear_velocity.y = pose.vVelocity.v[1]; + pad.pose.linear_velocity.z = pose.vVelocity.v[2]; + } else { + pad.pose.orientation.not_null = false; + pad.pose.position.not_null = false; + pad.pose.angular_velocity.not_null = false; + pad.pose.linear_velocity.not_null = false; + } + } +} + +void OpenVRGamepadDataFetcher::PauseHint(bool paused) {} + +} // namespace device diff --git a/chromium/device/vr/openvr/openvr_gamepad_data_fetcher.h b/chromium/device/vr/openvr/openvr_gamepad_data_fetcher.h new file mode 100644 index 00000000000..37544a34e13 --- /dev/null +++ b/chromium/device/vr/openvr/openvr_gamepad_data_fetcher.h @@ -0,0 +1,47 @@ +// Copyright 2017 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 DEVICE_VR_OPENVR_GAMEPAD_DATA_FETCHER_H_ +#define DEVICE_VR_OPENVR_GAMEPAD_DATA_FETCHER_H_ + +#include "device/gamepad/gamepad_data_fetcher.h" + +namespace vr { +class IVRSystem; +} // namespace vr + +namespace device { + +class OpenVRGamepadDataFetcher : public GamepadDataFetcher { + public: + class Factory : public GamepadDataFetcherFactory { + public: + Factory(unsigned int display_id, vr::IVRSystem* vr); + ~Factory() override; + std::unique_ptr<GamepadDataFetcher> CreateDataFetcher() override; + GamepadSource source() override; + + private: + unsigned int display_id_; + vr::IVRSystem* vr_system_; + }; + + OpenVRGamepadDataFetcher(unsigned int display_id, vr::IVRSystem* vr); + ~OpenVRGamepadDataFetcher() override; + + GamepadSource source() override; + + void GetGamepadData(bool devices_changed_hint) override; + void PauseHint(bool paused) override; + void OnAddedToProvider() override; + + private: + unsigned int display_id_; + vr::IVRSystem* vr_system_; + + DISALLOW_COPY_AND_ASSIGN(OpenVRGamepadDataFetcher); +}; + +} // namespace device +#endif // DEVICE_VR_OPENVR_GAMEPAD_DATA_FETCHER_H_ diff --git a/chromium/device/vr/vr_device.cc b/chromium/device/vr/vr_device.cc index 6a33287be59..e08c548e312 100644 --- a/chromium/device/vr/vr_device.cc +++ b/chromium/device/vr/vr_device.cc @@ -69,9 +69,10 @@ void VRDevice::OnFocus() { display->OnFocus(); } -void VRDevice::OnActivate(mojom::VRDisplayEventReason reason) { +void VRDevice::OnActivate(mojom::VRDisplayEventReason reason, + const base::Callback<void(bool)>& on_handled) { for (auto* display : displays_) - display->OnActivate(reason); + display->OnActivate(reason, on_handled); } void VRDevice::OnDeactivate(mojom::VRDisplayEventReason reason) { diff --git a/chromium/device/vr/vr_device.h b/chromium/device/vr/vr_device.h index f469ef45c74..ff1b898eb1f 100644 --- a/chromium/device/vr/vr_device.h +++ b/chromium/device/vr/vr_device.h @@ -54,7 +54,8 @@ class DEVICE_VR_EXPORT VRDevice { virtual void OnExitPresent(); virtual void OnBlur(); virtual void OnFocus(); - virtual void OnActivate(mojom::VRDisplayEventReason reason); + virtual void OnActivate(mojom::VRDisplayEventReason reason, + const base::Callback<void(bool)>& on_handled); virtual void OnDeactivate(mojom::VRDisplayEventReason reason); protected: diff --git a/chromium/device/vr/vr_device_manager.cc b/chromium/device/vr/vr_device_manager.cc index bd314f4c5f2..af97c0a939b 100644 --- a/chromium/device/vr/vr_device_manager.cc +++ b/chromium/device/vr/vr_device_manager.cc @@ -10,7 +10,7 @@ #include "base/memory/ptr_util.h" #include "base/memory/singleton.h" #include "build/build_config.h" -#include "device/vr/features.h" +#include "device/vr/features/features.h" #if defined(OS_ANDROID) #include "device/vr/android/gvr/gvr_device_provider.h" diff --git a/chromium/device/vr/vr_display_impl.cc b/chromium/device/vr/vr_display_impl.cc index 46542389da9..880e5d9ff7c 100644 --- a/chromium/device/vr/vr_display_impl.cc +++ b/chromium/device/vr/vr_display_impl.cc @@ -45,11 +45,12 @@ void VRDisplayImpl::OnFocus() { client_->OnFocus(); } -void VRDisplayImpl::OnActivate(mojom::VRDisplayEventReason reason) { +void VRDisplayImpl::OnActivate(mojom::VRDisplayEventReason reason, + const base::Callback<void(bool)>& on_handled) { VRDeviceManager* manager = VRDeviceManager::GetInstance(); if (!manager->IsMostRecentlyListeningForActivate(service_)) return; - client_->OnActivate(reason); + client_->OnActivate(reason, on_handled); } void VRDisplayImpl::OnDeactivate(mojom::VRDisplayEventReason reason) { @@ -59,9 +60,7 @@ void VRDisplayImpl::OnDeactivate(mojom::VRDisplayEventReason reason) { void VRDisplayImpl::RequestPresent(bool secure_origin, mojom::VRSubmitFrameClientPtr submit_client, const RequestPresentCallback& callback) { - // TODO(mthiesse): Re-enable insecure origin support once webVR content - // warnings are fixed. crbug.com/704937 - if (!device_->IsAccessAllowed(this) || !secure_origin) { + if (!device_->IsAccessAllowed(this)) { callback.Run(false); return; } @@ -113,4 +112,5 @@ void VRDisplayImpl::GetVRVSyncProvider(mojom::VRVSyncProviderRequest request) { } device_->GetVRVSyncProvider(std::move(request)); } -} + +} // namespace device diff --git a/chromium/device/vr/vr_display_impl.h b/chromium/device/vr/vr_display_impl.h index 97feacbc120..7aaa68a3c06 100644 --- a/chromium/device/vr/vr_display_impl.h +++ b/chromium/device/vr/vr_display_impl.h @@ -35,7 +35,8 @@ class VRDisplayImpl : public mojom::VRDisplay { virtual void OnExitPresent(); virtual void OnBlur(); virtual void OnFocus(); - virtual void OnActivate(mojom::VRDisplayEventReason reason); + virtual void OnActivate(mojom::VRDisplayEventReason reason, + const base::Callback<void(bool)>& on_handled); virtual void OnDeactivate(mojom::VRDisplayEventReason reason); private: diff --git a/chromium/device/vr/vr_math.cc b/chromium/device/vr/vr_math.cc index cd95d5eba1c..8d5d4379781 100644 --- a/chromium/device/vr/vr_math.cc +++ b/chromium/device/vr/vr_math.cc @@ -120,6 +120,9 @@ float NormalizeVector(gfx::Vector3dF* vec) { void NormalizeQuat(Quatf* quat) { float len = sqrt(quat->qx * quat->qx + quat->qy * quat->qy + quat->qz * quat->qz + quat->qw * quat->qw); + DCHECK_NE(len, 0); + if (len == 0) + return; quat->qx /= len; quat->qy /= len; quat->qz /= len; @@ -177,6 +180,69 @@ void QuatToMatrix(const Quatf& quat, Mat4f* out) { {{0.0f, 0.0f, 0.0f, 1.0f}}}}; } +vr::Quatf GetVectorRotation(const gfx::Vector3dF& from, + const gfx::Vector3dF& to) { + float dot = gfx::DotProduct(from, to); + float norm = sqrt(from.LengthSquared() * to.LengthSquared()); + float real = norm + dot; + gfx::Vector3dF w; + if (real < 1.e-6f * norm) { + real = 0.0f; + w = fabsf(from.x()) > fabsf(from.z()) + ? gfx::Vector3dF{-from.y(), from.x(), 0.0f} + : gfx::Vector3dF{0.0f, -from.z(), from.y()}; + } else { + w = gfx::CrossProduct(from, to); + } + vr::Quatf result{w.x(), w.y(), w.z(), real}; + NormalizeQuat(&result); + return result; +} + +vr::Quatf QuatSum(const vr::Quatf& a, const vr::Quatf& b) { + return {a.qx + b.qx, a.qy + b.qy, a.qz + b.qz, a.qw + b.qw}; +} + +vr::Quatf QuatProduct(const vr::Quatf& a, const vr::Quatf& b) { + return {a.qw * b.qx + a.qx * b.qw + a.qy * b.qz - a.qz * b.qy, + a.qw * b.qy - a.qx * b.qz + a.qy * b.qw + a.qz * b.qx, + a.qw * b.qz + a.qx * b.qy - a.qy * b.qx + a.qz * b.qw, + a.qw * b.qw - a.qx * b.qx - a.qy * b.qy - a.qz * b.qz}; +} + +vr::Quatf ScaleQuat(const vr::Quatf& q, float s) { + return {q.qx * s, q.qy * s, q.qz * s, q.qw * s}; +} + +vr::Quatf InvertQuat(const vr::Quatf& quat) { + return {-quat.qx, -quat.qy, -quat.qz, quat.qw}; +} + +float QuatAngleDegrees(const vr::Quatf& a, const vr::Quatf& b) { + return QuatProduct(b, InvertQuat(a)).qw; +} + +vr::Quatf QuatLerp(const vr::Quatf& a, const vr::Quatf& b, float t) { + auto result = QuatSum(ScaleQuat(a, 1.0f - t), ScaleQuat(b, t)); + NormalizeQuat(&result); + return result; +} + +gfx::Vector3dF QuatSlerp(const gfx::Vector3dF& v_start, + const gfx::Vector3dF& v_end, + float percent) { + auto start = v_start; + auto end = v_end; + NormalizeVector(&start); + NormalizeVector(&end); + float dot = Clampf(gfx::DotProduct(start, end), -1.0f, 1.0f); + float theta = acos(dot) * percent; + auto relative_vec = end - gfx::ScaleVector3d(start, dot); + NormalizeVector(&relative_vec); + return gfx::ScaleVector3d(start, cos(theta)) + + gfx::ScaleVector3d(relative_vec, sin(theta)); +} + gfx::Point3F GetRayPoint(const gfx::Point3F& rayOrigin, const gfx::Vector3dF& rayVector, float scale) { @@ -199,4 +265,28 @@ bool XZAngle(const gfx::Vector3dF& vec1, return true; } +gfx::Vector3dF ToVector(const gfx::Point3F& p) { + return {p.x(), p.y(), p.z()}; +} + +gfx::Point3F ToPoint(const gfx::Vector3dF& p) { + return {p.x(), p.y(), p.z()}; +} + +gfx::Point3F ScalePoint(const gfx::Point3F& p, const gfx::Vector3dF& s) { + return gfx::ScalePoint(p, s.x(), s.y(), s.z()); +} + +gfx::Vector3dF ScaleVector(const gfx::Vector3dF& v, const gfx::Vector3dF& s) { + return gfx::ScaleVector3d(v, s.x(), s.y(), s.z()); +} + +float Clampf(float value, float min, float max) { + if (value < min) + return min; + if (value > max) + return max; + return value; +} + } // namespace vr diff --git a/chromium/device/vr/vr_math.h b/chromium/device/vr/vr_math.h index 2426b3dccfd..55c165c45f6 100644 --- a/chromium/device/vr/vr_math.h +++ b/chromium/device/vr/vr_math.h @@ -33,6 +33,27 @@ gfx::Vector3dF DEVICE_VR_EXPORT GetTranslation(const Mat4f& matrix); void DEVICE_VR_EXPORT QuatToMatrix(const Quatf& quat, Mat4f* out); +// Creates a rotation which rotates `from` vector to `to`. +vr::Quatf DEVICE_VR_EXPORT GetVectorRotation(const gfx::Vector3dF& from, + const gfx::Vector3dF& to); + +vr::Quatf DEVICE_VR_EXPORT QuatSum(const vr::Quatf& a, const vr::Quatf& b); +vr::Quatf DEVICE_VR_EXPORT QuatProduct(const vr::Quatf& a, const vr::Quatf& b); +vr::Quatf DEVICE_VR_EXPORT ScaleQuat(const vr::Quatf& q, float s); + +vr::Quatf DEVICE_VR_EXPORT InvertQuat(const vr::Quatf& quat); + +float DEVICE_VR_EXPORT QuatAngleDegrees(const vr::Quatf& a, const vr::Quatf& b); + +vr::Quatf DEVICE_VR_EXPORT QuatLerp(const vr::Quatf& a, + const vr::Quatf& b, + float t); + +// Spherical linear interpolation. +gfx::Vector3dF DEVICE_VR_EXPORT QuatSlerp(const gfx::Vector3dF& v_start, + const gfx::Vector3dF& v_end, + float percent); + // Normalize a vector, and return its original length. float DEVICE_VR_EXPORT NormalizeVector(gfx::Vector3dF* vec); @@ -49,6 +70,20 @@ bool DEVICE_VR_EXPORT XZAngle(const gfx::Vector3dF& vec1, const gfx::Vector3dF& vec2, float* angle); +gfx::Vector3dF DEVICE_VR_EXPORT ToVector(const gfx::Point3F& p); + +gfx::Point3F DEVICE_VR_EXPORT ToPoint(const gfx::Vector3dF& p); + +// Scale components of the point by the components of the vector. +gfx::Point3F DEVICE_VR_EXPORT ScalePoint(const gfx::Point3F& p, + const gfx::Vector3dF& s); + +// Scale components of a vector by the components of another. +gfx::Vector3dF DEVICE_VR_EXPORT ScaleVector(const gfx::Vector3dF& p, + const gfx::Vector3dF& s); + +float DEVICE_VR_EXPORT Clampf(float value, float min, float max); + } // namespace vr #endif // DEVICE_VR_VR_MATH_H_ diff --git a/chromium/device/vr/vr_service.mojom b/chromium/device/vr/vr_service.mojom index fe504ea0034..e1acedae9fe 100644 --- a/chromium/device/vr/vr_service.mojom +++ b/chromium/device/vr/vr_service.mojom @@ -115,6 +115,6 @@ interface VRDisplayClient { OnExitPresent(); OnBlur(); OnFocus(); - OnActivate(VRDisplayEventReason reason); + OnActivate(VRDisplayEventReason reason) => (bool will_not_present); OnDeactivate(VRDisplayEventReason reason); }; diff --git a/chromium/device/vr/vr_service_impl.cc b/chromium/device/vr/vr_service_impl.cc index 93d24f6cda4..fa3d30022b8 100644 --- a/chromium/device/vr/vr_service_impl.cc +++ b/chromium/device/vr/vr_service_impl.cc @@ -6,6 +6,7 @@ #include <utility> +#include "base/auto_reset.h" #include "base/bind.h" #include "base/memory/ptr_util.h" #include "device/vr/vr_device.h" @@ -15,7 +16,11 @@ namespace device { VRServiceImpl::VRServiceImpl() - : listening_for_activate_(false), weak_ptr_factory_(this) {} + : listening_for_activate_(false), + in_set_client_(false), + connected_devices_(0), + handled_devices_(0), + weak_ptr_factory_(this) {} VRServiceImpl::~VRServiceImpl() { // Destroy VRDisplay before calling RemoveService below. RemoveService might @@ -25,7 +30,8 @@ VRServiceImpl::~VRServiceImpl() { VRDeviceManager::GetInstance()->RemoveService(this); } -void VRServiceImpl::Create(mojo::InterfaceRequest<mojom::VRService> request) { +void VRServiceImpl::Create(const service_manager::BindSourceInfo& source_info, + mojom::VRServiceRequest request) { mojo::MakeStrongBinding(base::MakeUnique<VRServiceImpl>(), std::move(request)); } @@ -33,14 +39,28 @@ void VRServiceImpl::Create(mojo::InterfaceRequest<mojom::VRService> request) { void VRServiceImpl::SetClient(mojom::VRServiceClientPtr service_client, const SetClientCallback& callback) { DCHECK(!client_.get()); + + // Set a scoped variable to true so we can verify we are in the same stack. + base::AutoReset<bool> set_client(&in_set_client_, true); + client_ = std::move(service_client); - VRDeviceManager* device_manager = VRDeviceManager::GetInstance(); // Once a client has been connected AddService will force any VRDisplays to // send ConnectDevice to it so that it's populated with the currently active // displays. Thereafter it will stay up to date by virtue of listening for new // connected events. + + VRDeviceManager* device_manager = VRDeviceManager::GetInstance(); device_manager->AddService(this); - callback.Run(device_manager->GetNumberOfConnectedDevices()); + unsigned expected_devices = device_manager->GetNumberOfConnectedDevices(); + // TODO(amp): Remove this count based synchronization. + // If libraries are not loaded, new devices will immediatly be handled but not + // connect, return only those devices which have already connected. + // If libraries were loaded then all devices may not be handled yet so return + // the number we expect to eventually connect. + if (expected_devices == handled_devices_) { + expected_devices = connected_devices_; + } + callback.Run(expected_devices); } void VRServiceImpl::ConnectDevice(VRDevice* device) { @@ -69,14 +89,19 @@ void VRServiceImpl::OnVRDisplayInfoCreated( "process is not established"; return; } + if (!display_info) { // If we get passed a null display info it means the device does not exist. // This can happen for example if VR services are not installed. We will not - // instantiate a display in this case. - return; + // instantiate a display in this case and don't count it as connected, but + // we do mark that we have handled it and verify we haven't changed stacks. + DCHECK(in_set_client_); + } else { + displays_[device] = base::MakeUnique<VRDisplayImpl>( + device, this, client_.get(), std::move(display_info)); + connected_devices_++; } - displays_[device] = base::MakeUnique<VRDisplayImpl>( - device, this, client_.get(), std::move(display_info)); + handled_devices_++; } VRDisplayImpl* VRServiceImpl::GetVRDisplayImplForTesting(VRDevice* device) { diff --git a/chromium/device/vr/vr_service_impl.h b/chromium/device/vr/vr_service_impl.h index a004cea944b..81f8c02549f 100644 --- a/chromium/device/vr/vr_service_impl.h +++ b/chromium/device/vr/vr_service_impl.h @@ -15,6 +15,10 @@ #include "device/vr/vr_service.mojom.h" #include "mojo/public/cpp/bindings/binding.h" +namespace service_manager { +struct BindSourceInfo; +} + namespace device { // Browser process representation of a WebVR site session. Instantiated through @@ -28,7 +32,8 @@ class VRServiceImpl : public mojom::VRService { DEVICE_VR_EXPORT ~VRServiceImpl() override; DEVICE_VR_EXPORT static void Create( - mojo::InterfaceRequest<mojom::VRService> request); + const service_manager::BindSourceInfo& source_info, + mojom::VRServiceRequest request); // mojom::VRService implementation // Adds this service to the VRDeviceManager. @@ -55,6 +60,9 @@ class VRServiceImpl : public mojom::VRService { mojom::VRServiceClientPtr client_; bool listening_for_activate_; + bool in_set_client_; + unsigned connected_devices_; + unsigned handled_devices_; base::WeakPtrFactory<VRServiceImpl> weak_ptr_factory_; diff --git a/chromium/device/vr/vr_types.h b/chromium/device/vr/vr_types.h index a030bd987dc..a6980413263 100644 --- a/chromium/device/vr/vr_types.h +++ b/chromium/device/vr/vr_types.h @@ -25,13 +25,6 @@ typedef struct RotationAxisAngle { float angle; } RotationAxisAngle; -typedef struct Colorf { - float r; - float g; - float b; - float a; -} Colorf; - // A floating point quaternion, in JPL format. typedef struct Quatf { /// qx, qy, qz are the vector component. diff --git a/chromium/device/wake_lock/BUILD.gn b/chromium/device/wake_lock/BUILD.gn index 99febb8bb1d..0f7fe9db75c 100644 --- a/chromium/device/wake_lock/BUILD.gn +++ b/chromium/device/wake_lock/BUILD.gn @@ -4,8 +4,8 @@ source_set("wake_lock") { sources = [ - "wake_lock_context_provider.cc", - "wake_lock_context_provider.h", + "wake_lock_provider.cc", + "wake_lock_provider.h", "wake_lock_service_context.cc", "wake_lock_service_context.h", "wake_lock_service_impl.cc", diff --git a/chromium/device/wake_lock/DEPS b/chromium/device/wake_lock/DEPS index b273ae3319c..93fe821412e 100644 --- a/chromium/device/wake_lock/DEPS +++ b/chromium/device/wake_lock/DEPS @@ -1,3 +1,4 @@ include_rules = [ + "+device/power_save_blocker", "+ui/gfx", ] diff --git a/chromium/device/wake_lock/public/interfaces/BUILD.gn b/chromium/device/wake_lock/public/interfaces/BUILD.gn index 9e5bb012181..06045e1b78a 100644 --- a/chromium/device/wake_lock/public/interfaces/BUILD.gn +++ b/chromium/device/wake_lock/public/interfaces/BUILD.gn @@ -7,7 +7,10 @@ import("//mojo/public/tools/bindings/mojom.gni") mojom("interfaces") { sources = [ "wake_lock_context.mojom", - "wake_lock_context_provider.mojom", + "wake_lock_provider.mojom", "wake_lock_service.mojom", ] + + # TODO(crbug.com/714018): Convert the implementation to use OnceCallback. + use_once_callback = false } diff --git a/chromium/device/wake_lock/public/interfaces/README.md b/chromium/device/wake_lock/public/interfaces/README.md index ee4679afd98..a0be7f93804 100644 --- a/chromium/device/wake_lock/public/interfaces/README.md +++ b/chromium/device/wake_lock/public/interfaces/README.md @@ -8,7 +8,7 @@ this coupling, the Wake Lock usage model on Android is as follows: enables the Wake Lock implementation to map (embedder-specific) context IDs to NativeViews. (2) For a given embedder-specific context, a trusted client -connects to the WakeLockContextProvider interface and gets a +connects to the WakeLockProvider interface and gets a WakeLockContext instance that is associated with that context. (3) That trusted client then forwards requests to bind wake locks from untrusted clients that are made within that context, with the Wake Lock @@ -17,3 +17,8 @@ NativeView associated with that context. On other platforms, the usage model is similar but the callback is not necessary/employed. + +If the client does not have any context available (e.g., is not within the +context of a WebContents), it can get a WakeLock that doesn't associate to any +context (by GetWakeLockWithoutContext() in WakeLockProvider). However, note that +the resulting Wake Lock will not have any effect on Android. diff --git a/chromium/device/wake_lock/public/interfaces/wake_lock_context.mojom b/chromium/device/wake_lock/public/interfaces/wake_lock_context.mojom index 24cd02f3bcd..ba6a9efc4da 100644 --- a/chromium/device/wake_lock/public/interfaces/wake_lock_context.mojom +++ b/chromium/device/wake_lock/public/interfaces/wake_lock_context.mojom @@ -6,12 +6,35 @@ module device.mojom; import "device/wake_lock/public/interfaces/wake_lock_service.mojom"; +enum WakeLockType { + // Prevent the application from being suspended. On some platforms, apps may + // be suspended when they are not visible to the user. This type of block + // requests that the app continue to run in that case, and on all platforms + // prevents the system from sleeping. + // Example use cases: downloading a file, playing audio. + PreventAppSuspension = 0, + + // Prevent the display from going to sleep. This also has the side effect of + // preventing the system from sleeping, but does not necessarily prevent the + // app from being suspended on some platforms if the user hides it. + // Example use case: playing video. + PreventDisplaySleep = 1, +}; + +enum WakeLockReason { + // Audio is being played. + ReasonAudioPlayback = 0, + // Video is being played. + ReasonVideoPlayback = 1, + // WakeLock for some other reason. + ReasonOther = 2, +}; + // Context in which WakeLockService instances operate. interface WakeLockContext { // Gets a WakeLockService within this context. - GetWakeLock(WakeLockService& wake_lock); - - // Test-only method that returns whethere a wake lock is currently active - // within this context. - HasWakeLockForTests() => (bool result); + GetWakeLock(WakeLockType type, + WakeLockReason reason, + string description, + WakeLockService& wake_lock); }; diff --git a/chromium/device/wake_lock/public/interfaces/wake_lock_context_provider.mojom b/chromium/device/wake_lock/public/interfaces/wake_lock_context_provider.mojom deleted file mode 100644 index 442cf6de5f4..00000000000 --- a/chromium/device/wake_lock/public/interfaces/wake_lock_context_provider.mojom +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2015 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. - -module device.mojom; - -import "device/wake_lock/public/interfaces/wake_lock_context.mojom"; - -interface WakeLockContextProvider { - - // Gets a WakeLockContext that is associated with |context_id|. |context_id| - // is used to obtain the NativeView associated with the relevant context on - // Android (see WakeLockContextCallback). - GetContext(int32 context_id, WakeLockContext& context); -}; diff --git a/chromium/device/wake_lock/public/interfaces/wake_lock_provider.mojom b/chromium/device/wake_lock/public/interfaces/wake_lock_provider.mojom new file mode 100644 index 00000000000..417c0bdb613 --- /dev/null +++ b/chromium/device/wake_lock/public/interfaces/wake_lock_provider.mojom @@ -0,0 +1,25 @@ +// Copyright 2015 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. + +module device.mojom; + +import "device/wake_lock/public/interfaces/wake_lock_context.mojom"; +import "device/wake_lock/public/interfaces/wake_lock_service.mojom"; + +interface WakeLockProvider { + + // Gets a WakeLockContext that is associated with |context_id|. |context_id| + // is used to obtain the NativeView associated with the relevant context on + // Android (see WakeLockContextCallback). |context_id| must be >= 0. + GetWakeLockContextForID(int32 context_id, WakeLockContext& context); + + // Gets a WakeLock outside of any context. This method can be used + // if the client does not have any context available (e.g., is not + // within the context of a WebContents). However, note that the resulting + // Wake Lock will not have any effect on Android. + GetWakeLockWithoutContext(WakeLockType type, + WakeLockReason reason, + string description, + WakeLockService& wake_lock); +}; diff --git a/chromium/device/wake_lock/public/interfaces/wake_lock_service.mojom b/chromium/device/wake_lock/public/interfaces/wake_lock_service.mojom index 8c6e7a494c0..aa3b1daf199 100644 --- a/chromium/device/wake_lock/public/interfaces/wake_lock_service.mojom +++ b/chromium/device/wake_lock/public/interfaces/wake_lock_service.mojom @@ -6,6 +6,23 @@ module device.mojom; // WebLockService receives wake lock preferences from its client. interface WakeLockService { + // Requests that a wake lock be applied on behalf of this client. Has no + // effect if the client has previously called this method without + // subsequently calling CancelWakeLock(). RequestWakeLock(); + + // Cancels all outstanding wake lock requests from this client. If there are + // no more outstanding requests from any clients, the active wake lock (if + // there is one) will be turned off. CancelWakeLock(); + + // Adds a client to this WakeLockService instance. Clients are grouped on a + // per-WakeLockService instance basis: that is, a given WakeLockService + // instance turns on its wake lock whenever *any* of its clients make a + // request to do so and turns off its wake lock only when *all* its clients + // that had previously called RequestWakelock() cancel their requests. + AddClient(WakeLockService& wake_lock); + + // Test-only method that returns whether a wake lock is currently active. + HasWakeLockForTests() => (bool result); }; diff --git a/chromium/device/wake_lock/wake_lock_context_provider.cc b/chromium/device/wake_lock/wake_lock_context_provider.cc deleted file mode 100644 index 289b1c64296..00000000000 --- a/chromium/device/wake_lock/wake_lock_context_provider.cc +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2017 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 "device/wake_lock/wake_lock_context_provider.h" - -#include <utility> - -#include "mojo/public/cpp/bindings/strong_binding.h" - -namespace device { - -// static -void WakeLockContextProvider::Create( - mojom::WakeLockContextProviderRequest request, - scoped_refptr<base::SingleThreadTaskRunner> file_task_runner, - const WakeLockContextCallback& native_view_getter) { - mojo::MakeStrongBinding(base::MakeUnique<WakeLockContextProvider>( - std::move(file_task_runner), native_view_getter), - std::move(request)); -} - -WakeLockContextProvider::WakeLockContextProvider( - scoped_refptr<base::SingleThreadTaskRunner> file_task_runner, - const WakeLockContextCallback& native_view_getter) - : file_task_runner_(std::move(file_task_runner)), - native_view_getter_(native_view_getter) {} - -WakeLockContextProvider::~WakeLockContextProvider() {} - -void WakeLockContextProvider::GetContext( - int context_id, - mojo::InterfaceRequest<mojom::WakeLockContext> request) { - // WakeLockServiceContext owns itself (see the comment on - // wake_lock_service_context.h). - new WakeLockServiceContext(std::move(request), context_id, file_task_runner_, - native_view_getter_); -} - -} // namespace device diff --git a/chromium/device/wake_lock/wake_lock_provider.cc b/chromium/device/wake_lock/wake_lock_provider.cc new file mode 100644 index 00000000000..bbd4922fd99 --- /dev/null +++ b/chromium/device/wake_lock/wake_lock_provider.cc @@ -0,0 +1,53 @@ +// Copyright 2017 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 "device/wake_lock/wake_lock_provider.h" + +#include <utility> + +#include "device/wake_lock/wake_lock_service_impl.h" +#include "mojo/public/cpp/bindings/strong_binding.h" + +namespace device { + +// static +void WakeLockProvider::Create( + mojom::WakeLockProviderRequest request, + scoped_refptr<base::SingleThreadTaskRunner> file_task_runner, + const WakeLockContextCallback& native_view_getter) { + mojo::MakeStrongBinding(base::MakeUnique<WakeLockProvider>( + std::move(file_task_runner), native_view_getter), + std::move(request)); +} + +WakeLockProvider::WakeLockProvider( + scoped_refptr<base::SingleThreadTaskRunner> file_task_runner, + const WakeLockContextCallback& native_view_getter) + : file_task_runner_(std::move(file_task_runner)), + native_view_getter_(native_view_getter) {} + +WakeLockProvider::~WakeLockProvider() {} + +void WakeLockProvider::GetWakeLockContextForID( + int context_id, + mojo::InterfaceRequest<mojom::WakeLockContext> request) { + DCHECK(context_id >= 0); + mojo::MakeStrongBinding( + base::MakeUnique<WakeLockServiceContext>(context_id, file_task_runner_, + native_view_getter_), + std::move(request)); +} + +void WakeLockProvider::GetWakeLockWithoutContext( + mojom::WakeLockType type, + mojom::WakeLockReason reason, + const std::string& description, + mojom::WakeLockServiceRequest request) { + // WakeLockServiceImpl owns itself. + new WakeLockServiceImpl(std::move(request), type, reason, description, + WakeLockServiceContext::WakeLockInvalidContextId, + native_view_getter_, file_task_runner_); +} + +} // namespace device diff --git a/chromium/device/wake_lock/wake_lock_context_provider.h b/chromium/device/wake_lock/wake_lock_provider.h index 9909a089865..0177c287aec 100644 --- a/chromium/device/wake_lock/wake_lock_context_provider.h +++ b/chromium/device/wake_lock/wake_lock_provider.h @@ -2,12 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef DEVICE_WAKE_LOCK_WAKE_LOCK_CONTEXT_PROVIDER_H_ -#define DEVICE_WAKE_LOCK_WAKE_LOCK_CONTEXT_PROVIDER_H_ +#ifndef DEVICE_WAKE_LOCK_WAKE_LOCK_PROVIDER_H_ +#define DEVICE_WAKE_LOCK_WAKE_LOCK_PROVIDER_H_ #include "base/sequenced_task_runner.h" +#include "base/single_thread_task_runner.h" #include "device/wake_lock/public/interfaces/wake_lock_context.mojom.h" -#include "device/wake_lock/public/interfaces/wake_lock_context_provider.mojom.h" +#include "device/wake_lock/public/interfaces/wake_lock_provider.mojom.h" #include "device/wake_lock/wake_lock_service_context.h" #include "mojo/public/cpp/bindings/interface_request.h" #include "ui/gfx/native_widget_types.h" @@ -15,30 +16,35 @@ namespace device { // Serves requests for WakeLockContext connections. -class WakeLockContextProvider : public mojom::WakeLockContextProvider { +class WakeLockProvider : public mojom::WakeLockProvider { public: - WakeLockContextProvider( - scoped_refptr<base::SingleThreadTaskRunner> file_task_runner, - const WakeLockContextCallback& native_view_getter); - ~WakeLockContextProvider() override; + WakeLockProvider(scoped_refptr<base::SingleThreadTaskRunner> file_task_runner, + const WakeLockContextCallback& native_view_getter); + ~WakeLockProvider() override; static void Create( - mojom::WakeLockContextProviderRequest request, + mojom::WakeLockProviderRequest request, scoped_refptr<base::SingleThreadTaskRunner> file_task_runner, const WakeLockContextCallback& native_view_getter); - // mojom::WakeLockContextProvider: - void GetContext( + // mojom::WakeLockProvider: + void GetWakeLockContextForID( int context_id, mojo::InterfaceRequest<mojom::WakeLockContext> request) override; + void GetWakeLockWithoutContext( + mojom::WakeLockType type, + mojom::WakeLockReason reason, + const std::string& description, + mojom::WakeLockServiceRequest request) override; + private: scoped_refptr<base::SingleThreadTaskRunner> file_task_runner_; WakeLockContextCallback native_view_getter_; - DISALLOW_COPY_AND_ASSIGN(WakeLockContextProvider); + DISALLOW_COPY_AND_ASSIGN(WakeLockProvider); }; } // namespace device -#endif // DEVICE_WAKE_LOCK_WAKE_LOCK_CONTEXT_PROVIDER_H_ +#endif // DEVICE_WAKE_LOCK_WAKE_LOCK_PROVIDER_H_ diff --git a/chromium/device/wake_lock/wake_lock_service_context.cc b/chromium/device/wake_lock/wake_lock_service_context.cc index b56680f3806..682a4f934cd 100644 --- a/chromium/device/wake_lock/wake_lock_service_context.cc +++ b/chromium/device/wake_lock/wake_lock_service_context.cc @@ -6,103 +6,30 @@ #include <utility> -#include "base/bind.h" -#include "base/memory/ptr_util.h" -#include "base/threading/thread_task_runner_handle.h" -#include "build/build_config.h" -#include "device/power_save_blocker/power_save_blocker.h" +#include "device/wake_lock/wake_lock_service_impl.h" namespace device { +const int WakeLockServiceContext::WakeLockInvalidContextId = -1; + WakeLockServiceContext::WakeLockServiceContext( - mojom::WakeLockContextRequest request, int context_id, scoped_refptr<base::SingleThreadTaskRunner> file_task_runner, const WakeLockContextCallback& native_view_getter) - : main_task_runner_(base::ThreadTaskRunnerHandle::Get()), - file_task_runner_(std::move(file_task_runner)), - num_lock_requests_(0), -#if defined(OS_ANDROID) + : file_task_runner_(std::move(file_task_runner)), context_id_(context_id), - native_view_getter_(native_view_getter), -#endif - context_binding_(this, std::move(request)), - context_binding_encountered_error_(false) { - context_binding_.set_connection_error_handler(base::Bind( - &WakeLockServiceContext::OnContextBindingError, base::Unretained(this))); - wake_lock_bindings_.set_connection_error_handler( - base::Bind(&WakeLockServiceContext::DestroyIfNoLongerNeeded, - base::Unretained(this))); -} + native_view_getter_(native_view_getter) {} WakeLockServiceContext::~WakeLockServiceContext() {} void WakeLockServiceContext::GetWakeLock( - mojo::InterfaceRequest<mojom::WakeLockService> request) { - wake_lock_bindings_.AddBinding(base::MakeUnique<WakeLockServiceImpl>(this), - std::move(request)); -} - -void WakeLockServiceContext::RequestWakeLock() { - DCHECK(main_task_runner_->RunsTasksOnCurrentThread()); - num_lock_requests_++; - UpdateWakeLock(); -} - -void WakeLockServiceContext::CancelWakeLock() { - DCHECK(main_task_runner_->RunsTasksOnCurrentThread()); - num_lock_requests_--; - UpdateWakeLock(); -} - -void WakeLockServiceContext::HasWakeLockForTests( - const HasWakeLockForTestsCallback& callback) { - callback.Run(!!wake_lock_); -} - -void WakeLockServiceContext::CreateWakeLock() { - DCHECK(!wake_lock_); - wake_lock_.reset(new device::PowerSaveBlocker( - device::PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep, - device::PowerSaveBlocker::kReasonOther, "Wake Lock API", - main_task_runner_, file_task_runner_)); - -#if defined(OS_ANDROID) - gfx::NativeView native_view = native_view_getter_.Run(context_id_); - if (native_view) { - wake_lock_.get()->InitDisplaySleepBlocker(native_view); - } -#endif -} - -void WakeLockServiceContext::RemoveWakeLock() { - DCHECK(wake_lock_); - wake_lock_.reset(); -} - -void WakeLockServiceContext::UpdateWakeLock() { - DCHECK(num_lock_requests_ >= 0); - if (num_lock_requests_) { - if (!wake_lock_) - CreateWakeLock(); - } else { - if (wake_lock_) - RemoveWakeLock(); - } -} - -void WakeLockServiceContext::OnContextBindingError() { - context_binding_encountered_error_ = true; - DestroyIfNoLongerNeeded(); -} - -void WakeLockServiceContext::DestroyIfNoLongerNeeded() { - if (context_binding_encountered_error_ && wake_lock_bindings_.empty()) { - // Delete this instance once there are no more live connections to it. - // However, ensure that this instance stays alive throughout the destructor - // of a WakeLockServiceImpl instance that might be triggering this callback. - base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this); - } + mojom::WakeLockType type, + mojom::WakeLockReason reason, + const std::string& description, + mojom::WakeLockServiceRequest request) { + // WakeLockServiceImpl owns itself. + new WakeLockServiceImpl(std::move(request), type, reason, description, + context_id_, native_view_getter_, file_task_runner_); } } // namespace device diff --git a/chromium/device/wake_lock/wake_lock_service_context.h b/chromium/device/wake_lock/wake_lock_service_context.h index 0baa1a79c39..59253de5ccc 100644 --- a/chromium/device/wake_lock/wake_lock_service_context.h +++ b/chromium/device/wake_lock/wake_lock_service_context.h @@ -6,86 +6,42 @@ #define DEVICE_WAKE_LOCK_WAKE_LOCK_SERVICE_CONTEXT_H_ #include <memory> -#include <set> #include <utility> #include "base/callback.h" -#include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/sequenced_task_runner.h" +#include "base/single_thread_task_runner.h" #include "device/wake_lock/public/interfaces/wake_lock_context.mojom.h" -#include "device/wake_lock/wake_lock_service_impl.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "mojo/public/cpp/bindings/interface_request.h" -#include "mojo/public/cpp/bindings/strong_binding_set.h" #include "ui/gfx/native_widget_types.h" namespace device { -class PowerSaveBlocker; - // Callback that maps a context ID to the NativeView associated with // that context. This callback is provided to the Device Service by its // embedder. using WakeLockContextCallback = base::Callback<gfx::NativeView(int)>; // Serves requests for WakeLockService connections within a given context. - -// Note that the lifetime model of WakeLockContext is somewhat complex: It must -// stay alive as long as either -// (1) Its Mojo connection is still valid (as the client might make future -// GetWakeLock() calls) OR -// (2) There are still live WakeLock instances that it has instantiated (since -// they call into it when they receive Mojo requests from *their* clients). -// Consequently, WakeLockContext monitors the state of the connections described -// in (1) and (2), dying only when *all* of those connections go away. class WakeLockServiceContext : public mojom::WakeLockContext { public: WakeLockServiceContext( - mojom::WakeLockContextRequest request, int context_id, scoped_refptr<base::SingleThreadTaskRunner> file_task_runner, const WakeLockContextCallback& native_view_getter); ~WakeLockServiceContext() override; // mojom::WakeLockContext: - void GetWakeLock( - mojo::InterfaceRequest<mojom::WakeLockService> request) override; - void HasWakeLockForTests( - const HasWakeLockForTestsCallback& callback) override; - - // Requests wake lock. - void RequestWakeLock(); + void GetWakeLock(mojom::WakeLockType type, + mojom::WakeLockReason reason, + const std::string& description, + mojom::WakeLockServiceRequest request) override; - // Cancels pending wake lock request. - void CancelWakeLock(); + static const int WakeLockInvalidContextId; private: - void CreateWakeLock(); - void RemoveWakeLock(); - void UpdateWakeLock(); - void OnContextBindingError(); - - // Checks whether this instance is still needed, and if not, destroys it. - void DestroyIfNoLongerNeeded(); - - scoped_refptr<base::SequencedTaskRunner> main_task_runner_; scoped_refptr<base::SingleThreadTaskRunner> file_task_runner_; - - int num_lock_requests_; - - // The actual power save blocker for screen. - std::unique_ptr<PowerSaveBlocker> wake_lock_; - -#if defined(OS_ANDROID) int context_id_; WakeLockContextCallback native_view_getter_; -#endif - - mojo::Binding<mojom::WakeLockContext> context_binding_; - bool context_binding_encountered_error_; - - mojo::StrongBindingSet<mojom::WakeLockService> wake_lock_bindings_; DISALLOW_COPY_AND_ASSIGN(WakeLockServiceContext); }; diff --git a/chromium/device/wake_lock/wake_lock_service_impl.cc b/chromium/device/wake_lock/wake_lock_service_impl.cc index ae998aa62f4..a5065b6ba90 100644 --- a/chromium/device/wake_lock/wake_lock_service_impl.cc +++ b/chromium/device/wake_lock/wake_lock_service_impl.cc @@ -6,31 +6,160 @@ #include <utility> -#include "device/wake_lock/wake_lock_service_context.h" +#include "base/memory/ptr_util.h" namespace device { -WakeLockServiceImpl::WakeLockServiceImpl(WakeLockServiceContext* context) - : context_(context), wake_lock_request_outstanding_(false) {} +namespace { -WakeLockServiceImpl::~WakeLockServiceImpl() { - CancelWakeLock(); +PowerSaveBlocker::PowerSaveBlockerType ToPowerSaveBlockerType( + mojom::WakeLockType type) { + switch (type) { + case mojom::WakeLockType::PreventAppSuspension: + return PowerSaveBlocker::PowerSaveBlockerType:: + kPowerSaveBlockPreventAppSuspension; + case mojom::WakeLockType::PreventDisplaySleep: + return PowerSaveBlocker::PowerSaveBlockerType:: + kPowerSaveBlockPreventDisplaySleep; + } + + NOTREACHED(); + return PowerSaveBlocker::PowerSaveBlockerType:: + kPowerSaveBlockPreventAppSuspension; +} + +PowerSaveBlocker::Reason ToPowerSaveBlockerReason( + mojom::WakeLockReason reason) { + switch (reason) { + case mojom::WakeLockReason::ReasonAudioPlayback: + return PowerSaveBlocker::Reason::kReasonAudioPlayback; + case mojom::WakeLockReason::ReasonVideoPlayback: + return PowerSaveBlocker::Reason::kReasonVideoPlayback; + case mojom::WakeLockReason::ReasonOther: + return PowerSaveBlocker::Reason::kReasonOther; + } + + NOTREACHED(); + return PowerSaveBlocker::Reason::kReasonOther; +} + +} // namespace + +WakeLockServiceImpl::WakeLockServiceImpl( + mojom::WakeLockServiceRequest request, + mojom::WakeLockType type, + mojom::WakeLockReason reason, + const std::string& description, + int context_id, + WakeLockContextCallback native_view_getter, + scoped_refptr<base::SingleThreadTaskRunner> file_task_runner) + : type_(type), + reason_(reason), + description_(base::MakeUnique<std::string>(description)), + num_lock_requests_(0), +#if defined(OS_ANDROID) + context_id_(context_id), + native_view_getter_(native_view_getter), +#endif + main_task_runner_(base::ThreadTaskRunnerHandle::Get()), + file_task_runner_(std::move(file_task_runner)) { + AddClient(std::move(request)); + binding_set_.set_connection_error_handler(base::Bind( + &WakeLockServiceImpl::OnConnectionError, base::Unretained(this))); +} + +WakeLockServiceImpl::~WakeLockServiceImpl() {} + +void WakeLockServiceImpl::AddClient(mojom::WakeLockServiceRequest request) { + binding_set_.AddBinding(this, std::move(request), + base::MakeUnique<bool>(false)); } void WakeLockServiceImpl::RequestWakeLock() { - if (wake_lock_request_outstanding_) + DCHECK(main_task_runner_->RunsTasksInCurrentSequence()); + DCHECK(binding_set_.dispatch_context()); + + // Uses the Context to get the outstanding status of current binding. + // Two consecutive requests from the same client should be coalesced + // as one request. + if (*binding_set_.dispatch_context()) return; - wake_lock_request_outstanding_ = true; - context_->RequestWakeLock(); + *binding_set_.dispatch_context() = true; + num_lock_requests_++; + UpdateWakeLock(); } void WakeLockServiceImpl::CancelWakeLock() { - if (!wake_lock_request_outstanding_) + DCHECK(main_task_runner_->RunsTasksInCurrentSequence()); + DCHECK(binding_set_.dispatch_context()); + + if (!(*binding_set_.dispatch_context())) return; - wake_lock_request_outstanding_ = false; - context_->CancelWakeLock(); + DCHECK(num_lock_requests_ > 0); + *binding_set_.dispatch_context() = false; + num_lock_requests_--; + UpdateWakeLock(); +} + +void WakeLockServiceImpl::HasWakeLockForTests( + const HasWakeLockForTestsCallback& callback) { + callback.Run(!!wake_lock_); +} +void WakeLockServiceImpl::UpdateWakeLock() { + DCHECK(num_lock_requests_ >= 0); + + if (num_lock_requests_) { + if (!wake_lock_) + CreateWakeLock(); + } else { + if (wake_lock_) + RemoveWakeLock(); + } +} + +void WakeLockServiceImpl::CreateWakeLock() { + DCHECK(!wake_lock_); + + // TODO(heke): Switch PowerSaveBlocker to use mojom::WakeLockType and + // mojom::WakeLockReason once all its clients are converted to be the clients + // of WakeLock. + wake_lock_ = base::MakeUnique<PowerSaveBlocker>( + ToPowerSaveBlockerType(type_), ToPowerSaveBlockerReason(reason_), + *description_, main_task_runner_, file_task_runner_); + + if (type_ != mojom::WakeLockType::PreventDisplaySleep) + return; + +#if defined(OS_ANDROID) + if (context_id_ == WakeLockServiceContext::WakeLockInvalidContextId) { + LOG(ERROR) << "Client must pass a valid context_id when requests wake lock " + "on Android."; + return; + } + + gfx::NativeView native_view = native_view_getter_.Run(context_id_); + if (native_view) + wake_lock_.get()->InitDisplaySleepBlocker(native_view); +#endif +} + +void WakeLockServiceImpl::RemoveWakeLock() { + DCHECK(wake_lock_); + wake_lock_.reset(); +} + +void WakeLockServiceImpl::OnConnectionError() { + // If this client has an outstanding wake lock request, decrease the + // num_lock_requests and call UpdateWakeLock(). + if (*binding_set_.dispatch_context() && num_lock_requests_ > 0) { + num_lock_requests_--; + UpdateWakeLock(); + } + + if (binding_set_.empty()) + base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this); } } // namespace device diff --git a/chromium/device/wake_lock/wake_lock_service_impl.h b/chromium/device/wake_lock/wake_lock_service_impl.h index c66ec8d1a8f..a64ff40843c 100644 --- a/chromium/device/wake_lock/wake_lock_service_impl.h +++ b/chromium/device/wake_lock/wake_lock_service_impl.h @@ -5,27 +5,67 @@ #ifndef DEVICE_WAKE_LOCK_WAKE_LOCK_SERVICE_IMPL_H_ #define DEVICE_WAKE_LOCK_WAKE_LOCK_SERVICE_IMPL_H_ +#include <memory> + #include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/single_thread_task_runner.h" +#include "device/power_save_blocker/power_save_blocker.h" +#include "device/wake_lock/public/interfaces/wake_lock_context.mojom.h" #include "device/wake_lock/public/interfaces/wake_lock_service.mojom.h" -#include "mojo/public/cpp/bindings/interface_request.h" +#include "device/wake_lock/wake_lock_service_context.h" +#include "mojo/public/cpp/bindings/binding_set.h" +#include "ui/gfx/native_widget_types.h" namespace device { -class WakeLockServiceContext; - class WakeLockServiceImpl : public mojom::WakeLockService { public: - explicit WakeLockServiceImpl(WakeLockServiceContext* context); + WakeLockServiceImpl( + mojom::WakeLockServiceRequest request, + mojom::WakeLockType type, + mojom::WakeLockReason reason, + const std::string& description, + int context_id, + WakeLockContextCallback native_view_getter, + scoped_refptr<base::SingleThreadTaskRunner> file_task_runner); ~WakeLockServiceImpl() override; // WakeLockSevice implementation. void RequestWakeLock() override; void CancelWakeLock() override; + void AddClient(mojom::WakeLockServiceRequest request) override; + void HasWakeLockForTests( + const HasWakeLockForTestsCallback& callback) override; private: - // Will outlive this instance. - WakeLockServiceContext* context_; - bool wake_lock_request_outstanding_; + void UpdateWakeLock(); + void CreateWakeLock(); + void RemoveWakeLock(); + void OnConnectionError(); + + mojom::WakeLockType type_; + mojom::WakeLockReason reason_; + std::unique_ptr<std::string> description_; + int num_lock_requests_; + +#if defined(OS_ANDROID) + int context_id_; + WakeLockContextCallback native_view_getter_; +#endif + + scoped_refptr<base::SequencedTaskRunner> main_task_runner_; + scoped_refptr<base::SingleThreadTaskRunner> file_task_runner_; + + // The actual power save blocker for screen. + std::unique_ptr<PowerSaveBlocker> wake_lock_; + + // Multiple clients that associate to the same WebContents share the same one + // WakeLockServiceImpl instance. Two consecutive |RequestWakeLock| requests + // from the same client should be coalesced as one request. Everytime a new + // client is being added into the BindingSet, we create an unique_ptr<bool> + // as its context, which records this client's request status. + mojo::BindingSet<mojom::WakeLockService, std::unique_ptr<bool>> binding_set_; DISALLOW_COPY_AND_ASSIGN(WakeLockServiceImpl); }; |