Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2218)

Unified Diff: Source/modules/webmidi/MIDIAccess.cpp

Issue 77773003: Make WebMIDI use blink Promise. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Reduce protect(this). Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: Source/modules/webmidi/MIDIAccess.cpp
diff --git a/Source/modules/webmidi/MIDIAccess.cpp b/Source/modules/webmidi/MIDIAccess.cpp
index 39a7ad86fb746cd02795d68adf15bb674251c0a2..d513a480249612584b3eadc3a8b2e135e7ded9ae 100644
--- a/Source/modules/webmidi/MIDIAccess.cpp
+++ b/Source/modules/webmidi/MIDIAccess.cpp
@@ -31,36 +31,44 @@
#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 {
-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_activeDOMObjectState(Active)
+ , m_promiseState(Pending)
+ , m_options(options)
, m_hasAccess(false)
, m_sysExEnabled(false)
, m_requesting(false)
+ , m_resumeTimer(this, &MIDIAccess::resumeTimerFired)
{
ScriptWrappable::init(this);
m_accessor = MIDIAccessor::create(this);
@@ -68,12 +76,13 @@ MIDIAccess::MIDIAccess(ExecutionContext* context, MIDIAccessPromise* promise)
void MIDIAccess::setSysExEnabled(bool enable)
{
- m_requesting = false;
m_sysExEnabled = enable;
- if (enable)
+ if (enable) {
m_accessor->startSession();
- else
- permissionDenied();
+ } else {
+ reject(DOMError::create("SecurityError"));
+ // |this| may be deleted here.
+ }
}
void MIDIAccess::didAddInputPort(const String& id, const String& manufacturer, const String& name, const String& version)
@@ -94,12 +103,13 @@ void MIDIAccess::didAddOutputPort(const String& id, const String& manufacturer,
void MIDIAccess::didStartSession(bool success)
{
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"));
+ // |this| may be deleted here.
}
void MIDIAccess::didReceiveMIDIData(unsigned portIndex, const unsigned char* data, size_t length, double timeStamp)
@@ -141,49 +151,151 @@ void MIDIAccess::sendMIDIData(unsigned portIndex, const unsigned char* data, siz
}
}
+void MIDIAccess::suspend()
+{
+ ASSERT(m_activeDOMObjectState == Active);
+ m_activeDOMObjectState = Suspended;
+ m_resumeTimer.stop();
+}
+
+void MIDIAccess::resume()
+{
+ ASSERT(m_activeDOMObjectState == Suspended);
+ m_activeDOMObjectState = Active;
+ if (m_promiseState == Resolving || m_promiseState == Rejecting)
+ m_resumeTimer.startOneShot(0);
+}
+
void MIDIAccess::stop()
{
+ RefPtrWillBeRawPtr<MIDIAccess> protect(this);
+ m_activeDOMObjectState = Stopped;
m_hasAccess = false;
+ m_promiseState = ResolvedOrRejected;
+ m_error.clear();
+ m_resumeTimer.stop();
+ m_accessor.clear();
if (!m_requesting)
return;
- m_requesting = false;
Document* document = toDocument(executionContext());
ASSERT(document);
MIDIController* controller = MIDIController::from(document->page());
ASSERT(controller);
controller->cancelSysExPermissionRequest(this);
+ setRequesting(false);
+}
+
+void MIDIAccess::permissionDenied()
+{
+ ASSERT(isMainThread());
+ reject(DOMError::create("SecurityError"));
}
-void MIDIAccess::startRequest()
+void MIDIAccess::setRequesting(bool value)
{
- if (!m_promise->options()->sysex) {
+ ASSERT(m_requesting != value);
+ if (value) {
+ setPendingActivity(this);
+ m_requesting = true;
haraken 2014/02/26 11:30:39 Could you avoid using setPendingActivity/unsetPend
yhirano 2014/02/26 11:55:15 Because MIDIAccess is not exposed to the V8 GC at
haraken 2014/02/26 12:09:52 Then probably should we use ContextLifecycleObserv
yhirano 2014/02/26 12:16:37 MIDIAccess will be exposed to the GC, but it is no
yhirano 2014/02/26 12:37:12 Sorry, I was wrong. The wrapper will be created wh
haraken 2014/02/26 12:52:40 Let's discuss this issue offline tomorrow. I think
yhirano 2014/03/04 17:52:59 Done.
+ } else {
+ m_requesting = false;
+ unsetPendingActivity(this);
+ }
+}
+
+ScriptPromise MIDIAccess::startRequest()
+{
+ ASSERT(!m_requesting);
+ ScriptPromise promise = ScriptPromise::createPending();
+ m_resolver = MIDIAccessResolver::create(ScriptPromiseResolver::create(promise, executionContext()), executionContext());
+ setRequesting(true);
+ 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;
controller->requestSysExPermission(this);
} else {
- permissionDenied();
+ reject(DOMError::create("SecurityError"));
+ // |this| may be deleted here.
}
+ return promise;
}
-void MIDIAccess::permissionDenied()
+void MIDIAccess::resolve()
{
- ASSERT(isMainThread());
+ if (m_promiseState != Pending || m_activeDOMObjectState == Stopped)
+ return;
+ if (m_activeDOMObjectState == Active) {
+ resolveNow();
+ // |this| may be deleted here.
+ } else {
+ ASSERT(m_activeDOMObjectState == Suspended);
+ m_promiseState = Resolving;
+ }
+}
+
+void MIDIAccess::reject(PassRefPtr<DOMError> error)
+{
+ if (m_promiseState != Pending || m_activeDOMObjectState == Stopped)
+ return;
+ if (m_activeDOMObjectState == Active) {
+ rejectNow(error);
+ // |this| may be deleted here.
+ } else {
+ ASSERT(m_activeDOMObjectState == Suspended);
+ m_promiseState = Rejecting;
+ m_error = error;
+ }
+}
+
+void MIDIAccess::resolveNow()
+{
+ if (!m_requesting)
+ return;
+ ASSERT(m_promiseState != ResolvedOrRejected);
+ ASSERT(m_activeDOMObjectState == Active);
+
+ RefPtrWillBeRawPtr<MIDIAccess> protect(this);
+ m_promiseState = ResolvedOrRejected;
+ m_hasAccess = true;
+ setRequesting(false);
+ m_resolver->resolve(this);
+}
+void MIDIAccess::rejectNow(PassRefPtr<DOMError> error)
+{
+ if (!m_requesting)
+ return;
+ ASSERT(m_promiseState != ResolvedOrRejected);
+ ASSERT(m_activeDOMObjectState == Active);
+
+ RefPtrWillBeRawPtr<MIDIAccess> protect(this);
+ m_promiseState = ResolvedOrRejected;
m_hasAccess = false;
- m_promise->reject(DOMError::create("SecurityError"));
+ setRequesting(false);
+ m_resolver->reject(error);
+}
+
+void MIDIAccess::resumeTimerFired(Timer<MIDIAccess>*)
+{
+ ASSERT(m_activeDOMObjectState == Active);
+ if (m_promiseState == Resolving) {
+ resolveNow();
+ } else {
+ ASSERT(m_promiseState == Rejecting);
+ rejectNow(m_error.release());
+ }
+ // |this| may be deleted here.
}
void MIDIAccess::trace(Visitor* visitor)
{
visitor->trace(m_inputs);
visitor->trace(m_outputs);
- visitor->trace(m_promise);
}
} // namespace WebCore

Powered by Google App Engine
This is Rietveld 408576698