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

Side by Side Diff: Source/modules/webmidi/MIDIAccess.cpp

Issue 311773003: Decouple MIDIAccess initialization from MIDIAccess class. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: rebase Created 6 years, 6 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 unified diff | Download patch
« no previous file with comments | « Source/modules/webmidi/MIDIAccess.h ('k') | Source/modules/webmidi/MIDIAccessInitializer.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2013 Google Inc. All rights reserved. 2 * Copyright (C) 2013 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 21 matching lines...) Expand all
32 #include "modules/webmidi/MIDIAccess.h" 32 #include "modules/webmidi/MIDIAccess.h"
33 33
34 #include "bindings/v8/ScriptFunction.h" 34 #include "bindings/v8/ScriptFunction.h"
35 #include "bindings/v8/ScriptPromise.h" 35 #include "bindings/v8/ScriptPromise.h"
36 #include "bindings/v8/ScriptPromiseResolverWithContext.h" 36 #include "bindings/v8/ScriptPromiseResolverWithContext.h"
37 #include "bindings/v8/V8Binding.h" 37 #include "bindings/v8/V8Binding.h"
38 #include "core/dom/DOMError.h" 38 #include "core/dom/DOMError.h"
39 #include "core/dom/Document.h" 39 #include "core/dom/Document.h"
40 #include "core/loader/DocumentLoadTiming.h" 40 #include "core/loader/DocumentLoadTiming.h"
41 #include "core/loader/DocumentLoader.h" 41 #include "core/loader/DocumentLoader.h"
42 #include "modules/webmidi/MIDIAccessInitializer.h"
42 #include "modules/webmidi/MIDIConnectionEvent.h" 43 #include "modules/webmidi/MIDIConnectionEvent.h"
43 #include "modules/webmidi/MIDIController.h" 44 #include "modules/webmidi/MIDIController.h"
44 #include "modules/webmidi/MIDIOptions.h" 45 #include "modules/webmidi/MIDIOptions.h"
45 #include "modules/webmidi/MIDIPort.h" 46 #include "modules/webmidi/MIDIPort.h"
46 #include "platform/AsyncMethodRunner.h" 47 #include "platform/AsyncMethodRunner.h"
47 #include <v8.h> 48 #include <v8.h>
48 49
49 namespace WebCore { 50 namespace WebCore {
50 51
51 class MIDIAccess::PostAction : public ScriptFunction {
52 public:
53 static PassOwnPtr<MIDIAccess::PostAction> create(v8::Isolate* isolate, WeakP tr<MIDIAccess> owner, State state) { return adoptPtr(new PostAction(isolate, own er, state)); }
54
55 private:
56 PostAction(v8::Isolate* isolate, WeakPtr<MIDIAccess> owner, State state): Sc riptFunction(isolate), m_owner(owner), m_state(state) { }
57 virtual ScriptValue call(ScriptValue value) OVERRIDE
58 {
59 if (!m_owner.get())
60 return value;
61 m_owner->doPostAction(m_state);
62 return value;
63 }
64
65 WeakPtr<MIDIAccess> m_owner;
66 State m_state;
67 };
68
69 ScriptPromise MIDIAccess::request(const MIDIOptions& options, ScriptState* scrip tState) 52 ScriptPromise MIDIAccess::request(const MIDIOptions& options, ScriptState* scrip tState)
70 { 53 {
71 RefPtrWillBeRawPtr<MIDIAccess> midiAccess(adoptRefWillBeRefCountedGarbageCol lected(new MIDIAccess(options, scriptState->executionContext()))); 54 RefPtrWillBeRawPtr<MIDIAccess> midiAccess(adoptRefWillBeRefCountedGarbageCol lected(new MIDIAccess(options, scriptState->executionContext())));
72 midiAccess->suspendIfNeeded(); 55 midiAccess->suspendIfNeeded();
73 // Create a wrapper to expose this object to the V8 GC so that 56 // Create a wrapper to expose this object to the V8 GC so that
74 // hasPendingActivity takes effect. 57 // hasPendingActivity takes effect.
75 toV8NoInline(midiAccess.get(), scriptState->context()->Global(), scriptState ->isolate()); 58 toV8NoInline(midiAccess.get(), scriptState->context()->Global(), scriptState ->isolate());
76 // Now this object is retained because m_state equals to Requesting. 59 // Now this object is retained because hasPending returns true.
77 return midiAccess->startRequest(scriptState); 60 return midiAccess->m_initializer->initialize(scriptState);
78 } 61 }
79 62
80 MIDIAccess::~MIDIAccess() 63 MIDIAccess::~MIDIAccess()
81 { 64 {
82 } 65 }
83 66
84 MIDIAccess::MIDIAccess(const MIDIOptions& options, ExecutionContext* context) 67 MIDIAccess::MIDIAccess(const MIDIOptions& options, ExecutionContext* context)
85 : ActiveDOMObject(context) 68 : ActiveDOMObject(context)
86 , m_state(Requesting) 69 , m_initializer(MIDIAccessInitializer::create(options, this))
87 , m_weakPtrFactory(this)
88 , m_options(options)
89 , m_sysexEnabled(false)
90 { 70 {
91 ScriptWrappable::init(this); 71 ScriptWrappable::init(this);
92 m_accessor = MIDIAccessor::create(this);
93 }
94
95 void MIDIAccess::setSysexEnabled(bool enable)
96 {
97 m_sysexEnabled = enable;
98 if (enable) {
99 m_accessor->startSession();
100 } else {
101 m_resolver->reject(DOMError::create("SecurityError"));
102 }
103 } 72 }
104 73
105 void MIDIAccess::didAddInputPort(const String& id, const String& manufacturer, c onst String& name, const String& version) 74 void MIDIAccess::didAddInputPort(const String& id, const String& manufacturer, c onst String& name, const String& version)
106 { 75 {
107 ASSERT(isMainThread()); 76 ASSERT(isMainThread());
108
109 m_inputs.append(MIDIInput::create(this, id, manufacturer, name, version)); 77 m_inputs.append(MIDIInput::create(this, id, manufacturer, name, version));
110 } 78 }
111 79
112 void MIDIAccess::didAddOutputPort(const String& id, const String& manufacturer, const String& name, const String& version) 80 void MIDIAccess::didAddOutputPort(const String& id, const String& manufacturer, const String& name, const String& version)
113 { 81 {
114 ASSERT(isMainThread()); 82 ASSERT(isMainThread());
115
116 unsigned portIndex = m_outputs.size(); 83 unsigned portIndex = m_outputs.size();
117 m_outputs.append(MIDIOutput::create(this, portIndex, id, manufacturer, name, version)); 84 m_outputs.append(MIDIOutput::create(this, portIndex, id, manufacturer, name, version));
118 } 85 }
119 86
120 void MIDIAccess::didStartSession(bool success, const String& error, const String & message)
121 {
122 ASSERT(isMainThread());
123 if (success)
124 m_resolver->resolve(this);
125 else
126 m_resolver->reject(DOMError::create(error, message));
127 }
128
129 void MIDIAccess::didReceiveMIDIData(unsigned portIndex, const unsigned char* dat a, size_t length, double timeStamp) 87 void MIDIAccess::didReceiveMIDIData(unsigned portIndex, const unsigned char* dat a, size_t length, double timeStamp)
130 { 88 {
131 ASSERT(isMainThread()); 89 ASSERT(isMainThread());
90 if (portIndex >= m_inputs.size())
91 return;
132 92
133 if (m_state == Resolved && portIndex < m_inputs.size()) { 93 // Convert from time in seconds which is based on the time coordinate system of monotonicallyIncreasingTime()
134 // Convert from time in seconds which is based on the time coordinate sy stem of monotonicallyIncreasingTime() 94 // into time in milliseconds (a DOMHighResTimeStamp) according to the same t ime coordinate system as performance.now().
135 // into time in milliseconds (a DOMHighResTimeStamp) according to the sa me time coordinate system as performance.now(). 95 // This is how timestamps are defined in the Web MIDI spec.
136 // This is how timestamps are defined in the Web MIDI spec. 96 Document* document = toDocument(executionContext());
137 Document* document = toDocument(executionContext()); 97 ASSERT(document);
138 ASSERT(document);
139 98
140 double timeStampInMilliseconds = 1000 * document->loader()->timing()->mo notonicTimeToZeroBasedDocumentTime(timeStamp); 99 double timeStampInMilliseconds = 1000 * document->loader()->timing()->monoto nicTimeToZeroBasedDocumentTime(timeStamp);
141 100
142 m_inputs[portIndex]->didReceiveMIDIData(portIndex, data, length, timeSta mpInMilliseconds); 101 m_inputs[portIndex]->didReceiveMIDIData(portIndex, data, length, timeStampIn Milliseconds);
143 }
144 } 102 }
145 103
146 void MIDIAccess::sendMIDIData(unsigned portIndex, const unsigned char* data, siz e_t length, double timeStampInMilliseconds) 104 void MIDIAccess::sendMIDIData(unsigned portIndex, const unsigned char* data, siz e_t length, double timeStampInMilliseconds)
147 { 105 {
148 if (m_state == Resolved && portIndex < m_outputs.size() && data && length > 0) { 106 if (!data || !length || portIndex >= m_outputs.size())
149 // Convert from a time in milliseconds (a DOMHighResTimeStamp) according to the same time coordinate system as performance.now() 107 return;
150 // into a time in seconds which is based on the time coordinate system o f monotonicallyIncreasingTime(). 108 // Convert from a time in milliseconds (a DOMHighResTimeStamp) according to the same time coordinate system as performance.now()
151 double timeStamp; 109 // into a time in seconds which is based on the time coordinate system of mo notonicallyIncreasingTime().
110 double timeStamp;
152 111
153 if (!timeStampInMilliseconds) { 112 if (!timeStampInMilliseconds) {
154 // We treat a value of 0 (which is the default value) as special, me aning "now". 113 // We treat a value of 0 (which is the default value) as special, meanin g "now".
155 // We need to translate it exactly to 0 seconds. 114 // We need to translate it exactly to 0 seconds.
156 timeStamp = 0; 115 timeStamp = 0;
157 } else { 116 } else {
158 Document* document = toDocument(executionContext()); 117 Document* document = toDocument(executionContext());
159 ASSERT(document); 118 ASSERT(document);
160 double documentStartTime = document->loader()->timing()->referenceMo notonicTime(); 119 double documentStartTime = document->loader()->timing()->referenceMonoto nicTime();
161 timeStamp = documentStartTime + 0.001 * timeStampInMilliseconds; 120 timeStamp = documentStartTime + 0.001 * timeStampInMilliseconds;
162 } 121 }
163 122
164 m_accessor->sendMIDIData(portIndex, data, length, timeStamp); 123 m_accessor->sendMIDIData(portIndex, data, length, timeStamp);
165 }
166 } 124 }
167 125
168 void MIDIAccess::stop() 126 void MIDIAccess::stop()
169 { 127 {
170 if (m_state == Stopped)
171 return;
172 m_accessor.clear(); 128 m_accessor.clear();
173 m_weakPtrFactory.revokeAll(); 129 m_initializer->cancel();
174 if (m_state == Requesting) {
175 Document* document = toDocument(executionContext());
176 ASSERT(document);
177 MIDIController* controller = MIDIController::from(document->frame());
178 ASSERT(controller);
179 controller->cancelSysexPermissionRequest(this);
180 }
181 m_state = Stopped;
182 } 130 }
183 131
184 bool MIDIAccess::hasPendingActivity() const 132 bool MIDIAccess::hasPendingActivity() const
185 { 133 {
186 return m_state == Requesting; 134 return m_initializer->hasPendingActivity();
187 } 135 }
188 136
189 void MIDIAccess::permissionDenied() 137 void MIDIAccess::initialize(PassOwnPtr<MIDIAccessor> accessor, bool sysexEnabled )
190 { 138 {
191 ASSERT(isMainThread()); 139 ASSERT(accessor);
192 m_resolver->reject(DOMError::create("SecurityError")); 140 m_accessor = accessor;
193 } 141 m_accessor->setClient(this);
194 142 m_sysexEnabled = sysexEnabled;
195 ScriptPromise MIDIAccess::startRequest(ScriptState* scriptState)
196 {
197 m_resolver = ScriptPromiseResolverWithContext::create(scriptState);
198 ScriptPromise promise = m_resolver->promise();
199 promise.then(PostAction::create(scriptState->isolate(), m_weakPtrFactory.cre ateWeakPtr(), Resolved),
200 PostAction::create(scriptState->isolate(), m_weakPtrFactory.createWeakPt r(), Stopped));
201
202 if (!m_options.sysex) {
203 m_accessor->startSession();
204 return promise;
205 }
206 Document* document = toDocument(executionContext());
207 ASSERT(document);
208 MIDIController* controller = MIDIController::from(document->frame());
209 if (controller) {
210 controller->requestSysexPermission(this);
211 } else {
212 m_resolver->reject(DOMError::create("SecurityError"));
213 }
214 return promise;
215 }
216
217 void MIDIAccess::doPostAction(State state)
218 {
219 ASSERT(m_state == Requesting);
220 ASSERT(state == Resolved || state == Stopped);
221 if (state == Stopped) {
222 m_accessor.clear();
223 }
224 m_weakPtrFactory.revokeAll();
225 m_state = state;
226 } 143 }
227 144
228 void MIDIAccess::trace(Visitor* visitor) 145 void MIDIAccess::trace(Visitor* visitor)
229 { 146 {
230 visitor->trace(m_inputs); 147 visitor->trace(m_inputs);
231 visitor->trace(m_outputs); 148 visitor->trace(m_outputs);
232 EventTargetWithInlineData::trace(visitor); 149 EventTargetWithInlineData::trace(visitor);
233 } 150 }
234 151
235 } // namespace WebCore 152 } // namespace WebCore
OLDNEW
« no previous file with comments | « Source/modules/webmidi/MIDIAccess.h ('k') | Source/modules/webmidi/MIDIAccessInitializer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698