OLD | NEW |
1 (() => { | 1 (() => { |
2 let mojo_; | 2 let mojo_; |
3 | 3 |
4 async function loadFakeBluetoothInterfaces() { | 4 async function loadFakeBluetoothInterfaces() { |
5 if(typeof mojo_ !== 'undefined') { | 5 if(typeof mojo_ !== 'undefined') { |
6 return mojo_; | 6 return mojo_; |
7 } | 7 } |
8 | 8 |
9 if (typeof loadMojoModules === 'undefined') { | 9 if (typeof loadMojoModules === 'undefined') { |
10 throw 'Mojo is required for this API.' | 10 throw 'Mojo is required for this API.' |
11 } | 11 } |
12 | 12 |
13 mojo_ = await loadMojoModules('fakeBluetooth', [ | 13 mojo_ = await loadMojoModules('fakeBluetooth', [ |
14 'mojo/public/js/bindings', | 14 'mojo/public/js/bindings', |
15 'device/bluetooth/public/interfaces/test/fake_bluetooth.mojom' | 15 'device/bluetooth/public/interfaces/test/fake_bluetooth.mojom' |
16 ]); | 16 ]); |
17 | 17 |
18 [mojo_.bindings, { | 18 [mojo_.bindings, { |
19 CentralState: mojo_.CentralState, | 19 CentralState: mojo_.CentralState, |
20 FakeBluetooth: mojo_.FakeBluetooth, | 20 FakeBluetooth: mojo_.FakeBluetooth, |
21 FakeBluetoothPtr: mojo_.FakeBluetoothPtr, | 21 FakeBluetoothPtr: mojo_.FakeBluetoothPtr, |
22 FakeCentral: mojo_.FakeCentral, | 22 FakeCentral: mojo_.FakeCentral, |
23 FakeCentralPtr: mojo_.FakeCentralPtr, | 23 FakeCentralPtr: mojo_.FakeCentralPtr, |
24 }] = mojo_.modules; | 24 }] = mojo_.modules; |
25 | 25 |
26 return mojo_; | 26 return mojo_; |
27 } | 27 } |
28 | 28 |
| 29 function toMojoCentralState(state) { |
| 30 switch (state) { |
| 31 case 'absent': |
| 32 return mojo_.CentralState.ABSENT; |
| 33 case 'powered-off': |
| 34 return mojo_.CentralState.POWERED_OFF; |
| 35 case 'powered-on': |
| 36 return mojo_.CentralState.POWERED_ON; |
| 37 default: |
| 38 throw `Unsupported value ${state} for state.`; |
| 39 } |
| 40 } |
| 41 |
29 class FakeBluetooth { | 42 class FakeBluetooth { |
30 constructor() { | 43 constructor() { |
31 this.fake_bluetooth_ptr_ = undefined; | 44 this.fake_bluetooth_ptr_ = undefined; |
32 } | 45 } |
33 | 46 |
34 // Set it to indicate whether the platform supports BLE. For example, | 47 // Set it to indicate whether the platform supports BLE. For example, |
35 // Windows 7 is a platform that doesn't support Low Energy. On the other | 48 // Windows 7 is a platform that doesn't support Low Energy. On the other |
36 // hand Windows 10 is a platform that does support LE, even if there is no | 49 // hand Windows 10 is a platform that does support LE, even if there is no |
37 // Bluetooth radio present. | 50 // Bluetooth radio present. |
38 async setLESupported(supported) { | 51 async setLESupported(supported) { |
39 // Call setBluetoothFakeAdapter() to clean up any fake adapters left over | 52 // Call setBluetoothFakeAdapter() to clean up any fake adapters left over |
40 // by legacy tests. | 53 // by legacy tests. |
41 // Legacy tests that use setBluetoothFakeAdapter() sometimes fail to clean | 54 // Legacy tests that use setBluetoothFakeAdapter() sometimes fail to clean |
42 // their fake adapter. This is not a problem for these tests because the | 55 // their fake adapter. This is not a problem for these tests because the |
43 // next setBluetoothFakeAdapter() will clean it up anyway but it is a | 56 // next setBluetoothFakeAdapter() will clean it up anyway but it is a |
44 // problem for the new tests that do not use setBluetoothFakeAdapter(). | 57 // problem for the new tests that do not use setBluetoothFakeAdapter(). |
45 // TODO(crbug.com/569709): Remove once setBluetoothFakeAdapter is no | 58 // TODO(crbug.com/569709): Remove once setBluetoothFakeAdapter is no |
46 // longer used. | 59 // longer used. |
47 await setBluetoothFakeAdapter(''); | 60 await setBluetoothFakeAdapter(''); |
| 61 await this.initFakeBluetoothInterfacePtr_(); |
48 | 62 |
49 if (typeof supported !== 'boolean') throw 'Type Not Supported'; | 63 if (typeof supported !== 'boolean') throw 'Type Not Supported'; |
50 await (await this.getFakeBluetoothInterface_()).setLESupported(supported); | 64 await this.fake_bluetooth_ptr_.setLESupported(supported); |
51 } | 65 } |
52 | 66 |
53 // Returns a promise that resolves with a FakeCentral that clients can use | 67 // Returns a promise that resolves with a FakeCentral that clients can use |
54 // to simulate events that a device in the Central/Observer role would | 68 // to simulate events that a device in the Central/Observer role would |
55 // receive as well as monitor the operations performed by the device in the | 69 // receive as well as monitor the operations performed by the device in the |
56 // Central/Observer role. | 70 // Central/Observer role. |
57 // Calls sets LE as supported. | 71 // Calls sets LE as supported. |
58 // | 72 // |
59 // A "Central" object would allow its clients to receive advertising events | 73 // A "Central" object would allow its clients to receive advertising events |
60 // and initiate connections to peripherals i.e. operations of two roles | 74 // and initiate connections to peripherals i.e. operations of two roles |
61 // defined by the Bluetooth Spec: Observer and Central. | 75 // defined by the Bluetooth Spec: Observer and Central. |
62 // See Bluetooth 4.2 Vol 3 Part C 2.2.2 "Roles when Operating over an | 76 // See Bluetooth 4.2 Vol 3 Part C 2.2.2 "Roles when Operating over an |
63 // LE Physical Transport". | 77 // LE Physical Transport". |
64 async simulateCentral({state}) { | 78 async simulateCentral({state}) { |
65 // Call setBluetoothFakeAdapter() to clean up any fake adapters left over | 79 // Call setBluetoothFakeAdapter() to clean up any fake adapters left over |
66 // by legacy tests. | 80 // by legacy tests. |
67 // Legacy tests that use setBluetoothFakeAdapter() sometimes fail to clean | 81 // Legacy tests that use setBluetoothFakeAdapter() sometimes fail to clean |
68 // their fake adapter. This is not a problem for these tests because the | 82 // their fake adapter. This is not a problem for these tests because the |
69 // next setBluetoothFakeAdapter() will clean it up anyway but it is a | 83 // next setBluetoothFakeAdapter() will clean it up anyway but it is a |
70 // problem for the new tests that do not use setBluetoothFakeAdapter(). | 84 // problem for the new tests that do not use setBluetoothFakeAdapter(). |
71 // TODO(crbug.com/569709): Remove once setBluetoothFakeAdapter is no | 85 // TODO(crbug.com/569709): Remove once setBluetoothFakeAdapter is no |
72 // longer used. | 86 // longer used. |
73 await setBluetoothFakeAdapter(''); | 87 await setBluetoothFakeAdapter(''); |
| 88 await this.initFakeBluetoothInterfacePtr_(); |
74 | 89 |
75 await this.setLESupported(true); | 90 await this.setLESupported(true); |
76 let mojo = await loadFakeBluetoothInterfaces(); | |
77 | |
78 let mojo_manager_state; | |
79 switch (state) { | |
80 case 'absent': | |
81 mojo_manager_state = mojo.CentralState.ABSENT; | |
82 break; | |
83 case 'powered-off': | |
84 mojo_manager_state = mojo.CentralState.POWERED_OFF; | |
85 break; | |
86 case 'powered-on': | |
87 mojo_manager_state = mojo.CentralState.POWERED_ON; | |
88 break; | |
89 default: | |
90 throw `Unsupported value ${state} for state.`; | |
91 } | |
92 | 91 |
93 let {fake_central:fake_central_ptr} = | 92 let {fake_central:fake_central_ptr} = |
94 await (await this.getFakeBluetoothInterface_()).simulateCentral( | 93 await this.fake_bluetooth_ptr_.simulateCentral( |
95 mojo_manager_state); | 94 toMojoCentralState(state)); |
96 | |
97 return new FakeCentral(fake_central_ptr); | 95 return new FakeCentral(fake_central_ptr); |
98 } | 96 } |
99 | 97 |
100 async getFakeBluetoothInterface_() { | 98 async initFakeBluetoothInterfacePtr_() { |
101 if (typeof this.fake_bluetooth_ptr_ !== 'undefined') { | 99 if (typeof this.fake_bluetooth_ptr_ !== 'undefined') { |
102 return this.fake_bluetooth_ptr_; | 100 return this.fake_bluetooth_ptr_; |
103 } | 101 } |
104 | 102 |
105 let mojo = await loadFakeBluetoothInterfaces(); | 103 let mojo = await loadFakeBluetoothInterfaces(); |
106 | 104 |
107 this.fake_bluetooth_ptr_ = new mojo.FakeBluetoothPtr( | 105 this.fake_bluetooth_ptr_ = new mojo.FakeBluetoothPtr( |
108 mojo.interfaces.getInterface(mojo.FakeBluetooth.name)); | 106 mojo.interfaces.getInterface(mojo.FakeBluetooth.name)); |
109 | |
110 return this.fake_bluetooth_ptr_; | |
111 } | 107 } |
112 } | 108 } |
113 | 109 |
114 // FakeCentral allows clients to simulate events that a device in the | 110 // FakeCentral allows clients to simulate events that a device in the |
115 // Central/Observer role would receive as well as monitor the operations | 111 // Central/Observer role would receive as well as monitor the operations |
116 // performed by the device in the Central/Observer role. | 112 // performed by the device in the Central/Observer role. |
117 class FakeCentral { | 113 class FakeCentral { |
118 constructor(fake_central_ptr) { | 114 constructor(fake_central_ptr) { |
119 this.fake_central_ptr_ = fake_central_ptr; | 115 this.fake_central_ptr_ = fake_central_ptr; |
120 this.peripherals_ = new Map(); | 116 this.peripherals_ = new Map(); |
121 } | 117 } |
122 | 118 |
123 // Simulates a peripheral with |address| and |name| that has already | 119 // Simulates a peripheral with |address|, |name| and |known_service_uuids| |
124 // been connected to the system. If the peripheral existed already it | 120 // that has already been connected to the system. If the peripheral existed |
125 // updates its name. | 121 // already it updates its name and known UUIDs. |known_service_uuids| should |
| 122 // be an array of BluetoothServiceUUIDs |
| 123 // https://webbluetoothcg.github.io/web-bluetooth/#typedefdef-bluetoothservi
ceuuid |
126 // | 124 // |
127 // Platforms offer methods to retrieve devices that have already been | 125 // Platforms offer methods to retrieve devices that have already been |
128 // connected to the system or weren't connected through the UA e.g. a | 126 // connected to the system or weren't connected through the UA e.g. a user |
129 // user connected a peripheral through the system's settings. This method is | 127 // connected a peripheral through the system's settings. This method is |
130 // intended to simulate peripherals that those methods would return. | 128 // intended to simulate peripherals that those methods would return. |
131 async simulatePreconnectedPeripheral({address, name}) { | 129 async simulatePreconnectedPeripheral({ |
| 130 address, name, knownServiceUUIDs = []}) { |
| 131 |
| 132 // Canonicalize and convert to mojo UUIDs. |
| 133 knownServiceUUIDs.forEach((val, i, arr) => { |
| 134 knownServiceUUIDs[i] = {uuid: BluetoothUUID.getService(val)}; |
| 135 }); |
| 136 |
132 await this.fake_central_ptr_.simulatePreconnectedPeripheral( | 137 await this.fake_central_ptr_.simulatePreconnectedPeripheral( |
133 address, name); | 138 address, name, knownServiceUUIDs); |
134 | 139 |
135 let peripheral = this.peripherals_.get(address); | 140 let peripheral = this.peripherals_.get(address); |
136 if (peripheral === undefined) { | 141 if (peripheral === undefined) { |
137 peripheral = new FakePeripheral(address, this); | 142 peripheral = new FakePeripheral(address, this); |
138 this.peripherals_.set(address, peripheral); | 143 this.peripherals_.set(address, peripheral); |
139 } | 144 } |
140 | 145 |
141 return peripheral; | 146 return peripheral; |
142 } | 147 } |
143 } | 148 } |
144 | 149 |
145 class FakePeripheral { | 150 class FakePeripheral { |
146 constructor(address, fake_central) { | 151 constructor(address, fake_central) { |
147 this.address = address; | 152 this.address = address; |
148 this.fake_central_ = fake_central; | 153 this.fake_central_ = fake_central; |
149 } | 154 } |
150 } | 155 } |
151 | 156 |
152 navigator.bluetooth.test = new FakeBluetooth(); | 157 navigator.bluetooth.test = new FakeBluetooth(); |
153 })(); | 158 })(); |
OLD | NEW |