| // 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 "content/shell/test_runner/mock_web_midi_accessor.h" |
| |
| #include "base/bind.h" |
| #include "base/bind_helpers.h" |
| #include "base/macros.h" |
| #include "base/strings/stringprintf.h" |
| #include "content/shell/test_runner/test_interfaces.h" |
| #include "content/shell/test_runner/test_runner.h" |
| #include "content/shell/test_runner/web_test_delegate.h" |
| #include "content/shell/test_runner/web_test_runner.h" |
| #include "third_party/blink/public/platform/modules/webmidi/web_midi_accessor_client.h" |
| #include "third_party/blink/public/platform/web_string.h" |
| |
| using midi::mojom::PortState; |
| using midi::mojom::Result; |
| |
| namespace test_runner { |
| |
| namespace { |
| |
| constexpr unsigned char kSysexHeader[] = {0xf0, 0x00, 0x02, 0x0d, 0x7f}; |
| constexpr unsigned char kSysexFooter = 0xf7; |
| constexpr size_t kSysexMinimumLength = |
| arraysize(kSysexHeader) + sizeof(kSysexFooter) + 1; |
| |
| bool isSysexForTesting(const unsigned char* data, size_t length) { |
| // It should have five bytes header, one byte footer, and at least one byte |
| // payload. |
| if (length < kSysexMinimumLength) |
| return false; |
| if (memcmp(data, kSysexHeader, arraysize(kSysexHeader))) |
| return false; |
| return data[length - 1] == kSysexFooter; |
| } |
| |
| } // namespace |
| |
| MockWebMIDIAccessor::MockWebMIDIAccessor(blink::WebMIDIAccessorClient* client, |
| TestInterfaces* interfaces) |
| : client_(client), |
| interfaces_(interfaces), |
| next_input_port_index_(0), |
| next_output_port_index_(0), |
| weak_factory_(this) {} |
| |
| MockWebMIDIAccessor::~MockWebMIDIAccessor() {} |
| |
| void MockWebMIDIAccessor::StartSession() { |
| // Add a mock input and output port. |
| addInputPort(PortState::CONNECTED); |
| addOutputPort(PortState::CONNECTED); |
| interfaces_->GetDelegate()->PostTask(base::BindOnce( |
| &MockWebMIDIAccessor::reportStartedSession, weak_factory_.GetWeakPtr(), |
| interfaces_->GetTestRunner()->midiAccessorResult())); |
| } |
| |
| void MockWebMIDIAccessor::RunDidReceiveMIDIData(unsigned port_index, |
| std::vector<unsigned char> data, |
| base::TimeTicks timestamp) { |
| client_->DidReceiveMIDIData(port_index, data.data(), data.size(), timestamp); |
| } |
| |
| void MockWebMIDIAccessor::SendMIDIData(unsigned port_index, |
| const unsigned char* data, |
| size_t length, |
| base::TimeTicks timestamp) { |
| // Emulate a loopback device for testing. Make sure if an input port that has |
| // the same index exists. |
| if (port_index < next_input_port_index_) { |
| std::vector<unsigned char> copied_data(data, data + length); |
| interfaces_->GetDelegate()->PostDelayedTask( |
| base::BindOnce(&MockWebMIDIAccessor::RunDidReceiveMIDIData, |
| weak_factory_.GetWeakPtr(), port_index, |
| std::move(copied_data), timestamp), |
| std::max(base::TimeDelta(), timestamp - base::TimeTicks::Now())); |
| } |
| |
| // Handle special sysex messages for testing. |
| // A special sequence is [0xf0, 0x00, 0x02, 0x0d, 0x7f, <function>, 0xf7]. |
| // <function> should be one of following sequences. |
| // - [0x00, 0x00]: Add an input port as connected. |
| // - [0x00, 0x01]: Add an output port as connected. |
| // - [0x00, 0x02]: Add an input port as opened. |
| // - [0x00, 0x03]: Add an output port as opened. |
| if (!isSysexForTesting(data, length)) |
| return; |
| size_t offset = arraysize(kSysexHeader); |
| if (data[offset++] != 0) |
| return; |
| switch (data[offset]) { |
| case 0: |
| addInputPort(PortState::CONNECTED); |
| break; |
| case 1: |
| addOutputPort(PortState::CONNECTED); |
| break; |
| case 2: |
| addInputPort(PortState::OPENED); |
| break; |
| case 3: |
| addOutputPort(PortState::OPENED); |
| break; |
| default: |
| break; |
| } |
| } |
| |
| void MockWebMIDIAccessor::addInputPort(PortState state) { |
| std::string id = |
| base::StringPrintf("MockInputID-%d", next_input_port_index_++); |
| client_->DidAddInputPort(blink::WebString::FromUTF8(id), |
| "MockInputManufacturer", "MockInputName", |
| "MockInputVersion", state); |
| } |
| |
| void MockWebMIDIAccessor::addOutputPort(PortState state) { |
| std::string id = |
| base::StringPrintf("MockOutputID-%d", next_output_port_index_++); |
| client_->DidAddOutputPort(blink::WebString::FromUTF8(id), |
| "MockOutputManufacturer", "MockOutputName", |
| "MockOutputVersion", state); |
| } |
| |
| void MockWebMIDIAccessor::reportStartedSession(Result result) { |
| client_->DidStartSession(result); |
| } |
| |
| } // namespace test_runner |