| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/bluetooth/frame_connected_bluetooth_devices.h" | 5 #include "content/browser/bluetooth/frame_connected_bluetooth_devices.h" |
| 6 | 6 |
| 7 #include "base/memory/ptr_util.h" | 7 #include "base/memory/ptr_util.h" |
| 8 #include "base/memory/ref_counted.h" | 8 #include "base/memory/ref_counted.h" |
| 9 #include "content/browser/bluetooth/web_bluetooth_service_impl.h" |
| 9 #include "content/test/test_render_view_host.h" | 10 #include "content/test/test_render_view_host.h" |
| 10 #include "content/test/test_web_contents.h" | 11 #include "content/test/test_web_contents.h" |
| 11 #include "device/bluetooth/bluetooth_gatt_connection.h" | 12 #include "device/bluetooth/bluetooth_gatt_connection.h" |
| 12 #include "device/bluetooth/test/mock_bluetooth_adapter.h" | 13 #include "device/bluetooth/test/mock_bluetooth_adapter.h" |
| 13 #include "device/bluetooth/test/mock_bluetooth_device.h" | 14 #include "device/bluetooth/test/mock_bluetooth_device.h" |
| 14 #include "device/bluetooth/test/mock_bluetooth_gatt_connection.h" | 15 #include "device/bluetooth/test/mock_bluetooth_gatt_connection.h" |
| 15 #include "testing/gmock/include/gmock/gmock.h" | 16 #include "testing/gmock/include/gmock/gmock.h" |
| 16 #include "testing/gtest/include/gtest/gtest.h" | 17 #include "testing/gtest/include/gtest/gtest.h" |
| 17 | 18 |
| 18 namespace content { | 19 namespace content { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 30 namespace { | 31 namespace { |
| 31 | 32 |
| 32 constexpr char kDeviceId0[] = "0"; | 33 constexpr char kDeviceId0[] = "0"; |
| 33 constexpr char kDeviceAddress0[] = "0"; | 34 constexpr char kDeviceAddress0[] = "0"; |
| 34 constexpr char kDeviceName0[] = "Device0"; | 35 constexpr char kDeviceName0[] = "Device0"; |
| 35 | 36 |
| 36 constexpr char kDeviceId1[] = "1"; | 37 constexpr char kDeviceId1[] = "1"; |
| 37 constexpr char kDeviceAddress1[] = "1"; | 38 constexpr char kDeviceAddress1[] = "1"; |
| 38 constexpr char kDeviceName1[] = "Device1"; | 39 constexpr char kDeviceName1[] = "Device1"; |
| 39 | 40 |
| 41 } // namespace |
| 42 |
| 40 class FrameConnectedBluetoothDevicesTest | 43 class FrameConnectedBluetoothDevicesTest |
| 41 : public RenderViewHostImplTestHarness { | 44 : public RenderViewHostImplTestHarness { |
| 42 public: | 45 public: |
| 43 FrameConnectedBluetoothDevicesTest() | 46 FrameConnectedBluetoothDevicesTest() |
| 44 : adapter_(new NiceMockBluetoothAdapter()), | 47 : adapter_(new NiceMockBluetoothAdapter()), |
| 45 device0_(adapter_.get(), | 48 device0_(adapter_.get(), |
| 46 0 /* class */, | 49 0 /* class */, |
| 47 kDeviceName0, | 50 kDeviceName0, |
| 48 kDeviceAddress0, | 51 kDeviceAddress0, |
| 49 false /* paired */, | 52 false /* paired */, |
| 50 false /* connected */), | 53 false /* connected */), |
| 51 device1_(adapter_.get(), | 54 device1_(adapter_.get(), |
| 52 0 /* class */, | 55 0 /* class */, |
| 53 kDeviceName1, | 56 kDeviceName1, |
| 54 kDeviceAddress1, | 57 kDeviceAddress1, |
| 55 false /* paired */, | 58 false /* paired */, |
| 56 false /* connected */) { | 59 false /* connected */) { |
| 57 ON_CALL(*adapter_, GetDevice(_)).WillByDefault(Return(nullptr)); | 60 ON_CALL(*adapter_, GetDevice(_)).WillByDefault(Return(nullptr)); |
| 58 ON_CALL(*adapter_, GetDevice(StrEq(kDeviceAddress0))) | 61 ON_CALL(*adapter_, GetDevice(StrEq(kDeviceAddress0))) |
| 59 .WillByDefault(Return(&device0_)); | 62 .WillByDefault(Return(&device0_)); |
| 60 ON_CALL(*adapter_, GetDevice(StrEq(kDeviceAddress1))) | 63 ON_CALL(*adapter_, GetDevice(StrEq(kDeviceAddress1))) |
| 61 .WillByDefault(Return(&device1_)); | 64 .WillByDefault(Return(&device1_)); |
| 62 } | 65 } |
| 63 | 66 |
| 64 ~FrameConnectedBluetoothDevicesTest() override {} | 67 ~FrameConnectedBluetoothDevicesTest() override {} |
| 65 | 68 |
| 66 void SetUp() override { | 69 void SetUp() override { |
| 67 RenderViewHostImplTestHarness::SetUp(); | 70 RenderViewHostImplTestHarness::SetUp(); |
| 68 map0_.reset(new FrameConnectedBluetoothDevices(contents()->GetMainFrame())); | 71 |
| 69 map1_.reset(new FrameConnectedBluetoothDevices(contents()->GetMainFrame())); | 72 // TODO(nick): This test used to work by creating two |
| 73 // FrameConnectedBluetoothDevices instances on the same RenderFrameHost. But |
| 74 // that would never possibly happen in reality! To get two |
| 75 // FrameConnectedBluetoothDevices on the same WebContents, we should create |
| 76 // a child frame. |
| 77 contents()->GetMainFrame()->InitializeRenderFrameIfNeeded(); |
| 78 TestRenderFrameHost* subframe = |
| 79 contents()->GetMainFrame()->AppendChild("bluetooth_frame"); |
| 80 subframe->InitializeRenderFrameIfNeeded(); |
| 81 |
| 82 // Simulate two frames each connected to a bluetooth service. |
| 83 service0_ = |
| 84 contents()->GetMainFrame()->CreateWebBluetoothServiceForTesting(); |
| 85 map0_ = service0_->connected_devices_.get(); |
| 86 |
| 87 service1_ = subframe->CreateWebBluetoothServiceForTesting(); |
| 88 map1_ = service1_->connected_devices_.get(); |
| 70 } | 89 } |
| 71 | 90 |
| 72 void TearDown() override { | 91 void TearDown() override { |
| 73 map1_.reset(); | |
| 74 map0_.reset(); | |
| 75 RenderViewHostImplTestHarness::TearDown(); | 92 RenderViewHostImplTestHarness::TearDown(); |
| 76 } | 93 } |
| 77 | 94 |
| 78 std::unique_ptr<NiceMockBluetoothGattConnection> GetConnection( | 95 std::unique_ptr<NiceMockBluetoothGattConnection> GetConnection( |
| 79 const std::string& address) { | 96 const std::string& address) { |
| 80 return base::WrapUnique( | 97 return base::WrapUnique( |
| 81 new NiceMockBluetoothGattConnection(adapter_.get(), address)); | 98 new NiceMockBluetoothGattConnection(adapter_.get(), address)); |
| 82 } | 99 } |
| 83 | 100 |
| 101 void ResetService0() { |
| 102 service0_->ClearState(); |
| 103 map0_ = nullptr; |
| 104 } |
| 105 |
| 106 void ResetService1() { |
| 107 service1_->ClearState(); |
| 108 map1_ = nullptr; |
| 109 } |
| 110 |
| 84 protected: | 111 protected: |
| 85 std::unique_ptr<FrameConnectedBluetoothDevices> map0_; | 112 FrameConnectedBluetoothDevices* map0_; |
| 86 std::unique_ptr<FrameConnectedBluetoothDevices> map1_; | 113 WebBluetoothServiceImpl* service0_; |
| 114 |
| 115 FrameConnectedBluetoothDevices* map1_; |
| 116 WebBluetoothServiceImpl* service1_; |
| 87 | 117 |
| 88 private: | 118 private: |
| 89 scoped_refptr<NiceMockBluetoothAdapter> adapter_; | 119 scoped_refptr<NiceMockBluetoothAdapter> adapter_; |
| 90 NiceMockBluetoothDevice device0_; | 120 NiceMockBluetoothDevice device0_; |
| 91 NiceMockBluetoothDevice device1_; | 121 NiceMockBluetoothDevice device1_; |
| 92 }; | 122 }; |
| 93 | 123 |
| 94 } // namespace | |
| 95 | |
| 96 TEST_F(FrameConnectedBluetoothDevicesTest, Insert_Once) { | 124 TEST_F(FrameConnectedBluetoothDevicesTest, Insert_Once) { |
| 97 map0_->Insert(kDeviceId0, GetConnection(kDeviceAddress0)); | 125 map0_->Insert(kDeviceId0, GetConnection(kDeviceAddress0)); |
| 98 | 126 |
| 99 EXPECT_TRUE(contents()->IsConnectedToBluetoothDevice()); | 127 EXPECT_TRUE(contents()->IsConnectedToBluetoothDevice()); |
| 100 EXPECT_TRUE(map0_->IsConnectedToDeviceWithId(kDeviceId0)); | 128 EXPECT_TRUE(map0_->IsConnectedToDeviceWithId(kDeviceId0)); |
| 101 } | 129 } |
| 102 | 130 |
| 103 TEST_F(FrameConnectedBluetoothDevicesTest, Insert_Twice) { | 131 TEST_F(FrameConnectedBluetoothDevicesTest, Insert_Twice) { |
| 104 map0_->Insert(kDeviceId0, GetConnection(kDeviceAddress0)); | 132 map0_->Insert(kDeviceId0, GetConnection(kDeviceAddress0)); |
| 105 map0_->Insert(kDeviceId0, GetConnection(kDeviceAddress0)); | 133 map0_->Insert(kDeviceId0, GetConnection(kDeviceAddress0)); |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 323 EXPECT_FALSE(contents()->IsConnectedToBluetoothDevice()); | 351 EXPECT_FALSE(contents()->IsConnectedToBluetoothDevice()); |
| 324 EXPECT_FALSE(map1_->IsConnectedToDeviceWithId(kDeviceId1)); | 352 EXPECT_FALSE(map1_->IsConnectedToDeviceWithId(kDeviceId1)); |
| 325 } | 353 } |
| 326 | 354 |
| 327 TEST_F(FrameConnectedBluetoothDevicesTest, Destruction_MultipleDevices) { | 355 TEST_F(FrameConnectedBluetoothDevicesTest, Destruction_MultipleDevices) { |
| 328 map0_->Insert(kDeviceId0, GetConnection(kDeviceAddress0)); | 356 map0_->Insert(kDeviceId0, GetConnection(kDeviceAddress0)); |
| 329 map0_->Insert(kDeviceId1, GetConnection(kDeviceAddress1)); | 357 map0_->Insert(kDeviceId1, GetConnection(kDeviceAddress1)); |
| 330 | 358 |
| 331 EXPECT_TRUE(contents()->IsConnectedToBluetoothDevice()); | 359 EXPECT_TRUE(contents()->IsConnectedToBluetoothDevice()); |
| 332 | 360 |
| 333 map0_.reset(); | 361 ResetService0(); |
| 334 | 362 |
| 335 EXPECT_FALSE(contents()->IsConnectedToBluetoothDevice()); | 363 EXPECT_FALSE(contents()->IsConnectedToBluetoothDevice()); |
| 336 } | 364 } |
| 337 | 365 |
| 338 TEST_F(FrameConnectedBluetoothDevicesTest, Destruction_MultipleMaps) { | 366 TEST_F(FrameConnectedBluetoothDevicesTest, Destruction_MultipleMaps) { |
| 339 map0_->Insert(kDeviceId0, GetConnection(kDeviceAddress0)); | 367 map0_->Insert(kDeviceId0, GetConnection(kDeviceAddress0)); |
| 340 map0_->Insert(kDeviceId1, GetConnection(kDeviceAddress1)); | 368 map0_->Insert(kDeviceId1, GetConnection(kDeviceAddress1)); |
| 341 | 369 |
| 342 map1_->Insert(kDeviceId0, GetConnection(kDeviceAddress0)); | 370 map1_->Insert(kDeviceId0, GetConnection(kDeviceAddress0)); |
| 343 map1_->Insert(kDeviceId1, GetConnection(kDeviceAddress1)); | 371 map1_->Insert(kDeviceId1, GetConnection(kDeviceAddress1)); |
| 344 | 372 |
| 345 EXPECT_TRUE(contents()->IsConnectedToBluetoothDevice()); | 373 EXPECT_TRUE(contents()->IsConnectedToBluetoothDevice()); |
| 346 | 374 |
| 347 map0_.reset(); | 375 ResetService0(); |
| 348 | 376 |
| 349 // WebContents should still be connected because of map1_. | 377 // WebContents should still be connected because of map1_. |
| 350 EXPECT_TRUE(contents()->IsConnectedToBluetoothDevice()); | 378 EXPECT_TRUE(contents()->IsConnectedToBluetoothDevice()); |
| 351 | 379 |
| 352 map1_.reset(); | 380 ResetService1(); |
| 353 | 381 |
| 354 EXPECT_FALSE(contents()->IsConnectedToBluetoothDevice()); | 382 EXPECT_FALSE(contents()->IsConnectedToBluetoothDevice()); |
| 355 } | 383 } |
| 356 | 384 |
| 357 TEST_F(FrameConnectedBluetoothDevicesTest, | 385 TEST_F(FrameConnectedBluetoothDevicesTest, |
| 358 DestroyedByWebContentsImplDestruction) { | 386 DestroyedByWebContentsImplDestruction) { |
| 359 // Tests that we don't crash when FrameConnectedBluetoothDevices contains | 387 // Tests that we don't crash when FrameConnectedBluetoothDevices contains |
| 360 // at least one device, and it is destroyed while WebContentsImpl is being | 388 // at least one device, and it is destroyed while WebContentsImpl is being |
| 361 // destroyed. | 389 // destroyed. |
| 362 | |
| 363 map0_->Insert(kDeviceId0, GetConnection(kDeviceAddress0)); | 390 map0_->Insert(kDeviceId0, GetConnection(kDeviceAddress0)); |
| 364 // A FrameConnectedBluetoothDevices instance is usually owned by a | |
| 365 // WebBluetoothServiceImpl instance which is owned by a RenderFrameHost which | |
| 366 // is owned by WebContentsImpl. In order to avoid adding unnecessary | |
| 367 // complexity to WebBluetoothServiceImpl just so we can perform this test we | |
| 368 // add the map directly to a frame and then delete WebContents. | |
| 369 contents()->GetMainFrame()->SetFrameConnectedBluetoothDevices( | |
| 370 std::move(map0_)); | |
| 371 DeleteContents(); | 391 DeleteContents(); |
| 372 } | 392 } |
| 373 | 393 |
| 374 } // namespace content | 394 } // namespace content |
| OLD | NEW |