TEST_F(CrossThreadTaskTest, CreateForFunctionWithExecutionContext)
{
    OwnPtr<ExecutionContextTask> task1 = createCrossThreadTask(&functionWithExecutionContext, new GCObject);
    OwnPtr<ExecutionContextTask> task2 = createCrossThreadTask(&functionWithExecutionContext, RawPtr<GCObject>(new GCObject));
    Heap::collectGarbage(BlinkGC::NoHeapPointersOnStack, BlinkGC::GCWithSweep, BlinkGC::ForcedGC);
    EXPECT_EQ(2, GCObject::s_counter);
}
Пример #2
0
void UniqueIDBDatabase::performPutOrAdd(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyData& keyData, const ThreadSafeDataBuffer& valueData, IndexedDB::ObjectStoreOverwriteMode overwriteMode)
{
    ASSERT(!isMainThread());
    LOG(IndexedDB, "(db) UniqueIDBDatabase::performPutOrAdd");

    ASSERT(m_backingStore);
    ASSERT(objectStoreIdentifier);

    IDBKeyData usedKey;
    IDBError error;

    auto objectStoreInfo = m_databaseInfo->infoForExistingObjectStore(objectStoreIdentifier);
    if (!objectStoreInfo) {
        error = IDBError(IDBExceptionCode::InvalidStateError, ASCIILiteral("Object store cannot be found in the backing store"));
        m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, error, usedKey));
        return;
    }

    if (objectStoreInfo->autoIncrement() && !keyData.isValid()) {
        uint64_t keyNumber;
        error = m_backingStore->generateKeyNumber(transactionIdentifier, objectStoreIdentifier, keyNumber);
        if (!error.isNull()) {
            m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, error, usedKey));
            return;
        }
        
        usedKey.setNumberValue(keyNumber);
    } else
        usedKey = keyData;

    if (overwriteMode == IndexedDB::ObjectStoreOverwriteMode::NoOverwrite) {
        bool keyExists;
        error = m_backingStore->keyExistsInObjectStore(transactionIdentifier, objectStoreIdentifier, usedKey, keyExists);
        if (error.isNull() && keyExists)
            error = IDBError(IDBExceptionCode::ConstraintError, ASCIILiteral("Key already exists in the object store"));

        if (!error.isNull()) {
            m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, error, usedKey));
            return;
        }
    }

    // 3.4.1 Object Store Storage Operation
    // ...If a record already exists in store ...
    // then remove the record from store using the steps for deleting records from an object store...
    // This is important because formally deleting it from from the object store also removes it from the appropriate indexes.
    error = m_backingStore->deleteRange(transactionIdentifier, objectStoreIdentifier, usedKey);
    if (!error.isNull()) {
        m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, error, usedKey));
        return;
    }

    error = m_backingStore->addRecord(transactionIdentifier, objectStoreIdentifier, usedKey, valueData);

    m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, error, usedKey));
}
Пример #3
0
void UniqueIDBDatabase::getRecord(const IDBRequestData& requestData, const IDBKeyRangeData& range, GetResultCallback callback)
{
    ASSERT(isMainThread());
    LOG(IndexedDB, "(main) UniqueIDBDatabase::getRecord");

    uint64_t callbackID = storeCallback(callback);

    if (uint64_t indexIdentifier = requestData.indexIdentifier())
        m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performGetIndexRecord, callbackID, requestData.transactionIdentifier(), requestData.objectStoreIdentifier(), indexIdentifier, requestData.indexRecordType(), range));
    else
        m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performGetRecord, callbackID, requestData.transactionIdentifier(), requestData.objectStoreIdentifier(), range));
}
Пример #4
0
void WebSharedWorkerImpl::postMessageToPageInspector(const String& message) {
  m_mainFrame->frame()->document()->postInspectorTask(
      BLINK_FROM_HERE,
      createCrossThreadTask(
          &WebSharedWorkerImpl::postMessageToPageInspectorOnMainThread,
          crossThreadUnretained(this), message));
}
Пример #5
0
void Bridge::initialize(const String& sourceURL, unsigned lineNumber)
{
    if (!waitForMethodCompletion(createCrossThreadTask(&Peer::initialize, m_peer.get(), sourceURL, lineNumber))) {
        // The worker thread has been signalled to shutdown before method completion.
        disconnect();
    }
}
void WorkerMessagingProxy::disconnectFromInspector()
{
    m_pageInspector = 0;
    if (m_askedToTerminate)
        return;
    m_workerThread->postDebuggerTask(createCrossThreadTask(disconnectFromWorkerGlobalScopeInspectorTask, true));
}
Пример #7
0
// 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 WorkerMessagingProxy::sendMessageToInspector(const String& message)
{
    if (m_askedToTerminate)
        return;
    m_workerThread->postDebuggerTask(createCrossThreadTask(dispatchOnInspectorBackendTask, String(message)));
    m_workerThread->interruptAndDispatchInspectorCommands();
}
Пример #9
0
void UniqueIDBDatabase::performActivateTransactionInBackingStore(uint64_t callbackIdentifier, const IDBTransactionInfo& info)
{
    LOG(IndexedDB, "(db) UniqueIDBDatabase::performActivateTransactionInBackingStore");

    IDBError error = m_backingStore->beginTransaction(info);
    m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformActivateTransactionInBackingStore, callbackIdentifier, error));
}
Пример #10
0
void Database::runTransaction(
    SQLTransactionCallback* callback,
    SQLTransactionErrorCallback* errorCallback,
    VoidCallback* successCallback,
    bool readOnly,
    const ChangeVersionData* changeVersionData)
{
    // FIXME: Rather than passing errorCallback to SQLTransaction and then
    // sometimes firing it ourselves, this code should probably be pushed down
    // into Database so that we only create the SQLTransaction if we're
    // actually going to run it.
#if ENABLE(ASSERT)
    SQLTransactionErrorCallback* originalErrorCallback = errorCallback;
#endif
    SQLTransaction* transaction = SQLTransaction::create(this, callback, successCallback, errorCallback, readOnly);
    SQLTransactionBackend* transactionBackend = runTransaction(transaction, readOnly, changeVersionData);
    if (!transactionBackend) {
        SQLTransactionErrorCallback* callback = transaction->releaseErrorCallback();
        ASSERT(callback == originalErrorCallback);
        if (callback) {
            OwnPtr<SQLErrorData> error = SQLErrorData::create(SQLError::UNKNOWN_ERR, "database has been closed");
            executionContext()->postTask(createCrossThreadTask(&callTransactionErrorCallback, callback, error.release()));
        }
    }
}
Пример #11
0
void UniqueIDBDatabase::deleteRecord(const IDBRequestData& requestData, const IDBKeyRangeData& keyRangeData, ErrorCallback callback)
{
    ASSERT(isMainThread());
    LOG(IndexedDB, "(main) UniqueIDBDatabase::deleteRecord");

    uint64_t callbackID = storeCallback(callback);
    m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performDeleteRecord, callbackID, requestData.transactionIdentifier(), requestData.objectStoreIdentifier(), keyRangeData));
}
void AudioScheduledSourceHandler::finish()
{
    finishWithoutOnEnded();

    if (m_hasEndedListener && context()->executionContext()) {
        context()->executionContext()->postTask(FROM_HERE, createCrossThreadTask(&AudioScheduledSourceHandler::notifyEnded, PassRefPtr<AudioScheduledSourceHandler>(this)));
    }
}
void WorkerMessagingProxy::connectToInspector(WorkerGlobalScopeProxy::PageInspector* pageInspector)
{
    if (m_askedToTerminate)
        return;
    ASSERT(!m_pageInspector);
    m_pageInspector = pageInspector;
    m_workerThread->postDebuggerTask(createCrossThreadTask(connectToWorkerGlobalScopeInspectorTask, true));
}
Пример #14
0
void UniqueIDBDatabase::performAbortTransaction(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier)
{
    ASSERT(!isMainThread());
    LOG(IndexedDB, "(db) UniqueIDBDatabase::performAbortTransaction");

    IDBError error = m_backingStore->abortTransaction(transactionIdentifier);
    m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformAbortTransaction, callbackIdentifier, error, transactionIdentifier));
}
Пример #15
0
void UniqueIDBDatabase::getCount(const IDBRequestData& requestData, const IDBKeyRangeData& range, CountCallback callback)
{
    ASSERT(isMainThread());
    LOG(IndexedDB, "(main) UniqueIDBDatabase::getCount");

    uint64_t callbackID = storeCallback(callback);
    m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performGetCount, callbackID, requestData.transactionIdentifier(), requestData.objectStoreIdentifier(), requestData.indexIdentifier(), range));
}
Пример #16
0
void UniqueIDBDatabase::clearObjectStore(UniqueIDBDatabaseTransaction& transaction, uint64_t objectStoreIdentifier, ErrorCallback callback)
{
    ASSERT(isMainThread());
    LOG(IndexedDB, "(main) UniqueIDBDatabase::clearObjectStore");

    uint64_t callbackID = storeCallback(callback);
    m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performClearObjectStore, callbackID, transaction.info().identifier(), objectStoreIdentifier));
}
Пример #17
0
void UniqueIDBDatabase::createIndex(UniqueIDBDatabaseTransaction& transaction, const IDBIndexInfo& info, ErrorCallback callback)
{
    ASSERT(isMainThread());
    LOG(IndexedDB, "(main) UniqueIDBDatabase::createIndex");

    uint64_t callbackID = storeCallback(callback);
    m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performCreateIndex, callbackID, transaction.info().identifier(), info));
}
Пример #18
0
void UniqueIDBDatabase::putOrAdd(const IDBRequestData& requestData, const IDBKeyData& keyData, const ThreadSafeDataBuffer& valueData, IndexedDB::ObjectStoreOverwriteMode overwriteMode, KeyDataCallback callback)
{
    ASSERT(isMainThread());
    LOG(IndexedDB, "(main) UniqueIDBDatabase::putOrAdd");

    uint64_t callbackID = storeCallback(callback);
    m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performPutOrAdd, callbackID, requestData.transactionIdentifier(), requestData.objectStoreIdentifier(), keyData, valueData, overwriteMode));
}
void WorkerMessagingProxy::workerObjectDestroyed()
{
    // workerObjectDestroyed() is called in InProcessWorkerBase's destructor.
    // Thus it should be guaranteed that a weak pointer m_workerObject has been cleared
    // before this method gets called.
    ASSERT(!m_workerObject);

    m_executionContext->postTask(FROM_HERE, createCrossThreadTask(&WorkerMessagingProxy::workerObjectDestroyedInternal, this));
}
Пример #20
0
void UniqueIDBDatabase::performDeleteRecord(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyRangeData& range)
{
    ASSERT(!isMainThread());
    LOG(IndexedDB, "(db) UniqueIDBDatabase::performDeleteRecord");

    IDBError error = m_backingStore->deleteRange(transactionIdentifier, objectStoreIdentifier, range);

    m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformDeleteRecord, callbackIdentifier, error));
}
Пример #21
0
void MemoryCache::removeURLFromCache(ExecutionContext* context, const KURL& url)
{
    if (context->isWorkerGlobalScope()) {
        WorkerGlobalScope* workerGlobalScope = toWorkerGlobalScope(context);
        workerGlobalScope->thread()->workerLoaderProxy().postTaskToLoader(createCrossThreadTask(&removeURLFromCacheInternal, url));
        return;
    }
    removeURLFromCacheInternal(context, url);
}
Пример #22
0
void Bridge::send(const CString& message)
{
    ASSERT(m_peer);
    OwnPtr<Vector<char>> data = adoptPtr(new Vector<char>(message.length()));
    if (message.length())
        memcpy(data->data(), static_cast<const char*>(message.data()), message.length());

    m_loaderProxy->postTaskToLoader(createCrossThreadTask(&Peer::sendTextAsCharVector, m_peer.get(), data.release()));
}
Пример #23
0
void Peer::didClose(ClosingHandshakeCompletionStatus closingHandshakeCompletion, unsigned short code, const String& reason)
{
    ASSERT(isMainThread());
    if (m_mainWebSocketChannel) {
        m_mainWebSocketChannel->disconnect();
        m_mainWebSocketChannel = nullptr;
    }
    m_loaderProxy->postTaskToWorkerGlobalScope(createCrossThreadTask(&workerGlobalScopeDidClose, m_bridge, closingHandshakeCompletion, code, reason));
}
void WorkerThreadableLoader::MainThreadBridge::destroy()
{
    // Ensure that no more client callbacks are done in the worker context's thread.
    clearClientWrapper();

    // "delete this" and m_mainThreadLoader::deref() on the worker object's thread.
    m_loaderProxy->postTaskToLoader(
        createCrossThreadTask(&MainThreadBridge::mainThreadDestroy, this));
}
void OfflineAudioDestinationHandler::finishOfflineRendering()
{
    ASSERT(!isMainThread());

    // The actual rendering has been completed. Notify the context.
    if (context()->executionContext()) {
        context()->executionContext()->postTask(BLINK_FROM_HERE,
            createCrossThreadTask(&OfflineAudioDestinationHandler::notifyComplete, this));
    }
}
void WorkerMessagingProxy::writeTimelineStartedEvent(const String& sessionId)
{
    if (m_askedToTerminate)
        return;
    OwnPtr<ExecutionContextTask> task = createCrossThreadTask(dispatchWriteTimelineStartedEvent, String(sessionId));
    if (m_workerThread)
        m_workerThread->postTask(task.release());
    else
        m_queuedEarlyTasks.append(task.release());
}
Пример #27
0
void Bridge::send(const DOMArrayBuffer& binaryData, unsigned byteOffset, unsigned byteLength)
{
    ASSERT(m_peer);
    // ArrayBuffer isn't thread-safe, hence the content of ArrayBuffer is copied into Vector<char>.
    OwnPtr<Vector<char>> data = adoptPtr(new Vector<char>(byteLength));
    if (binaryData.byteLength())
        memcpy(data->data(), static_cast<const char*>(binaryData.data()) + byteOffset, byteLength);

    m_loaderProxy->postTaskToLoader(createCrossThreadTask(&Peer::sendBinaryAsCharVector, m_peer.get(), data.release()));
}
Пример #28
0
bool Bridge::connect(const KURL& url, const String& protocol)
{
    if (!m_peer)
        return false;

    if (!waitForMethodCompletion(createCrossThreadTask(&Peer::connect, m_peer.get(), url, protocol)))
        return false;

    return m_syncHelper->connectRequestResult();
}
Пример #29
0
void IDBServer::performCloseAndDeleteDatabasesModifiedSince(std::chrono::system_clock::time_point modifiedSince, uint64_t callbackID)
{
    if (!m_databaseDirectoryPath.isEmpty()) {
        Vector<String> originPaths = listDirectory(m_databaseDirectoryPath, "*");
        for (auto& originPath : originPaths)
            removeAllDatabasesForOriginPath(originPath, modifiedSince);
    }

    postDatabaseTaskReply(createCrossThreadTask(*this, &IDBServer::didPerformCloseAndDeleteDatabases, callbackID));
}
Пример #30
0
void AudioScheduledSourceHandler::finish() {
  finishWithoutOnEnded();

  if (context()->getExecutionContext()) {
    context()->getExecutionContext()->postTask(
        BLINK_FROM_HERE,
        createCrossThreadTask(&AudioScheduledSourceHandler::notifyEnded,
                              PassRefPtr<AudioScheduledSourceHandler>(this)));
  }
}