Commit 5455496f authored by toyoshim@chromium.org's avatar toyoshim@chromium.org

Add sysexEnabled readonly attribute to MIDIAccess

To conform the latest W3C spec, add sysexEnabled attribute.
http://www.w3.org/TR/webmidi/#idl-def-MIDIAccess

MIDIAccess originally has a method sysExEnabled().
To avoid having two functions for the same operation, this change
renames it to sysexEnabled(). This change affects other caller
implementations.

To rename everything in blink, it modifies blink API.
So this change is also the first step of blink API change.

Here are a series of changes.
1. this change
2. https://codereview.chromium.org/210003002/
3. https://codereview.chromium.org/208423016/

BUG=349538
TEST=LayoutTests/webmidi

Review URL: https://codereview.chromium.org/208243014

git-svn-id: svn://svn.chromium.org/blink/trunk@169909 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 594133f9
......@@ -3,7 +3,7 @@ Test if sysex permission request is handled.
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
PASS testRunner.setMIDISysExPermission is defined.
PASS testRunner.setMIDISysexPermission is defined.
PASS navigator.requestMIDIAccess is defined.
PASS promise is defined.
PASS promise.then is defined.
......@@ -11,6 +11,9 @@ PASS sysex permission request is successfully rejected.
PASS promise is defined.
PASS promise.then is defined.
PASS sysex permission request is successfully accepted.
PASS access is defined.
PASS access.sysexEnabled is defined.
PASS access.sysexEnabled is true
PASS all permission request rests pass successfully.
PASS successfullyParsed is true
......
......@@ -8,7 +8,11 @@
description("Test if sysex permission request is handled.");
shouldBeDefined("testRunner.setMIDISysExPermission");
// FIXME: remove following workaround once testRunner in Chromium has a new interface.
if (!testRunner.setMIDISysexPermission)
testRunner.setMIDISysexPermission = testRunner.setMIDISysExPermission;
shouldBeDefined("testRunner.setMIDISysexPermission");
shouldBeDefined("navigator.requestMIDIAccess");
window.jsTestIsAsync = true;
......@@ -19,7 +23,7 @@ var finishSuccessfully = function () {
}
var rejectSysEx = function (next) {
testRunner.setMIDISysExPermission(false);
testRunner.setMIDISysexPermission(false);
promise = navigator.requestMIDIAccess({sysex: true});
shouldBeDefined("promise");
shouldBeDefined("promise.then");
......@@ -36,12 +40,16 @@ var rejectSysEx = function (next) {
}
var acceptSysEx = function (next) {
testRunner.setMIDISysExPermission(true);
testRunner.setMIDISysexPermission(true);
promise = navigator.requestMIDIAccess({sysex: true});
shouldBeDefined("promise");
shouldBeDefined("promise.then");
promise.then(function(access) {
promise.then(function(obtainedAccess) {
testPassed("sysex permission request is successfully accepted.");
access = obtainedAccess;
shouldBeDefined("access");
shouldBeDefined("access.sysexEnabled");
shouldBeTrue("access.sysexEnabled");
if (next)
next();
else
......
......@@ -6,6 +6,8 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
PASS requestMIDIAccess() succeeded with access [object MIDIAccess].
PASS access.inputs().length is 1
PASS access.outputs().length is 1
PASS access.sysexEnabled is defined.
PASS access.sysexEnabled is false
PASS input attributes are correct
PASS output attributes are correct
PASS a note on message is sent without timestamp
......
......@@ -18,6 +18,10 @@ function successCallback1(a) {
shouldBe("access.inputs().length", "1");
shouldBe("access.outputs().length", "1");
// Validate the values of the attributes on the access.
shouldBeDefined("access.sysexEnabled");
shouldBeFalse("access.sysexEnabled");
var inputs = access.inputs();
var outputs = access.outputs();
var input = inputs[0];
......
......@@ -3,7 +3,7 @@ Test if various kinds of MIDI messages can be validated.
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
PASS testRunner.setMIDISysExPermission is defined.
PASS testRunner.setMIDISysexPermission is defined.
PASS navigator.requestMIDIAccess is defined.
PASS output.send([0x00, 0x01]) threw exception TypeError: Failed to execute 'send' on 'MIDIOutput': Running status is not allowed at index 0 (0)..
PASS output.send([0xf7]) threw exception TypeError: Failed to execute 'send' on 'MIDIOutput': Unexpected end of system exclusive message at index 0 (247)..
......
......@@ -8,12 +8,16 @@
description("Test if various kinds of MIDI messages can be validated.");
shouldBeDefined("testRunner.setMIDISysExPermission");
// FIXME: remove following workaround once testRunner in Chromium has a new interface.
if (!testRunner.setMIDISysexPermission)
testRunner.setMIDISysexPermission = testRunner.setMIDISysExPermission;
shouldBeDefined("testRunner.setMIDISysexPermission");
shouldBeDefined("navigator.requestMIDIAccess");
window.jsTestIsAsync = true;
testRunner.setMIDISysExPermission(true);
testRunner.setMIDISysexPermission(true);
navigator.requestMIDIAccess({sysex: true}).then(function (a) {
output = a.outputs()[0];
......@@ -24,7 +28,7 @@ navigator.requestMIDIAccess({sysex: true}).then(function (a) {
// Running status is not allowed in Web MIDI API.
shouldThrow('output.send([0x00, 0x01])');
// Unexpected End of SysEx.
// Unexpected End of Sysex.
shouldThrow('output.send([0xf7])');
// Unexpected reserved status bytes.
......@@ -77,7 +81,7 @@ navigator.requestMIDIAccess({sysex: true}).then(function (a) {
// Valid messages with Real-Time messages.
output.send([0x90, 0xff, 0xff, 0x00, 0xff, 0x01, 0xff, 0x80, 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff]);
// SysEx messages.
// Sysex messages.
output.send([0xf0, 0x00, 0x01, 0x02, 0x03, 0xf7]);
output.send([0xf0, 0xf8, 0xf7, 0xff]);
shouldThrow('output.send([0xf0, 0x80, 0xf7])');
......
......@@ -85,7 +85,7 @@ MIDIAccess::MIDIAccess(const MIDIOptions& options, ExecutionContext* context)
, m_state(Requesting)
, m_weakPtrFactory(this)
, m_options(options)
, m_sysExEnabled(false)
, m_sysexEnabled(false)
, m_asyncResolveRunner(this, &MIDIAccess::resolveNow)
, m_asyncRejectRunner(this, &MIDIAccess::rejectNow)
{
......@@ -93,9 +93,9 @@ MIDIAccess::MIDIAccess(const MIDIOptions& options, ExecutionContext* context)
m_accessor = MIDIAccessor::create(this);
}
void MIDIAccess::setSysExEnabled(bool enable)
void MIDIAccess::setSysexEnabled(bool enable)
{
m_sysExEnabled = enable;
m_sysexEnabled = enable;
if (enable) {
m_accessor->startSession();
} else {
......@@ -192,7 +192,7 @@ void MIDIAccess::stop()
ASSERT(document);
MIDIController* controller = MIDIController::from(document->page());
ASSERT(controller);
controller->cancelSysExPermissionRequest(this);
controller->cancelSysexPermissionRequest(this);
}
m_state = Stopped;
}
......@@ -223,7 +223,7 @@ ScriptPromise MIDIAccess::startRequest()
ASSERT(document);
MIDIController* controller = MIDIController::from(document->page());
if (controller) {
controller->requestSysExPermission(this);
controller->requestSysexPermission(this);
} else {
reject(DOMError::create("SecurityError"));
}
......
......@@ -64,8 +64,8 @@ public:
DEFINE_ATTRIBUTE_EVENT_LISTENER(connect);
DEFINE_ATTRIBUTE_EVENT_LISTENER(disconnect);
void setSysExEnabled(bool);
bool sysExEnabled() const { return m_sysExEnabled; }
void setSysexEnabled(bool);
bool sysexEnabled() const { return m_sysexEnabled; }
// EventTarget
virtual const AtomicString& interfaceName() const OVERRIDE { return EventTargetNames::MIDIAccess; }
......@@ -115,7 +115,7 @@ private:
OwnPtr<MIDIAccessor> m_accessor;
OwnPtr<MIDIAccessResolver> m_resolver;
MIDIOptions m_options;
bool m_sysExEnabled;
bool m_sysexEnabled;
AsyncMethodRunner<MIDIAccess> m_asyncResolveRunner;
AsyncMethodRunner<MIDIAccess> m_asyncRejectRunner;
RefPtrWillBeMember<DOMError> m_error;
......
......@@ -35,6 +35,8 @@
sequence<MIDIInput> inputs();
sequence<MIDIOutput> outputs();
readonly attribute boolean sysexEnabled;
attribute EventHandler onconnect;
attribute EventHandler ondisconnect;
};
......@@ -40,8 +40,8 @@ class Page;
class MIDIClient {
public:
virtual void requestSysExPermission(PassRefPtrWillBeRawPtr<MIDIAccess>) = 0;
virtual void cancelSysExPermissionRequest(MIDIAccess*) = 0;
virtual void requestSysexPermission(PassRefPtrWillBeRawPtr<MIDIAccess>) = 0;
virtual void cancelSysexPermissionRequest(MIDIAccess*) = 0;
protected:
virtual ~MIDIClient() { }
......
......@@ -44,7 +44,7 @@ MIDIClientMock::~MIDIClientMock()
{
}
void MIDIClientMock::setSysExPermission(bool allowed)
void MIDIClientMock::setSysexPermission(bool allowed)
{
m_allowed = allowed;
}
......@@ -54,12 +54,12 @@ void MIDIClientMock::resetMock()
m_allowed = false;
}
void MIDIClientMock::requestSysExPermission(PassRefPtrWillBeRawPtr<MIDIAccess> access)
void MIDIClientMock::requestSysexPermission(PassRefPtrWillBeRawPtr<MIDIAccess> access)
{
access->setSysExEnabled(m_allowed);
access->setSysexEnabled(m_allowed);
}
void MIDIClientMock::cancelSysExPermissionRequest(MIDIAccess*)
void MIDIClientMock::cancelSysexPermissionRequest(MIDIAccess*)
{
}
......
......@@ -42,12 +42,12 @@ public:
MIDIClientMock();
virtual ~MIDIClientMock();
void setSysExPermission(bool);
void setSysexPermission(bool);
void resetMock();
// MIDIClient
virtual void requestSysExPermission(PassRefPtrWillBeRawPtr<MIDIAccess>) OVERRIDE;
virtual void cancelSysExPermissionRequest(MIDIAccess*) OVERRIDE;
virtual void requestSysexPermission(PassRefPtrWillBeRawPtr<MIDIAccess>) OVERRIDE;
virtual void cancelSysexPermissionRequest(MIDIAccess*) OVERRIDE;
private:
bool m_allowed;
......
......@@ -56,14 +56,14 @@ PassOwnPtr<MIDIController> MIDIController::create(MIDIClient* client)
return adoptPtr(new MIDIController(client));
}
void MIDIController::requestSysExPermission(PassRefPtrWillBeRawPtr<MIDIAccess> access)
void MIDIController::requestSysexPermission(PassRefPtrWillBeRawPtr<MIDIAccess> access)
{
m_client->requestSysExPermission(access);
m_client->requestSysexPermission(access);
}
void MIDIController::cancelSysExPermissionRequest(MIDIAccess* access)
void MIDIController::cancelSysexPermissionRequest(MIDIAccess* access)
{
m_client->cancelSysExPermissionRequest(access);
m_client->cancelSysexPermissionRequest(access);
}
void provideMIDITo(Page& page, MIDIClient* client)
......
......@@ -43,8 +43,8 @@ class MIDIController FINAL : public Supplement<Page> {
public:
virtual ~MIDIController();
void requestSysExPermission(PassRefPtrWillBeRawPtr<MIDIAccess>);
void cancelSysExPermissionRequest(MIDIAccess*);
void requestSysexPermission(PassRefPtrWillBeRawPtr<MIDIAccess>);
void cancelSysexPermissionRequest(MIDIAccess*);
static PassOwnPtr<MIDIController> create(MIDIClient*);
static const char* supplementName();
......
......@@ -57,10 +57,10 @@ void MIDIInput::didReceiveMIDIData(unsigned portIndex, const unsigned char* data
if (!length)
return;
// Drop SysEx message here when the client does not request it. Note that this is not a security check but an
// automatic filtering for clients that do not want SysEx message. Also note that SysEx message will never be sent
// unless the current process has an explicit permission to handle SysEx message.
if (data[0] == 0xf0 && !midiAccess()->sysExEnabled())
// Drop sysex message here when the client does not request it. Note that this is not a security check but an
// automatic filtering for clients that do not want sysex message. Also note that sysex message will never be sent
// unless the current process has an explicit permission to handle sysex message.
if (data[0] == 0xf0 && !midiAccess()->sysexEnabled())
return;
RefPtr<Uint8Array> array = Uint8Array::create(data, length);
dispatchEvent(MIDIMessageEvent::create(timeStamp, array));
......
......@@ -51,10 +51,10 @@ double now(ExecutionContext* context)
class MessageValidator {
public:
static bool validate(Uint8Array* array, ExceptionState& exceptionState, bool sysExEnabled)
static bool validate(Uint8Array* array, ExceptionState& exceptionState, bool sysexEnabled)
{
MessageValidator validator(array);
return validator.process(exceptionState, sysExEnabled);
return validator.process(exceptionState, sysexEnabled);
}
private:
MessageValidator(Uint8Array* array)
......@@ -62,14 +62,14 @@ private:
, m_length(array->length())
, m_offset(0) { }
bool process(ExceptionState& exceptionState, bool sysExEnabled)
bool process(ExceptionState& exceptionState, bool sysexEnabled)
{
while (!isEndOfData() && acceptRealTimeMessages()) {
if (!isStatusByte()) {
exceptionState.throwTypeError("Running status is not allowed " + getPositionString());
return false;
}
if (isEndOfSysEx()) {
if (isEndOfSysex()) {
exceptionState.throwTypeError("Unexpected end of system exclusive message " + getPositionString());
return false;
}
......@@ -77,12 +77,12 @@ private:
exceptionState.throwTypeError("Reserved status is not allowed " + getPositionString());
return false;
}
if (isSysEx()) {
if (!sysExEnabled) {
if (isSysex()) {
if (!sysexEnabled) {
exceptionState.throwDOMException(InvalidAccessError, "System exclusive message is not allowed " + getPositionString());
return false;
}
if (!acceptCurrentSysEx()) {
if (!acceptCurrentSysex()) {
if (isEndOfData())
exceptionState.throwTypeError("System exclusive message is not ended by end of system exclusive message.");
else
......@@ -104,9 +104,9 @@ private:
private:
bool isEndOfData() { return m_offset >= m_length; }
bool isSysEx() { return m_data[m_offset] == 0xf0; }
bool isSysex() { return m_data[m_offset] == 0xf0; }
bool isSystemMessage() { return m_data[m_offset] >= 0xf0; }
bool isEndOfSysEx() { return m_data[m_offset] == 0xf7; }
bool isEndOfSysex() { return m_data[m_offset] == 0xf7; }
bool isRealTimeMessage() { return m_data[m_offset] >= 0xf8; }
bool isStatusByte() { return m_data[m_offset] & 0x80; }
bool isReservedStatusByte() { return m_data[m_offset] == 0xf4 || m_data[m_offset] == 0xf5 || m_data[m_offset] == 0xf9 || m_data[m_offset] == 0xfd; }
......@@ -121,15 +121,15 @@ private:
return false;
}
bool acceptCurrentSysEx()
bool acceptCurrentSysex()
{
ASSERT(isSysEx());
ASSERT(isSysex());
for (m_offset++; !isEndOfData(); m_offset++) {
if (isReservedStatusByte())
return false;
if (isRealTimeMessage())
continue;
if (isEndOfSysEx()) {
if (isEndOfSysex()) {
m_offset++;
return true;
}
......@@ -142,7 +142,7 @@ private:
bool acceptCurrentMessage()
{
ASSERT(isStatusByte());
ASSERT(!isSysEx());
ASSERT(!isSysex());
ASSERT(!isReservedStatusByte());
ASSERT(!isRealTimeMessage());
static const int channelMessageLength[7] = { 3, 3, 3, 3, 2, 2, 3 }; // for 0x8*, 0x9*, ..., 0xe*
......@@ -198,7 +198,7 @@ void MIDIOutput::send(Uint8Array* array, double timestamp, ExceptionState& excep
if (!array)
return;
if (MessageValidator::validate(array, exceptionState, midiAccess()->sysExEnabled()))
if (MessageValidator::validate(array, exceptionState, midiAccess()->sysexEnabled()))
midiAccess()->sendMIDIData(m_portIndex, array->data(), array->length(), timestamp);
}
......
......@@ -44,16 +44,18 @@ MIDIClientProxy::MIDIClientProxy(WebMIDIClient* client)
{
}
void MIDIClientProxy::requestSysExPermission(PassRefPtrWillBeRawPtr<MIDIAccess> access)
void MIDIClientProxy::requestSysexPermission(PassRefPtrWillBeRawPtr<MIDIAccess> access)
{
// FIXME: call new function once Chromium implements it.
if (m_client)
m_client->requestSysExPermission(WebMIDIPermissionRequest(access));
else
access->setSysExEnabled(false);
access->setSysexEnabled(false);
}
void MIDIClientProxy::cancelSysExPermissionRequest(MIDIAccess* access)
void MIDIClientProxy::cancelSysexPermissionRequest(MIDIAccess* access)
{
// FIXME: call new function once Chromium implements it.
if (m_client)
m_client->cancelSysExPermissionRequest(WebMIDIPermissionRequest(access));
}
......
......@@ -47,8 +47,8 @@ public:
explicit MIDIClientProxy(WebMIDIClient*);
// WebCore::MIDIClient
virtual void requestSysExPermission(PassRefPtrWillBeRawPtr<WebCore::MIDIAccess>) OVERRIDE;
virtual void cancelSysExPermissionRequest(WebCore::MIDIAccess*) OVERRIDE;
virtual void requestSysexPermission(PassRefPtrWillBeRawPtr<WebCore::MIDIAccess>) OVERRIDE;
virtual void cancelSysexPermissionRequest(WebCore::MIDIAccess*) OVERRIDE;
private:
WebMIDIClient* m_client;
......
......@@ -42,9 +42,9 @@ WebMIDIClientMock::WebMIDIClientMock()
m_clientMock.reset(new WebCore::MIDIClientMock());
}
void WebMIDIClientMock::setSysExPermission(bool allowed)
void WebMIDIClientMock::setSysexPermission(bool allowed)
{
m_clientMock->setSysExPermission(allowed);
m_clientMock->setSysexPermission(allowed);
}
void WebMIDIClientMock::resetMock()
......@@ -52,14 +52,14 @@ void WebMIDIClientMock::resetMock()
m_clientMock->resetMock();
}
void WebMIDIClientMock::requestSysExPermission(const WebMIDIPermissionRequest& request)
void WebMIDIClientMock::requestSysexPermission(const WebMIDIPermissionRequest& request)
{
m_clientMock->requestSysExPermission(request.midiAccess());
m_clientMock->requestSysexPermission(request.midiAccess());
}
void WebMIDIClientMock::cancelSysExPermissionRequest(const WebMIDIPermissionRequest& request)
void WebMIDIClientMock::cancelSysexPermissionRequest(const WebMIDIPermissionRequest& request)
{
m_clientMock->cancelSysExPermissionRequest(request.midiAccess());
m_clientMock->cancelSysexPermissionRequest(request.midiAccess());
}
void WebMIDIClientMock::reset()
......
......@@ -67,7 +67,7 @@ WebSecurityOrigin WebMIDIPermissionRequest::securityOrigin() const
void WebMIDIPermissionRequest::setIsAllowed(bool allowed)
{
m_private->setSysExEnabled(allowed);
m_private->setSysexEnabled(allowed);
}
} // namespace blink
......@@ -39,9 +39,14 @@ public:
virtual ~WebMIDIClient() { }
// Request a permission to use system exclusive messages. Called when MIDIOptions.sysex is true.
virtual void requestSysExPermission(const WebMIDIPermissionRequest&) = 0;
// FIXME: Make following new functions pure virtual once Chromium implements them.
virtual void requestSysexPermission(const WebMIDIPermissionRequest&) { };
// Cancel the request since the requesting frame may be moving to a new page.
virtual void cancelSysExPermissionRequest(const WebMIDIPermissionRequest&) = 0;
virtual void cancelSysexPermissionRequest(const WebMIDIPermissionRequest&) { };
// FIXME: Remove following old functions once Chromium usess new functions.
virtual void requestSysExPermission(const WebMIDIPermissionRequest&) { };
virtual void cancelSysExPermissionRequest(const WebMIDIPermissionRequest&) { };
};
} // namespace blink
......
......@@ -46,12 +46,20 @@ public:
BLINK_EXPORT WebMIDIClientMock();
virtual ~WebMIDIClientMock() { reset(); }
BLINK_EXPORT void setSysExPermission(bool);
BLINK_EXPORT void setSysexPermission(bool);
BLINK_EXPORT void resetMock();
// FIXME: Remove following function once Chromium stop using it.
void setSysExPermission(bool permission) { setSysexPermission(permission); }
// WebMIDIClient
virtual void requestSysExPermission(const WebMIDIPermissionRequest&) OVERRIDE;
virtual void cancelSysExPermissionRequest(const WebMIDIPermissionRequest&) OVERRIDE;
virtual void requestSysexPermission(const WebMIDIPermissionRequest&) OVERRIDE;
virtual void cancelSysexPermissionRequest(const WebMIDIPermissionRequest&) OVERRIDE;
// FIXME: Remove following old functions once Chromium uses new functions.
virtual void requestSysExPermission(const WebMIDIPermissionRequest& request) { requestSysexPermission(request); }
virtual void cancelSysExPermissionRequest(const WebMIDIPermissionRequest& request) { cancelSysexPermissionRequest(request); }
private:
BLINK_EXPORT void reset();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment