| OLD | NEW |
| 1 'use strict'; | 1 'use strict'; |
| 2 | 2 |
| 3 // This polyfil library implements the following WebIDL: | 3 // This polyfil library implements the following WebIDL: |
| 4 // | 4 // |
| 5 // partial interface USB { | 5 // partial interface USB { |
| 6 // [SameObject] readonly attribute USBTest test; | 6 // [SameObject] readonly attribute USBTest test; |
| 7 // } | 7 // } |
| 8 // | 8 // |
| 9 // interface USBTest { | 9 // interface USBTest { |
| 10 // attribute EventHandler ondeviceclose; | 10 // attribute EventHandler ondeviceclose; |
| 11 // attribute DOMString? chosenDevice; | 11 // attribute FakeUSBDevice? chosenDevice; |
| 12 // attribute FrozenArray<USBDeviceFilter>? lastFilters; | 12 // attribute FrozenArray<USBDeviceFilter>? lastFilters; |
| 13 // | 13 // |
| 14 // Promise<void> initialize(); | 14 // Promise<void> initialize(); |
| 15 // Promise<void> attachToWindow(Window window); | 15 // Promise<void> attachToWindow(Window window); |
| 16 // DOMString addFakeDevice(FakeUSBDeviceInit deviceInit); | 16 // FakeUSBDevice addFakeDevice(FakeUSBDeviceInit deviceInit); |
| 17 // void removeFakeDevice(DOMString); | |
| 18 // void reset(); | 17 // void reset(); |
| 19 // }; | 18 // }; |
| 20 // | 19 // |
| 20 // interface FakeUSBDevice { |
| 21 // void disconnect(); |
| 22 // }; |
| 23 // |
| 21 // dictionary FakeUSBDeviceInit { | 24 // dictionary FakeUSBDeviceInit { |
| 22 // octet usbVersionMajor; | 25 // octet usbVersionMajor; |
| 23 // octet usbVersionMinor; | 26 // octet usbVersionMinor; |
| 24 // octet usbVersionSubminor; | 27 // octet usbVersionSubminor; |
| 25 // octet deviceClass; | 28 // octet deviceClass; |
| 26 // octet deviceSubclass; | 29 // octet deviceSubclass; |
| 27 // octet deviceProtocol; | 30 // octet deviceProtocol; |
| 28 // unsigned short vendorId; | 31 // unsigned short vendorId; |
| 29 // unsigned short productId; | 32 // unsigned short productId; |
| 30 // octet deviceVersionMajor; | 33 // octet deviceVersionMajor; |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 69 // The global mojo object contains the Mojo JS binding modules loaded during | 72 // The global mojo object contains the Mojo JS binding modules loaded during |
| 70 // initialization. | 73 // initialization. |
| 71 let mojo = null; | 74 let mojo = null; |
| 72 | 75 |
| 73 // These variables are logically members of the USBTest class but are defined | 76 // These variables are logically members of the USBTest class but are defined |
| 74 // here to hide them from being visible as fields of navigator.usb.test. | 77 // here to hide them from being visible as fields of navigator.usb.test. |
| 75 let g_initializePromise = null; | 78 let g_initializePromise = null; |
| 76 let g_chooserService = null; | 79 let g_chooserService = null; |
| 77 let g_deviceManager = null; | 80 let g_deviceManager = null; |
| 78 let g_closeListener = null; | 81 let g_closeListener = null; |
| 82 let g_nextGuid = 0; |
| 79 | 83 |
| 80 function fakeDeviceInitToDeviceInfo(guid, init) { | 84 function fakeDeviceInitToDeviceInfo(guid, init) { |
| 81 let deviceInfo = { | 85 let deviceInfo = { |
| 82 guid: guid + "", | 86 guid: guid + "", |
| 83 usb_version_major: init.usbVersionMajor, | 87 usb_version_major: init.usbVersionMajor, |
| 84 usb_version_minor: init.usbVersionMinor, | 88 usb_version_minor: init.usbVersionMinor, |
| 85 usb_version_subminor: init.usbVersionSubminor, | 89 usb_version_subminor: init.usbVersionSubminor, |
| 86 class_code: init.deviceClass, | 90 class_code: init.deviceClass, |
| 87 subclass_code: init.deviceSubclass, | 91 subclass_code: init.deviceSubclass, |
| 88 protocol_code: init.deviceProtocol, | 92 protocol_code: init.deviceProtocol, |
| (...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 340 } | 344 } |
| 341 return Promise.resolve({ packets: packets }); | 345 return Promise.resolve({ packets: packets }); |
| 342 } | 346 } |
| 343 } | 347 } |
| 344 | 348 |
| 345 class FakeDeviceManager { | 349 class FakeDeviceManager { |
| 346 constructor() { | 350 constructor() { |
| 347 this.bindingSet_ = | 351 this.bindingSet_ = |
| 348 new mojo.bindings.BindingSet(mojo.deviceManager.DeviceManager); | 352 new mojo.bindings.BindingSet(mojo.deviceManager.DeviceManager); |
| 349 this.devices_ = new Map(); | 353 this.devices_ = new Map(); |
| 354 this.devicesByGuid_ = new Map(); |
| 350 this.client_ = null; | 355 this.client_ = null; |
| 356 this.nextGuid_ = 0; |
| 351 } | 357 } |
| 352 | 358 |
| 353 addBinding(handle) { | 359 addBinding(handle) { |
| 354 this.bindingSet_.addBinding(this, handle); | 360 this.bindingSet_.addBinding(this, handle); |
| 355 } | 361 } |
| 356 | 362 |
| 357 addDevice(info) { | 363 addDevice(fakeDevice, info) { |
| 358 let device = { | 364 let device = { |
| 359 guid: this.nextGuid_++ + "", | 365 fakeDevice: fakeDevice, |
| 366 guid: (this.nextGuid_++).toString(), |
| 360 info: info, | 367 info: info, |
| 361 bindingArray: [] | 368 bindingArray: [] |
| 362 }; | 369 }; |
| 363 this.devices_.set(device.guid, device); | 370 this.devices_.set(fakeDevice, device); |
| 371 this.devicesByGuid_.set(device.guid, device); |
| 364 if (this.client_) | 372 if (this.client_) |
| 365 this.client_.onDeviceAdded(fakeDeviceInitToDeviceInfo(device.guid, info)); | 373 this.client_.onDeviceAdded(fakeDeviceInitToDeviceInfo(device.guid, info)); |
| 366 return device.guid; | |
| 367 } | 374 } |
| 368 | 375 |
| 369 removeDevice(guid) { | 376 removeDevice(fakeDevice) { |
| 370 let device = this.devices_.get(guid); | 377 let device = this.devices_.get(fakeDevice); |
| 378 if (!device) |
| 379 throw new Error('Cannot remove unknown device.'); |
| 380 |
| 371 for (var binding of device.bindingArray) | 381 for (var binding of device.bindingArray) |
| 372 binding.close(); | 382 binding.close(); |
| 373 this.devices_.delete(guid); | 383 this.devices_.delete(device.fakeDevice); |
| 384 this.devicesByGuid_.delete(device.guid); |
| 374 if (this.client_) { | 385 if (this.client_) { |
| 375 this.client_.onDeviceRemoved( | 386 this.client_.onDeviceRemoved( |
| 376 fakeDeviceInitToDeviceInfo(guid, device.info)); | 387 fakeDeviceInitToDeviceInfo(device.guid, device.info)); |
| 377 } | 388 } |
| 378 } | 389 } |
| 379 | 390 |
| 380 removeAllDevices() { | 391 removeAllDevices() { |
| 381 this.devices_.forEach(device => { | 392 this.devices_.forEach(device => { |
| 382 for (var binding of device.bindingArray) | 393 for (var binding of device.bindingArray) |
| 383 binding.close(); | 394 binding.close(); |
| 384 this.client_.onDeviceRemoved( | 395 this.client_.onDeviceRemoved( |
| 385 fakeDeviceInitToDeviceInfo(device.guid, device.info)); | 396 fakeDeviceInitToDeviceInfo(device.guid, device.info)); |
| 386 }); | 397 }); |
| 387 this.devices_.clear(); | 398 this.devices_.clear(); |
| 399 this.devicesByGuid_.clear(); |
| 388 } | 400 } |
| 389 | 401 |
| 390 getDevices(options) { | 402 getDevices(options) { |
| 391 let devices = []; | 403 let devices = []; |
| 392 this.devices_.forEach(device => { | 404 this.devices_.forEach(device => { |
| 393 devices.push(fakeDeviceInitToDeviceInfo(device.guid, device.info)); | 405 devices.push(fakeDeviceInitToDeviceInfo(device.guid, device.info)); |
| 394 }); | 406 }); |
| 395 return Promise.resolve({ results: devices }); | 407 return Promise.resolve({ results: devices }); |
| 396 } | 408 } |
| 397 | 409 |
| 398 getDevice(guid, request) { | 410 getDevice(guid, request) { |
| 399 let device = this.devices_.get(guid); | 411 let device = this.devicesByGuid_.get(guid); |
| 400 if (device) { | 412 if (device) { |
| 401 let binding = new mojo.bindings.Binding( | 413 let binding = new mojo.bindings.Binding( |
| 402 mojo.device.Device, new FakeDevice(device.info), request); | 414 mojo.device.Device, new FakeDevice(device.info), request); |
| 403 binding.setConnectionErrorHandler(() => { | 415 binding.setConnectionErrorHandler(() => { |
| 404 if (g_closeListener) | 416 if (g_closeListener) |
| 405 g_closeListener(guid); | 417 g_closeListener(device.fakeDevice); |
| 406 }); | 418 }); |
| 407 device.bindingArray.push(binding); | 419 device.bindingArray.push(binding); |
| 408 } else { | 420 } else { |
| 409 request.close(); | 421 request.close(); |
| 410 } | 422 } |
| 411 } | 423 } |
| 412 | 424 |
| 413 setClient(client) { | 425 setClient(client) { |
| 414 this.client_ = client; | 426 this.client_ = client; |
| 415 } | 427 } |
| 416 } | 428 } |
| 417 | 429 |
| 418 class FakeChooserService { | 430 class FakeChooserService { |
| 419 constructor() { | 431 constructor() { |
| 420 this.bindingSet_ = new mojo.bindings.BindingSet( | 432 this.bindingSet_ = new mojo.bindings.BindingSet( |
| 421 mojo.chooserService.ChooserService); | 433 mojo.chooserService.ChooserService); |
| 422 this.chosenDevice_ = null; | 434 this.chosenDevice_ = null; |
| 423 this.lastFilters_ = null; | 435 this.lastFilters_ = null; |
| 424 } | 436 } |
| 425 | 437 |
| 426 addBinding(handle) { | 438 addBinding(handle) { |
| 427 this.bindingSet_.addBinding(this, handle); | 439 this.bindingSet_.addBinding(this, handle); |
| 428 } | 440 } |
| 429 | 441 |
| 430 setChosenDevice(guid) { | 442 setChosenDevice(fakeDevice) { |
| 431 this.chosenDeviceGuid_ = guid; | 443 this.chosenDevice_ = fakeDevice; |
| 432 } | 444 } |
| 433 | 445 |
| 434 getPermission(deviceFilters) { | 446 getPermission(deviceFilters) { |
| 435 this.lastFilters_ = convertMojoDeviceFilters(deviceFilters); | 447 this.lastFilters_ = convertMojoDeviceFilters(deviceFilters); |
| 436 let device = g_deviceManager.devices_.get(this.chosenDeviceGuid_); | 448 let device = g_deviceManager.devices_.get(this.chosenDevice_); |
| 437 if (device) { | 449 if (device) { |
| 438 return Promise.resolve({ | 450 return Promise.resolve({ |
| 439 result: fakeDeviceInitToDeviceInfo(device.guid, device.info) | 451 result: fakeDeviceInitToDeviceInfo(device.guid, device.info) |
| 440 }); | 452 }); |
| 441 } else { | 453 } else { |
| 442 return Promise.resolve({ result: null }); | 454 return Promise.resolve({ result: null }); |
| 443 } | 455 } |
| 444 } | 456 } |
| 445 } | 457 } |
| 446 | 458 |
| 459 // Unlike FakeDevice this class is exported to callers of USBTest.addFakeDevice. |
| 460 class FakeUSBDevice { |
| 461 disconnect() { |
| 462 setTimeout(() => g_deviceManager.removeDevice(this), 0); |
| 463 } |
| 464 } |
| 465 |
| 447 class USBTest { | 466 class USBTest { |
| 448 constructor() {} | 467 constructor() {} |
| 449 | 468 |
| 450 initialize() { | 469 initialize() { |
| 451 if (!g_initializePromise) { | 470 if (!g_initializePromise) { |
| 452 g_initializePromise = new Promise(resolve => { | 471 g_initializePromise = new Promise(resolve => { |
| 453 window.define = gin.define; // Mojo modules expect this. | 472 window.define = gin.define; // Mojo modules expect this. |
| 454 | 473 |
| 455 gin.define('WebUSB Test Mocks', [ | 474 gin.define('WebUSB Test Mocks', [ |
| 456 'content/public/renderer/frame_interfaces', | 475 'content/public/renderer/frame_interfaces', |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 515 handle => g_chooserService.addBinding(handle)); | 534 handle => g_chooserService.addBinding(handle)); |
| 516 resolve(); | 535 resolve(); |
| 517 }); | 536 }); |
| 518 }); | 537 }); |
| 519 } | 538 } |
| 520 | 539 |
| 521 addFakeDevice(deviceInit) { | 540 addFakeDevice(deviceInit) { |
| 522 if (!g_deviceManager) | 541 if (!g_deviceManager) |
| 523 throw new Error('Call initialize() before addFakeDevice().'); | 542 throw new Error('Call initialize() before addFakeDevice().'); |
| 524 | 543 |
| 525 return g_deviceManager.addDevice(deviceInit); | 544 // |addDevice| and |removeDevice| are called in a setTimeout callback so |
| 526 } | 545 // that tests do not rely on the device being immediately available which |
| 527 | 546 // may not be true for all implementations of this test API. |
| 528 removeFakeDevice(guid) { | 547 let fakeDevice = new FakeUSBDevice(); |
| 529 if (!g_deviceManager) | 548 setTimeout(() => g_deviceManager.addDevice(fakeDevice, deviceInit), 0); |
| 530 throw new Error('Call initialize() before removeFakeDevice().'); | 549 return fakeDevice; |
| 531 | |
| 532 return g_deviceManager.removeDevice(guid); | |
| 533 } | 550 } |
| 534 | 551 |
| 535 set ondeviceclose(func) { | 552 set ondeviceclose(func) { |
| 536 g_closeListener = func; | 553 g_closeListener = func; |
| 537 } | 554 } |
| 538 | 555 |
| 539 set chosenDevice(guid) { | 556 set chosenDevice(fakeDevice) { |
| 540 if (!g_chooserService) | 557 if (!g_chooserService) |
| 541 throw new Error('Call initialize() before setting chosenDevice.'); | 558 throw new Error('Call initialize() before setting chosenDevice.'); |
| 542 | 559 |
| 543 g_chooserService.setChosenDevice(guid); | 560 g_chooserService.setChosenDevice(fakeDevice); |
| 544 } | 561 } |
| 545 | 562 |
| 546 get lastFilters() { | 563 get lastFilters() { |
| 547 if (!g_chooserService) | 564 if (!g_chooserService) |
| 548 throw new Error('Call initialize() before getting lastFilters.'); | 565 throw new Error('Call initialize() before getting lastFilters.'); |
| 549 | 566 |
| 550 return g_chooserService.lastFilters_; | 567 return g_chooserService.lastFilters_; |
| 551 } | 568 } |
| 552 | 569 |
| 553 reset() { | 570 reset() { |
| 554 if (!g_deviceManager || !g_chooserService) | 571 if (!g_deviceManager || !g_chooserService) |
| 555 throw new Error('Call initialize() before reset().'); | 572 throw new Error('Call initialize() before reset().'); |
| 556 | 573 |
| 557 g_deviceManager.removeAllDevices(); | 574 g_deviceManager.removeAllDevices(); |
| 558 g_chooserService.setChosenDevice(null); | 575 g_chooserService.setChosenDevice(null); |
| 559 g_closeListener = null; | 576 g_closeListener = null; |
| 560 } | 577 } |
| 561 } | 578 } |
| 562 | 579 |
| 563 navigator.usb.test = new USBTest(); | 580 navigator.usb.test = new USBTest(); |
| 564 | 581 |
| 565 })(); | 582 })(); |
| OLD | NEW |