blob: 9483d948ac5709ed1c453796c33f5216a3491476 [file] [log] [blame]
// 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 "modules/webmidi/MIDIAccessInitializer.h"
#include "bindings/core/v8/ScriptPromise.h"
#include "bindings/core/v8/ScriptPromiseResolver.h"
#include "core/dom/DOMException.h"
#include "core/dom/Document.h"
#include "core/dom/ExceptionCode.h"
#include "core/frame/Navigator.h"
#include "modules/webmidi/MIDIAccess.h"
#include "modules/webmidi/MIDIController.h"
#include "modules/webmidi/MIDIOptions.h"
#include "modules/webmidi/MIDIPort.h"
namespace blink {
using PortState = WebMIDIAccessorClient::MIDIPortState;
MIDIAccessInitializer::MIDIAccessInitializer(ScriptState* scriptState, const MIDIOptions& options)
: ScriptPromiseResolver(scriptState)
, m_options(options)
, m_hasBeenDisposed(false)
, m_permissionResolved(false)
{
}
MIDIAccessInitializer::~MIDIAccessInitializer()
{
dispose();
}
void MIDIAccessInitializer::contextDestroyed()
{
dispose();
LifecycleObserver::contextDestroyed();
}
void MIDIAccessInitializer::dispose()
{
if (m_hasBeenDisposed)
return;
if (!executionContext())
return;
if (!m_permissionResolved) {
Document* document = toDocument(executionContext());
ASSERT(document);
if (MIDIController* controller = MIDIController::from(document->frame()))
controller->cancelPermissionRequest(this);
m_permissionResolved = true;
}
m_hasBeenDisposed = true;
}
ScriptPromise MIDIAccessInitializer::start()
{
ScriptPromise promise = this->promise();
m_accessor = MIDIAccessor::create(this);
Document* document = toDocument(executionContext());
ASSERT(document);
if (MIDIController* controller = MIDIController::from(document->frame()))
controller->requestPermission(this, m_options);
else
reject(DOMException::create(SecurityError));
return promise;
}
void MIDIAccessInitializer::didAddInputPort(const String& id, const String& manufacturer, const String& name, const String& version, PortState state)
{
ASSERT(m_accessor);
m_portDescriptors.append(PortDescriptor(id, manufacturer, name, MIDIPort::TypeInput, version, state));
}
void MIDIAccessInitializer::didAddOutputPort(const String& id, const String& manufacturer, const String& name, const String& version, PortState state)
{
ASSERT(m_accessor);
m_portDescriptors.append(PortDescriptor(id, manufacturer, name, MIDIPort::TypeOutput, version, state));
}
void MIDIAccessInitializer::didSetInputPortState(unsigned portIndex, PortState state)
{
// didSetInputPortState() is not allowed to call before didStartSession()
// is called. Once didStartSession() is called, MIDIAccessorClient methods
// are delegated to MIDIAccess. See constructor of MIDIAccess.
ASSERT_NOT_REACHED();
}
void MIDIAccessInitializer::didSetOutputPortState(unsigned portIndex, PortState state)
{
// See comments on didSetInputPortState().
ASSERT_NOT_REACHED();
}
void MIDIAccessInitializer::didStartSession(bool success, const String& error, const String& message)
{
ASSERT(m_accessor);
if (success) {
resolve(MIDIAccess::create(m_accessor.release(), m_options.hasSysex(), m_portDescriptors, executionContext()));
} else {
// The spec says the name is one of
// - SecurityError
// - AbortError
// - InvalidStateError
// - NotSupportedError
// TODO(toyoshim): Do not rely on |error| string. Instead an enum
// representing an ExceptionCode should be defined and deliverred.
ExceptionCode ec = InvalidStateError;
if (error == DOMException::getErrorName(SecurityError)) {
ec = SecurityError;
} else if (error == DOMException::getErrorName(AbortError)) {
ec = AbortError;
} else if (error == DOMException::getErrorName(InvalidStateError)) {
ec = InvalidStateError;
} else if (error == DOMException::getErrorName(NotSupportedError)) {
ec = NotSupportedError;
}
reject(DOMException::create(ec, message));
}
}
void MIDIAccessInitializer::resolvePermission(bool allowed)
{
m_permissionResolved = true;
if (allowed)
m_accessor->startSession();
else
reject(DOMException::create(SecurityError));
}
SecurityOrigin* MIDIAccessInitializer::securityOrigin() const
{
return executionContext()->securityOrigin();
}
ExecutionContext* MIDIAccessInitializer::executionContext() const
{
return scriptState()->executionContext();
}
} // namespace blink