Bug 1743462 - Add a log module for the Web MIDI API. r=gsvelto

Differential Revision: https://phabricator.services.mozilla.com/D132387
This commit is contained in:
Paul Adenot 2022-01-18 09:54:42 +00:00
parent 23b5e2dd23
commit 82ee6c1e84
7 changed files with 125 additions and 1 deletions

View File

@ -24,6 +24,7 @@
#include "nsContentPermissionHelper.h"
#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, MOZ_COUNT_DTOR
#include "ipc/IPCMessageUtils.h"
#include "MIDILog.h"
namespace mozilla::dom {
@ -69,6 +70,7 @@ MIDIAccess::MIDIAccess(nsPIDOMWindowInner* aWindow, bool aSysexEnabled,
MIDIAccess::~MIDIAccess() { Shutdown(); }
void MIDIAccess::Shutdown() {
LOG("MIDIAccess::Shutdown");
if (mHasShutdown) {
return;
}
@ -96,6 +98,7 @@ void MIDIAccess::FireConnectionEvent(MIDIPort* aPort) {
}
// Check to make sure Has()/Delete() calls haven't failed.
if (NS_WARN_IF(rv.Failed())) {
LOG("Inconsistency during FireConnectionEvent");
return;
}
} else {
@ -106,22 +109,26 @@ void MIDIAccess::FireConnectionEvent(MIDIPort* aPort) {
if (aPort->Type() == MIDIPortType::Input &&
!MIDIInputMap_Binding::MaplikeHelpers::Has(mInputMap, id, rv)) {
if (NS_WARN_IF(rv.Failed())) {
LOG("Input port not found");
return;
}
MIDIInputMap_Binding::MaplikeHelpers::Set(
mInputMap, id, *(static_cast<MIDIInput*>(aPort)), rv);
if (NS_WARN_IF(rv.Failed())) {
LOG("Map Set failed for input port");
return;
}
} else if (aPort->Type() == MIDIPortType::Output &&
!MIDIOutputMap_Binding::MaplikeHelpers::Has(mOutputMap, id,
rv)) {
if (NS_WARN_IF(rv.Failed())) {
LOG("Output port not found");
return;
}
MIDIOutputMap_Binding::MaplikeHelpers::Set(
mOutputMap, id, *(static_cast<MIDIOutput*>(aPort)), rv);
if (NS_WARN_IF(rv.Failed())) {
LOG("Map set failed for output port");
return;
}
}
@ -145,12 +152,14 @@ void MIDIAccess::MaybeCreateMIDIPort(const MIDIPortInfo& aInfo,
}
port = MIDIInput::Create(GetOwner(), this, aInfo, mSysexEnabled);
if (NS_WARN_IF(!port)) {
LOG("Couldn't create input port");
aRv.Throw(NS_ERROR_FAILURE);
return;
}
MIDIInputMap_Binding::MaplikeHelpers::Set(
mInputMap, id, *(static_cast<MIDIInput*>(port.get())), aRv);
if (NS_WARN_IF(aRv.Failed())) {
LOG("Coudld't set input port in map");
return;
}
} else if (type == MIDIPortType::Output) {
@ -162,12 +171,14 @@ void MIDIAccess::MaybeCreateMIDIPort(const MIDIPortInfo& aInfo,
}
port = MIDIOutput::Create(GetOwner(), this, aInfo, mSysexEnabled);
if (NS_WARN_IF(!port)) {
LOG("Couldn't create output port");
aRv.Throw(NS_ERROR_FAILURE);
return;
}
MIDIOutputMap_Binding::MaplikeHelpers::Set(
mOutputMap, id, *(static_cast<MIDIOutput*>(port.get())), aRv);
if (NS_WARN_IF(aRv.Failed())) {
LOG("Coudld't set output port in map");
return;
}
} else {
@ -191,6 +202,7 @@ void MIDIAccess::MaybeCreateMIDIPort(const MIDIPortInfo& aInfo,
// received, that will be handled by the MIDIPort object itself, and it will
// request removal from MIDIAccess's maps.
void MIDIAccess::Notify(const MIDIPortList& aEvent) {
LOG("MIDIAcess::Notify");
for (const auto& port : aEvent.ports()) {
// Something went very wrong. Warn and return.
ErrorResult rv;

View File

@ -12,6 +12,8 @@
#include "mozilla/dom/MIDIMessageEventBinding.h"
#include "nsDOMNavigationTiming.h"
#include "MIDILog.h"
namespace mozilla::dom {
MIDIInput::MIDIInput(nsPIDOMWindowInner* aWindow, MIDIAccess* aMIDIAccessParent)
@ -69,6 +71,7 @@ void MIDIInput::EventListenerAdded(nsAtom* aType) {
// setting the midimessage event handler but Chrome does it even when
// adding event listeners hence this.
if (mPort->ConnectionState() != MIDIPortConnectionState::Open) {
LOG("onmidimessage event listener added, sending implicit Open");
mPort->SendOpen();
}
}

54
dom/midi/MIDILog.cpp Normal file
View File

@ -0,0 +1,54 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "MIDILog.h"
#include "mozilla/dom/MIDITypes.h"
#include "mozilla/dom/MIDIPortBinding.h"
mozilla::LazyLogModule gWebMIDILog("WebMIDI");
void LogMIDIMessage(nsTArray<mozilla::dom::MIDIMessage>& aMessages,
const nsAString& aPortId,
mozilla::dom::MIDIPortType aDirection) {
if (MOZ_LOG_TEST(gWebMIDILog, mozilla::LogLevel::Debug)) {
if (MOZ_LOG_TEST(gWebMIDILog, mozilla::LogLevel::Verbose)) {
for (auto& msg : aMessages) {
uint32_t byteCount = msg.data().Length();
nsAutoCString logMessage;
// Log long messages inline with the timestamp and the length, log
// longer messages a bit like xxd
logMessage.AppendPrintf(
"%s %s length=%u", NS_ConvertUTF16toUTF8(aPortId).get(),
aDirection == mozilla::dom::MIDIPortType::Input ? "->" : "<-",
byteCount);
if (byteCount <= 3) {
logMessage.AppendPrintf(" [");
// Regular messages
for (uint32_t i = 0; i < byteCount - 1; i++) {
logMessage.AppendPrintf("%x ", msg.data()[i]);
}
logMessage.AppendPrintf("%x]", msg.data()[byteCount - 1]);
} else {
// Longer messages
for (uint32_t i = 0; i < byteCount; i++) {
if (!(i % 8)) {
logMessage.AppendPrintf("\n%08u:\t", i);
}
logMessage.AppendPrintf("%x ", msg.data()[i]);
}
}
MOZ_LOG(gWebMIDILog, mozilla::LogLevel::Verbose,
("%s", logMessage.get()));
}
return;
}
for (auto& msg : aMessages) {
LOG("%s %s %zu bytes", NS_ConvertUTF16toUTF8(aPortId).get(),
aDirection == mozilla::dom::MIDIPortType::Input ? "->" : "<-",
msg.data().Length());
}
}
}

27
dom/midi/MIDILog.h Normal file
View File

@ -0,0 +1,27 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_MIDILog_h
#define mozilla_dom_MIDILog_h
#include <mozilla/Logging.h>
#include <nsTArray.h>
#include <nsStringFwd.h>
namespace mozilla::dom {
class MIDIMessage;
enum class MIDIPortType : uint8_t;
} // namespace mozilla::dom
extern mozilla::LazyLogModule gWebMIDILog;
#define LOG(...) MOZ_LOG(gWebMIDILog, mozilla::LogLevel::Debug, (__VA_ARGS__));
#define LOGV(x, ...) \
MOZ_LOG(gWebMIDILog, mozilla::LogLevel::Verbose, (__VA_ARGS__));
void LogMIDIMessage(nsTArray<mozilla::dom::MIDIMessage>& aMessage,
const nsAString& aPortId,
mozilla::dom::MIDIPortType aDirection);
#endif // mozilla_dom_MIDILog_h

View File

@ -15,6 +15,7 @@
#include "mozilla/dom/Promise.h"
#include "mozilla/Unused.h"
#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, MOZ_COUNT_DTOR
#include "MIDILog.h"
using namespace mozilla::ipc;
@ -72,13 +73,21 @@ bool MIDIPort::Initialize(const MIDIPortInfo& aPortInfo, bool aSysexEnabled) {
return false;
}
mPort = port;
LOG("MIDIPort::Initialize (%s, %s)",
NS_ConvertUTF16toUTF8(mPort->Name()).get(),
MIDIPortTypeValues::strings[uint32_t(mPort->Type())].value);
// Make sure to increase the ref count for the port, so it can be cleaned up
// by the IPC manager.
mPort->SetActorAlive();
return true;
}
void MIDIPort::UnsetIPCPort() { mPort = nullptr; }
void MIDIPort::UnsetIPCPort() {
LOG("MIDIPort::UnsetIPCPort (%s, %s)",
NS_ConvertUTF16toUTF8(mPort->Name()).get(),
MIDIPortTypeValues::strings[uint32_t(mPort->Type())].value);
mPort = nullptr;
}
void MIDIPort::GetId(nsString& aRetVal) const {
MOZ_ASSERT(mPort);
@ -121,6 +130,7 @@ bool MIDIPort::SysexEnabled() const {
}
already_AddRefed<Promise> MIDIPort::Open() {
LOG("MIDIPort::Open");
MOZ_ASSERT(mPort);
RefPtr<Promise> p;
if (mOpeningPromise) {
@ -139,6 +149,7 @@ already_AddRefed<Promise> MIDIPort::Open() {
}
already_AddRefed<Promise> MIDIPort::Close() {
LOG("MIDIPort::Close");
MOZ_ASSERT(mPort);
RefPtr<Promise> p;
if (mClosingPromise) {
@ -157,6 +168,7 @@ already_AddRefed<Promise> MIDIPort::Close() {
}
void MIDIPort::Notify(const void_t& aVoid) {
LOG("MIDIPort::notify MIDIAccess shutting down, dropping reference.");
// If we're getting notified, it means the MIDIAccess parent object is dead.
// Nullify our copy.
mMIDIAccessParent = nullptr;

View File

@ -14,6 +14,8 @@
#include "mozilla/ipc/BackgroundParent.h"
#include "mozilla/Unused.h"
#include "nsIThread.h"
#include "mozilla/Logging.h"
#include "MIDILog.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -54,6 +56,7 @@ midirMIDIPlatformService::midirMIDIPlatformService()
}
midirMIDIPlatformService::~midirMIDIPlatformService() {
LOG("midir_impl_shutdown");
midir_impl_shutdown(mImplementation);
StaticMutexAutoLock lock(gBackgroundThreadMutex);
gBackgroundThread = nullptr;
@ -78,6 +81,8 @@ void midirMIDIPlatformService::Init() {
mIsInitialized = true;
midir_impl_enum_ports(mImplementation, AddPort);
MIDIPlatformService::Get()->SendPortList();
} else {
LOG("midir_impl_init failure");
}
}
@ -98,6 +103,8 @@ void midirMIDIPlatformService::CheckAndReceive(const nsString* aId,
nsTArray<MIDIMessage> messages;
messages.AppendElement(message);
LogMIDIMessage(messages, *aId, MIDIPortType::Input);
nsCOMPtr<nsIRunnable> r(new ReceiveRunnable(*aId, messages));
StaticMutexAutoLock lock(gBackgroundThreadMutex);
if (gBackgroundThread) {
@ -112,10 +119,14 @@ void midirMIDIPlatformService::Open(MIDIPortParent* aPort) {
if (midir_impl_open_port(mImplementation, &id,
reinterpret_cast<GeckoTimeStamp*>(&openTimeStamp),
CheckAndReceive)) {
LOG("MIDI port open: %s at t=%lf", NS_ConvertUTF16toUTF8(id).get(),
(openTimeStamp - TimeStamp::ProcessCreation()).ToSeconds());
nsCOMPtr<nsIRunnable> r(new SetStatusRunnable(
aPort->MIDIPortInterface::Id(), aPort->DeviceState(),
MIDIPortConnectionState::Open));
NS_DispatchToCurrentThread(r);
} else {
LOG("MIDI port open: %s", NS_ConvertUTF16toUTF8(id).get());
}
}
@ -124,6 +135,7 @@ void midirMIDIPlatformService::Stop() {
}
void midirMIDIPlatformService::ScheduleSend(const nsAString& aPortId) {
LOG("MIDI port schedule open %s", NS_ConvertUTF16toUTF8(aPortId).get());
nsCOMPtr<nsIRunnable> r(new SendRunnable(aPortId));
StaticMutexAutoLock lock(gBackgroundThreadMutex);
if (gBackgroundThread) {
@ -134,6 +146,7 @@ void midirMIDIPlatformService::ScheduleSend(const nsAString& aPortId) {
void midirMIDIPlatformService::ScheduleClose(MIDIPortParent* aPort) {
MOZ_ASSERT(aPort);
nsString id = aPort->MIDIPortInterface::Id();
LOG("MIDI port schedule close %s", NS_ConvertUTF16toUTF8(id).get());
if (aPort->ConnectionState() == MIDIPortConnectionState::Open) {
midir_impl_close_port(mImplementation, &id);
nsCOMPtr<nsIRunnable> r(new SetStatusRunnable(
@ -144,8 +157,10 @@ void midirMIDIPlatformService::ScheduleClose(MIDIPortParent* aPort) {
}
void midirMIDIPlatformService::SendMessages(const nsAString& aPortId) {
LOG("MIDI port send message on %s", NS_ConvertUTF16toUTF8(aPortId).get());
nsTArray<MIDIMessage> messages;
GetMessages(aPortId, messages);
LogMIDIMessage(messages, aPortId, MIDIPortType::Output);
for (const auto& message : messages) {
midir_impl_send(mImplementation, &aPortId, &message.data());
}

View File

@ -36,6 +36,7 @@ UNIFIED_SOURCES += [
"MIDIAccessManager.cpp",
"MIDIInput.cpp",
"MIDIInputMap.cpp",
"MIDILog.cpp",
"MIDIManagerChild.cpp",
"MIDIManagerParent.cpp",
"MIDIMessageEvent.cpp",