void MessagePort::postMessage(ExecutionContext* context, PassRefPtr<SerializedScriptValue> message, const MessagePortArray& ports, ExceptionState& exceptionState) { if (!isEntangled()) return; DCHECK(getExecutionContext()); DCHECK(m_entangledChannel); // Make sure we aren't connected to any of the passed-in ports. for (unsigned i = 0; i < ports.size(); ++i) { if (ports[i] == this) { exceptionState.throwDOMException( DataCloneError, "Port at index " + String::number(i) + " contains the source port."); return; } } std::unique_ptr<MessagePortChannelArray> channels = MessagePort::disentanglePorts(context, ports, exceptionState); if (exceptionState.hadException()) return; if (message->containsTransferableArrayBuffer()) getExecutionContext()->addConsoleMessage(ConsoleMessage::create( JSMessageSource, WarningMessageLevel, "MessagePort cannot send an ArrayBuffer as a transferable object yet. " "See http://crbug.com/334408")); WebString messageString = message->toWireString(); std::unique_ptr<WebMessagePortChannelArray> webChannels = toWebMessagePortChannelArray(std::move(channels)); m_entangledChannel->postMessage(messageString, webChannels.release()); }
void IDBDatabase::closeConnection() { DCHECK(m_closePending); DCHECK(m_transactions.isEmpty()); if (m_backend) { m_backend->close(); m_backend.reset(); } if (m_databaseCallbacks) m_databaseCallbacks->detachWebCallbacks(); if (m_contextStopped || !getExecutionContext()) return; EventQueue* eventQueue = getExecutionContext()->getEventQueue(); // Remove any pending versionchange events scheduled to fire on this // connection. They would have been scheduled by the backend when another // connection attempted an upgrade, but the frontend connection is being // closed before they could fire. for (size_t i = 0; i < m_enqueuedEvents.size(); ++i) { bool removed = eventQueue->cancelEvent(m_enqueuedEvents[i].get()); DCHECK(removed); } }
// Invoked to notify us that there are messages available for this port. // This code may be called from another thread, and so should not call any // non-threadsafe APIs (i.e. should not call into the entangled channel or // access mutable variables). void MessagePort::messageAvailable() { DCHECK(getExecutionContext()); getExecutionContext()->postTask( BLINK_FROM_HERE, createCrossThreadTask(&MessagePort::dispatchMessages, wrapCrossThreadWeakPersistent(this))); }
void MessagePort::dispatchMessages() { // Because close() doesn't cancel any in flight calls to dispatchMessages() we // need to check if the port is still open before dispatch. if (m_closed) return; // Messages for contexts that are not fully active get dispatched too, but // JSAbstractEventListener::handleEvent() doesn't call handlers for these. // The HTML5 spec specifies that any messages sent to a document that is not // fully active should be dropped, so this behavior is OK. if (!started()) return; RefPtr<SerializedScriptValue> message; std::unique_ptr<MessagePortChannelArray> channels; while (tryGetMessage(message, channels)) { // close() in Worker onmessage handler should prevent next message from // dispatching. if (getExecutionContext()->isWorkerGlobalScope() && toWorkerGlobalScope(getExecutionContext())->isClosing()) return; MessagePortArray* ports = MessagePort::entanglePorts(*getExecutionContext(), std::move(channels)); Event* evt = MessageEvent::create(ports, message.release()); dispatchEvent(evt); } }
DispatchEventResult IDBTransaction::dispatchEventInternal(Event* event) { IDB_TRACE("IDBTransaction::dispatchEvent"); if (!getExecutionContext()) { m_state = Finished; return DispatchEventResult::CanceledBeforeDispatch; } DCHECK_NE(m_state, Finished); DCHECK(m_hasPendingActivity); DCHECK(getExecutionContext()); DCHECK_EQ(event->target(), this); m_state = Finished; HeapVector<Member<EventTarget>> targets; targets.append(this); targets.append(db()); // FIXME: When we allow custom event dispatching, this will probably need to // change. DCHECK(event->type() == EventTypeNames::complete || event->type() == EventTypeNames::abort); DispatchEventResult dispatchResult = IDBEventDispatcher::dispatch(event, targets); // FIXME: Try to construct a test where |this| outlives openDBRequest and we // get a crash. if (m_openDBRequest) { DCHECK(isVersionChange()); m_openDBRequest->transactionDidFinishAndDispatch(); } m_hasPendingActivity = false; return dispatchResult; }
void IDBDatabase::enqueueEvent(Event* event) { DCHECK(!m_contextStopped); DCHECK(getExecutionContext()); EventQueue* eventQueue = getExecutionContext()->getEventQueue(); event->setTarget(this); eventQueue->enqueueEvent(event); m_enqueuedEvents.append(event); }
void MediaSession::DidReceiveAction( blink::mojom::blink::MediaSessionAction action) { DCHECK(getExecutionContext()->isDocument()); Document* document = toDocument(getExecutionContext()); UserGestureIndicator gestureIndicator( DocumentUserGestureToken::create(document)); dispatchEvent(Event::create(mojomActionToEventName(action))); }
void ThreadedMessagingProxyBase::postTaskToLoader( const WebTraceLocation& location, std::unique_ptr<ExecutionContextTask> task) { DCHECK(getExecutionContext()->isDocument()); // TODO(hiroshige,yuryu): Make this not use ExecutionContextTask and use // m_parentFrameTaskRunners->get(TaskType::Networking) instead. getExecutionContext()->postTask(location, std::move(task)); }
bool PresentationRequest::hasPendingActivity() const { if (!getExecutionContext() || getExecutionContext()->activeDOMObjectsAreStopped()) return false; // Prevents garbage collecting of this object when not hold by another // object but still has listeners registered. return hasEventListeners(); }
void PermissionStatus::startListening() { DCHECK(!m_service); connectToPermissionService(getExecutionContext(), mojo::GetProxy(&m_service)); m_service->GetNextPermissionChange( m_descriptor->Clone(), getExecutionContext()->getSecurityOrigin(), m_status, convertToBaseCallback(WTF::bind(&PermissionStatus::permissionChanged, wrapWeakPersistent(this)))); }
void EventSource::didReceiveResponse( unsigned long, const ResourceResponse& response, std::unique_ptr<WebDataConsumerHandle> handle) { DCHECK(!handle); DCHECK_EQ(kConnecting, m_state); DCHECK(m_loader); m_currentURL = response.url(); m_eventStreamOrigin = SecurityOrigin::create(response.url())->toString(); int statusCode = response.httpStatusCode(); bool mimeTypeIsValid = response.mimeType() == "text/event-stream"; bool responseIsValid = statusCode == 200 && mimeTypeIsValid; if (responseIsValid) { const String& charset = response.textEncodingName(); // If we have a charset, the only allowed value is UTF-8 (case-insensitive). responseIsValid = charset.isEmpty() || equalIgnoringCase(charset, "UTF-8"); if (!responseIsValid) { StringBuilder message; message.append("EventSource's response has a charset (\""); message.append(charset); message.append("\") that is not UTF-8. Aborting the connection."); // FIXME: We are missing the source line. getExecutionContext()->addConsoleMessage(ConsoleMessage::create( JSMessageSource, ErrorMessageLevel, message.toString())); } } else { // To keep the signal-to-noise ratio low, we only log 200-response with an // invalid MIME type. if (statusCode == 200 && !mimeTypeIsValid) { StringBuilder message; message.append("EventSource's response has a MIME type (\""); message.append(response.mimeType()); message.append( "\") that is not \"text/event-stream\". Aborting the connection."); // FIXME: We are missing the source line. getExecutionContext()->addConsoleMessage(ConsoleMessage::create( JSMessageSource, ErrorMessageLevel, message.toString())); } } if (responseIsValid) { m_state = kOpen; AtomicString lastEventId; if (m_parser) { // The new parser takes over the event ID. lastEventId = m_parser->lastEventId(); } m_parser = new EventSourceParser(lastEventId, this); dispatchEvent(Event::create(EventTypeNames::open)); } else { m_loader->cancel(); dispatchEvent(Event::create(EventTypeNames::error)); } }
void ServiceWorkerRegistrationNotifications::prepareShow( const WebNotificationData& data, std::unique_ptr<WebNotificationShowCallbacks> callbacks) { RefPtr<SecurityOrigin> origin = getExecutionContext()->getSecurityOrigin(); NotificationResourcesLoader* loader = new NotificationResourcesLoader( WTF::bind(&ServiceWorkerRegistrationNotifications::didLoadResources, wrapWeakPersistent(this), origin.release(), data, WTF::passed(std::move(callbacks)))); m_loaders.add(loader); loader->start(getExecutionContext(), data); }
void IDBTransaction::enqueueEvent(Event* event) { DCHECK_NE(m_state, Finished) << "A finished transaction tried to enqueue an event of type " << event->type() << "."; if (!getExecutionContext()) return; EventQueue* eventQueue = getExecutionContext()->getEventQueue(); event->setTarget(this); eventQueue->enqueueEvent(event); }
void PresentationAvailability::updateListening() { WebPresentationClient* client = presentationClient(getExecutionContext()); if (!client) return; if (m_state == State::Active && (toDocument(getExecutionContext())->pageVisibilityState() == PageVisibilityStateVisible)) client->startListening(this); else client->stopListening(this); }
void Notification::prepareShow() { DCHECK_EQ(m_state, State::Loading); if (NotificationManager::from(getExecutionContext())->permissionStatus() != mojom::blink::PermissionStatus::GRANTED) { dispatchErrorEvent(); return; } m_loader = new NotificationResourcesLoader( WTF::bind(&Notification::didLoadResources, wrapWeakPersistent(this))); m_loader->start(getExecutionContext(), m_data); }
bool MediaStream::addEventListenerInternal( const AtomicString& eventType, EventListener* listener, const AddEventListenerOptionsResolved& options) { if (eventType == EventTypeNames::active) UseCounter::count(getExecutionContext(), UseCounter::MediaStreamOnActive); else if (eventType == EventTypeNames::inactive) UseCounter::count(getExecutionContext(), UseCounter::MediaStreamOnInactive); return EventTargetWithInlineData::addEventListenerInternal(eventType, listener, options); }
void Sensor::updateState(Sensor::SensorState newState) { if (newState == m_state) return; m_state = newState; if (getExecutionContext()) { getExecutionContext()->postTask( BLINK_FROM_HERE, createSameThreadTask(&Sensor::notifyStateChanged, wrapWeakPersistent(this))); } updatePollingStatus(); }
void Sensor::updateState(Sensor::SensorState newState) { if (newState == m_state) return; if (newState == SensorState::Activated && getExecutionContext()) { DCHECK_EQ(SensorState::Activating, m_state); getExecutionContext()->postTask( BLINK_FROM_HERE, createSameThreadTask(&Sensor::notifyOnActivate, wrapWeakPersistent(this))); } m_state = newState; }
void Sensor::reportError(ExceptionCode code, const String& sanitizedMessage, const String& unsanitizedMessage) { updateState(Sensor::SensorState::Errored); if (getExecutionContext()) { auto error = DOMException::create(code, sanitizedMessage, unsanitizedMessage); getExecutionContext()->postTask( BLINK_FROM_HERE, createSameThreadTask(&Sensor::notifyError, wrapWeakPersistent(this), wrapPersistent(error))); } }
void WorkerGlobalScope::countDeprecation(UseCounter::Feature feature) const { // FIXME: How should we count features for shared/service workers? ASSERT(isSharedWorkerGlobalScope() || isServiceWorkerGlobalScope() || isCompositorWorkerGlobalScope()); // For each deprecated feature, send console message at most once // per worker lifecycle. if (!m_deprecationWarningBits.hasRecordedMeasurement(feature)) { m_deprecationWarningBits.recordMeasurement(feature); ASSERT(!Deprecation::deprecationMessage(feature).isEmpty()); ASSERT(getExecutionContext()); getExecutionContext()->addConsoleMessage(ConsoleMessage::create(DeprecationMessageSource, WarningMessageLevel, Deprecation::deprecationMessage(feature))); } }
void ScriptPromiseResolver::resolveOrRejectImmediately() { DCHECK(!getExecutionContext()->isContextDestroyed()); DCHECK(!getExecutionContext()->activeDOMObjectsAreSuspended()); { InspectorInstrumentation::AsyncTask asyncTask(getExecutionContext(), this); if (m_state == Resolving) { m_resolver.resolve(m_value.newLocal(m_scriptState->isolate())); } else { ASSERT(m_state == Rejecting); m_resolver.reject(m_value.newLocal(m_scriptState->isolate())); } } detach(); }
ScriptedIdleTaskController::CallbackId ScriptedIdleTaskController::registerCallback( IdleRequestCallback* callback, const IdleRequestOptions& options) { CallbackId id = nextCallbackId(); m_callbacks.set(id, callback); long long timeoutMillis = options.timeout(); RefPtr<internal::IdleRequestCallbackWrapper> callbackWrapper = internal::IdleRequestCallbackWrapper::create(id, this); m_scheduler->postIdleTask( BLINK_FROM_HERE, WTF::bind(&internal::IdleRequestCallbackWrapper::idleTaskFired, callbackWrapper)); if (timeoutMillis > 0) m_scheduler->timerTaskRunner()->postDelayedTask( BLINK_FROM_HERE, WTF::bind(&internal::IdleRequestCallbackWrapper::timeoutFired, callbackWrapper), timeoutMillis); TRACE_EVENT_INSTANT1("devtools.timeline", "RequestIdleCallback", TRACE_EVENT_SCOPE_THREAD, "data", InspectorIdleCallbackRequestEvent::data( getExecutionContext(), id, timeoutMillis)); return id; }
void IDBTransaction::onAbort(DOMException* error) { IDB_TRACE("IDBTransaction::onAbort"); if (!getExecutionContext()) { finished(); return; } DCHECK_NE(m_state, Finished); if (m_state != Finishing) { // Abort was not triggered by front-end. DCHECK(error); setError(error); abortOutstandingRequests(); revertDatabaseMetadata(); m_state = Finishing; } if (isVersionChange()) m_database->close(); // Enqueue events before notifying database, as database may close which // enqueues more events and order matters. enqueueEvent(Event::createBubble(EventTypeNames::abort)); finished(); }
void MediaDevices::didChangeMediaDevices() { Document* document = toDocument(getExecutionContext()); DCHECK(document); if (RuntimeEnabledFeatures::onDeviceChangeEnabled()) scheduleDispatchEvent(Event::create(EventTypeNames::devicechange)); }
UserMediaController* MediaDevices::getUserMediaController() { Document* document = toDocument(getExecutionContext()); if (!document) return nullptr; return UserMediaController::from(document->frame()); }
void V8WebCL::constructorCustom(const v8::Arguments& args) { if (!args.IsConstructCall()) { throwTypeError("DOM object constructor cannot be called as a function.",args.GetIsolate()); return; } if (ConstructorMode::current() == ConstructorMode::WrapExistingObject) { v8SetReturnValue(args, args.Holder()); return; } // Get the script execution context. ScriptExecutionContext* context = (ScriptExecutionContext*)getExecutionContext(); //getScriptExecutionContext(); // if (!context) //{ throwError(ReferenceError, "WebCL constructor's associated frame is not available", args.GetIsolate()); return; } RefPtr<WebCL> computeContext = WebCL::create(context); const WrapperTypeInfo &info = wrapperTypeInfo; // ScalableVision V8DOMWrapper::setNativeInfo(args.Holder(), &info, computeContext.get()); //lifetime LT; //V8DOMWrapper::setJSWrapperForActiveDOMObject(computeContext.release(), v8::Persistent<v8::Object>::New(args.Holder()), args.GetIsolate()); V8DOMWrapper::associateObjectWithWrapper<V8WebCL, WebCL>(computeContext.release(),&info, /*v8::Persistent<v8::Object>::New(*/args.Holder()/*)*/, args.GetIsolate(),WrapperConfiguration::Dependent );//ÅáÓ¨ v8SetReturnValue(args, args.Holder()); return; }
void ScriptPromisePropertyBase::resolveOrReject(State targetState) { ASSERT(getExecutionContext()); ASSERT(m_state == Pending); ASSERT(targetState == Resolved || targetState == Rejected); m_state = targetState; v8::HandleScope handleScope(m_isolate); size_t i = 0; while (i < m_wrappers.size()) { const std::unique_ptr<ScopedPersistent<v8::Object>>& persistent = m_wrappers[i]; if (persistent->isEmpty()) { // wrapper has died. // Since v8 GC can run during the iteration and clear the reference, // we can't move this check out of the loop. m_wrappers.remove(i); continue; } v8::Local<v8::Object> wrapper = persistent->newLocal(m_isolate); ScriptState* scriptState = ScriptState::from(wrapper->CreationContext()); ScriptState::Scope scope(scriptState); v8::Local<v8::Promise::Resolver> resolver = V8HiddenValue::getHiddenValue(scriptState, wrapper, resolverName()).As<v8::Promise::Resolver>(); V8HiddenValue::deleteHiddenValue(scriptState, wrapper, resolverName()); resolveOrRejectInternal(resolver); ++i; } }
void MediaStream::addRemoteTrack(MediaStreamComponent* component) { DCHECK(component); if (m_stopped) return; MediaStreamTrack* track = MediaStreamTrack::create(getExecutionContext(), component); switch (component->source()->type()) { case MediaStreamSource::TypeAudio: m_audioTracks.append(track); break; case MediaStreamSource::TypeVideo: m_videoTracks.append(track); break; } track->registerMediaStream(this); m_descriptor->addComponent(component); scheduleDispatchEvent( MediaStreamTrackEvent::create(EventTypeNames::addtrack, track)); if (!active() && !track->ended()) { m_descriptor->setActive(true); scheduleDispatchEvent(Event::create(EventTypeNames::active)); } }
void MIDIAccess::sendMIDIData(unsigned portIndex, const unsigned char* data, size_t length, double timeStampInMilliseconds) { if (!data || !length || portIndex >= m_outputs.size()) return; // Convert from a time in milliseconds (a DOMHighResTimeStamp) according to // the same time coordinate system as performance.now() into a time in seconds // which is based on the time coordinate system of // monotonicallyIncreasingTime(). double timeStamp; if (!timeStampInMilliseconds) { // We treat a value of 0 (which is the default value) as special, meaning // "now". We need to translate it exactly to 0 seconds. timeStamp = 0; } else { Document* document = toDocument(getExecutionContext()); DCHECK(document); double documentStartTime = document->loader()->timing().referenceMonotonicTime(); timeStamp = documentStartTime + 0.001 * timeStampInMilliseconds; } m_accessor->sendMIDIData(portIndex, data, length, timeStamp); }
bool IDBTransaction::hasPendingActivity() const { // FIXME: In an ideal world, we should return true as long as anyone has a or // can get a handle to us or any child request object and any of those have // event listeners. This is in order to handle user generated events // properly. return m_hasPendingActivity && getExecutionContext(); }