Chromium Code Reviews| Index: Source/modules/webmidi/MIDIAccess.cpp |
| diff --git a/Source/modules/webmidi/MIDIAccess.cpp b/Source/modules/webmidi/MIDIAccess.cpp |
| index c2e333863039f3d4b554d79c8e5803d74055e8a0..f578938decef481cc01d710814f53d7311bae633 100644 |
| --- a/Source/modules/webmidi/MIDIAccess.cpp |
| +++ b/Source/modules/webmidi/MIDIAccess.cpp |
| @@ -31,35 +31,40 @@ |
| #include "config.h" |
| #include "modules/webmidi/MIDIAccess.h" |
| +#include "bindings/v8/DOMRequestState.h" |
| +#include "bindings/v8/DOMWrapperWorld.h" |
| +#include "bindings/v8/ScriptPromise.h" |
| +#include "bindings/v8/ScriptPromiseResolver.h" |
| +#include "bindings/v8/V8Binding.h" |
| #include "core/dom/DOMError.h" |
| #include "core/dom/Document.h" |
| #include "core/loader/DocumentLoadTiming.h" |
| #include "core/loader/DocumentLoader.h" |
| -#include "modules/webmidi/MIDIAccessPromise.h" |
| #include "modules/webmidi/MIDIConnectionEvent.h" |
| #include "modules/webmidi/MIDIController.h" |
| +#include "modules/webmidi/MIDIOptions.h" |
| #include "modules/webmidi/MIDIPort.h" |
| +#include "modules/webmidi/NavigatorWebMIDI.h" |
| namespace WebCore { |
| DEFINE_GC_INFO(MIDIAccess); |
| -PassRefPtrWillBeRawPtr<MIDIAccess> MIDIAccess::create(ExecutionContext* context, MIDIAccessPromise* promise) |
| +PassRefPtrWillBeRawPtr<MIDIAccess> MIDIAccess::create(const MIDIOptions& options, ExecutionContext* context) |
| { |
| - RefPtrWillBeRawPtr<MIDIAccess> midiAccess(adoptRefCountedWillBeRefCountedGarbageCollected(new MIDIAccess(context, promise))); |
| + RefPtrWillBeRawPtr<MIDIAccess> midiAccess(adoptRefCountedWillBeRefCountedGarbageCollected(new MIDIAccess(options, context))); |
| midiAccess->suspendIfNeeded(); |
| - midiAccess->startRequest(); |
| return midiAccess.release(); |
| } |
| MIDIAccess::~MIDIAccess() |
| { |
| - stop(); |
| + ASSERT(!m_requesting); |
| } |
| -MIDIAccess::MIDIAccess(ExecutionContext* context, MIDIAccessPromise* promise) |
| +MIDIAccess::MIDIAccess(const MIDIOptions& options, ExecutionContext* context) |
| : ActiveDOMObject(context) |
| - , m_promise(promise) |
| + , m_options(options) |
| , m_hasAccess(false) |
| , m_sysExEnabled(false) |
| , m_requesting(false) |
| @@ -70,12 +75,12 @@ MIDIAccess::MIDIAccess(ExecutionContext* context, MIDIAccessPromise* promise) |
| void MIDIAccess::setSysExEnabled(bool enable) |
| { |
| - m_requesting = false; |
| + RefPtr<MIDIAccess> protect(this); |
| m_sysExEnabled = enable; |
| if (enable) |
| m_accessor->startSession(); |
| else |
| - permissionDenied(); |
| + reject(DOMError::create("SecurityError")); |
| } |
| void MIDIAccess::didAddInputPort(const String& id, const String& manufacturer, const String& name, const String& version) |
| @@ -95,13 +100,14 @@ void MIDIAccess::didAddOutputPort(const String& id, const String& manufacturer, |
| void MIDIAccess::didStartSession(bool success) |
| { |
| + RefPtr<MIDIAccess> protect(this); |
| ASSERT(isMainThread()); |
| - |
| - m_hasAccess = success; |
| + if (!m_requesting) |
| + return; |
| if (success) |
| - m_promise->fulfill(); |
| + resolve(); |
| else |
| - m_promise->reject(DOMError::create("InvalidStateError")); |
| + reject(DOMError::create("InvalidStateError")); |
| } |
| void MIDIAccess::didReceiveMIDIData(unsigned portIndex, const unsigned char* data, size_t length, double timeStamp) |
| @@ -145,47 +151,86 @@ void MIDIAccess::sendMIDIData(unsigned portIndex, const unsigned char* data, siz |
| void MIDIAccess::stop() |
| { |
| + RefPtr<MIDIAccess> protect(this); |
| m_hasAccess = false; |
| if (!m_requesting) |
| return; |
| - m_requesting = false; |
| Document* document = toDocument(executionContext()); |
| ASSERT(document); |
| MIDIController* controller = MIDIController::from(document->page()); |
| ASSERT(controller); |
| controller->cancelSysExPermissionRequest(this); |
| + |
| + m_accessor.clear(); |
| + reject(DOMError::create("AbortError")); |
| } |
| -void MIDIAccess::startRequest() |
| +void MIDIAccess::permissionDenied() |
| +{ |
| + RefPtr<MIDIAccess> protect(this); |
| + ASSERT(isMainThread()); |
| + reject(DOMError::create("SecurityError")); |
| +} |
| + |
| +ScriptPromise MIDIAccess::startRequest() |
| { |
| - if (!m_promise->options()->sysex) { |
| + ASSERT(!m_requesting); |
| + RefPtr<MIDIAccess> protect(this); |
|
haraken
2014/02/21 11:11:40
Why do you need protection? Is this "just in case"
yhirano
2014/02/21 13:52:35
I think they were introduced by your suggestion.
h
yhirano
2014/02/26 09:18:08
I deleted many of protect(this).
|
| + ScriptPromise promise = ScriptPromise::createPending(); |
| + m_resolver = ScriptPromiseResolver::create(promise, executionContext()); |
| + m_world = RefPtr<DOMWrapperWorld>(DOMWrapperWorld::current(toIsolate(executionContext()))); |
| + m_requesting = true; |
| + setPendingActivity(this); |
|
haraken
2014/02/21 11:11:40
m_requesting and setPendingActivity should be sync
yhirano
2014/02/21 13:52:35
Done.
|
| + if (!m_options.sysex) { |
| m_accessor->startSession(); |
| - return; |
| + return promise; |
| } |
| Document* document = toDocument(executionContext()); |
| ASSERT(document); |
| MIDIController* controller = MIDIController::from(document->page()); |
| - if (controller) { |
| - m_requesting = true; |
| + if (controller) |
| controller->requestSysExPermission(this); |
| - } else { |
| - permissionDenied(); |
| - } |
| + else |
| + reject(DOMError::create("SecurityError")); |
| + return promise; |
| } |
| -void MIDIAccess::permissionDenied() |
| +void MIDIAccess::resolve() |
| { |
| - ASSERT(isMainThread()); |
| + RefPtr<MIDIAccess> protect(this); |
| + if (!m_requesting) |
| + return; |
| + ASSERT(m_world.get()); |
| + DOMRequestState state(executionContext(), m_world); |
| + DOMRequestState::Scope scope(state); |
|
haraken
2014/02/21 11:11:40
I don't understand why you need DOMRequestState he
yhirano
2014/02/21 13:52:35
I introduced MIDIAccessResolver.
|
| + m_world.clear(); |
| + m_hasAccess = true; |
|
haraken
2014/02/21 11:11:40
What is m_hasAccess for?
yhirano
2014/02/21 13:52:35
m_hasAccess is used in didReceiveMIDIData and send
|
| + m_requesting = false; |
| + unsetPendingActivity(this); |
| + // FIXME: Care about suspend / stop. |
|
haraken
2014/02/21 11:11:40
I think you need to fix this in this CL.
yhirano
2014/02/21 13:52:35
Done.
|
| + m_resolver->resolve(this, executionContext()); |
| +} |
| +void MIDIAccess::reject(PassRefPtr<DOMError> error) |
| +{ |
| + RefPtr<MIDIAccess> protect(this); |
| + if (!m_requesting) |
| + return; |
| + ASSERT(m_world.get()); |
| + DOMRequestState state(executionContext(), m_world); |
| + DOMRequestState::Scope scope(state); |
| + m_world.clear(); |
| m_hasAccess = false; |
| - m_promise->reject(DOMError::create("SecurityError")); |
| + m_requesting = false; |
| + unsetPendingActivity(this); |
| + // FIXME: Care about suspend / stop. |
| + m_resolver->reject(error, executionContext()); |
| } |
| void MIDIAccess::trace(Visitor* visitor) |
| { |
| visitor->trace(m_inputs); |
| visitor->trace(m_outputs); |
| - visitor->trace(m_promise); |
| } |
| } // namespace WebCore |