Esempio n. 1
0
void MessagePort::postMessage(RefPtr<SerializedScriptValue>&& message, MessagePort* port, ExceptionCode& ec)
{
    MessagePortArray ports;
    if (port)
        ports.append(port);
    postMessage(WTFMove(message), &ports, ec);
}
void fillMessagePortArray(JSC::ExecState* exec, JSC::JSValue value, MessagePortArray& portArray)
{
    // Convert from the passed-in JS array-like object to a MessagePortArray.
    // Also validates the elements per sections 4.1.13 and 4.1.15 of the WebIDL spec and section 8.3.3 of the HTML5 spec.
    if (value.isUndefinedOrNull()) {
        portArray.resize(0);
        return;
    }

    // Validation of sequence types, per WebIDL spec 4.1.13.
    unsigned length;
    JSObject* object = toJSSequence(exec, value, length);
    if (exec->hadException())
        return;

    portArray.resize(length);
    for (unsigned i = 0 ; i < length; ++i) {
        JSValue value = object->get(exec, i);
        if (exec->hadException())
            return;
        // Validation of non-null objects, per HTML5 spec 8.3.3.
        if (value.isUndefinedOrNull()) {
            setDOMException(exec, INVALID_STATE_ERR);
            return;
        }

        // Validation of Objects implementing an interface, per WebIDL spec 4.1.15.
        RefPtr<MessagePort> port = toMessagePort(value);
        if (!port) {
            throwTypeError(exec);
            return;
        }
        portArray[i] = port.release();
    }
}
Esempio n. 3
0
// FIXME: remove this when we update the ObjC bindings (bug #28774).
void Worker::postMessage(PassRefPtr<SerializedScriptValue> message, MessagePort* port, ExceptionCode& ec)
{
    MessagePortArray ports;
    if (port)
        ports.append(port);
    postMessage(message, &ports, ec);
}
void MessageEvent::initMessageEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<SerializedScriptValue> data, const String& origin, const String& lastEventId, DOMWindow* source, MessagePort* port)
{
    MessagePortArray* ports = 0;
    if (port) {
        ports = new MessagePortArray();
        ports->append(port);
    }
    initMessageEvent(type, canBubble, cancelable, data, origin, lastEventId, source, ports);
}
Esempio n. 5
0
JSValue JSMessageEvent::ports(ExecState* exec) const
{
    MessagePortArray* ports = static_cast<MessageEvent*>(impl())->ports();
    if (!ports)
        return constructEmptyArray(exec, globalObject());

    MarkedArgumentBuffer list;
    for (size_t i = 0; i < ports->size(); i++)
        list.append(toJS(exec, globalObject(), (*ports)[i].get()));
    return constructArray(exec, globalObject(), list);
}
void fillMessagePortArray(JSC::ExecState* exec, JSC::JSValue value, MessagePortArray& portArray, ArrayBufferArray& arrayBuffers)
{
    // Convert from the passed-in JS array-like object to a MessagePortArray.
    // Also validates the elements per sections 4.1.13 and 4.1.15 of the WebIDL spec and section 8.3.3 of the HTML5 spec.
    if (value.isUndefinedOrNull()) {
        portArray.resize(0);
        arrayBuffers.resize(0);
        return;
    }

    // Validation of sequence types, per WebIDL spec 4.1.13.
    unsigned length = 0;
    JSObject* object = toJSSequence(exec, value, length);
    if (exec->hadException())
        return;

    for (unsigned i = 0 ; i < length; ++i) {
        JSValue value = object->get(exec, i);
        if (exec->hadException())
            return;
        // Validation of non-null objects, per HTML5 spec 10.3.3.
        if (value.isUndefinedOrNull()) {
            setDOMException(exec, INVALID_STATE_ERR);
            return;
        }

        // Validation of Objects implementing an interface, per WebIDL spec 4.1.15.
        RefPtr<MessagePort> port = toMessagePort(value);
        if (port) {
            // Check for duplicate ports.
            if (portArray.contains(port)) {
#if MODIFY(ENGINE) //[2014.03.05][infraware][jungong16] : fix to issue. http://www.w3.org/TR/webmessaging/#dom-window-postmessage
                setDOMException(exec, DATA_CLONE_ERR);
#else
                setDOMException(exec, INVALID_STATE_ERR);
#endif
                return;
            }
            portArray.append(port.release());
        } else {
            RefPtr<ArrayBuffer> arrayBuffer = toArrayBuffer(value);
            if (arrayBuffer)
                arrayBuffers.append(arrayBuffer);
            else {
                throwTypeError(exec);
                return;
            }
        }
    }
}
bool extractTransferables(v8::Local<v8::Value> value, int argumentIndex, MessagePortArray& ports, ArrayBufferArray& arrayBuffers, ExceptionState& exceptionState, v8::Isolate* isolate)
{
    if (isUndefinedOrNull(value)) {
        ports.resize(0);
        arrayBuffers.resize(0);
        return true;
    }

    uint32_t length = 0;
    if (value->IsArray()) {
        v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(value);
        length = array->Length();
    } else if (toV8Sequence(value, length, isolate).IsEmpty()) {
        exceptionState.throwTypeError(ExceptionMessages::notAnArrayTypeArgumentOrValue(argumentIndex + 1));
        return false;
    }

    v8::Local<v8::Object> transferrables = v8::Local<v8::Object>::Cast(value);

    // Validate the passed array of transferrables.
    for (unsigned int i = 0; i < length; ++i) {
        v8::Local<v8::Value> transferrable = transferrables->Get(i);
        // Validation of non-null objects, per HTML5 spec 10.3.3.
        if (isUndefinedOrNull(transferrable)) {
            exceptionState.throwDOMException(DataCloneError, "Value at index " + String::number(i) + " is an untransferable " + (transferrable->IsUndefined() ? "'undefined'" : "'null'") + " value.");
            return false;
        }
        // Validation of Objects implementing an interface, per WebIDL spec 4.1.15.
        if (V8MessagePort::hasInstance(transferrable, isolate)) {
            RefPtr<MessagePort> port = V8MessagePort::toNative(v8::Handle<v8::Object>::Cast(transferrable));
            // Check for duplicate MessagePorts.
            if (ports.contains(port)) {
                exceptionState.throwDOMException(DataCloneError, "Message port at index " + String::number(i) + " is a duplicate of an earlier port.");
                return false;
            }
            ports.append(port.release());
        } else if (V8ArrayBuffer::hasInstance(transferrable, isolate)) {
            RefPtr<ArrayBuffer> arrayBuffer = V8ArrayBuffer::toNative(v8::Handle<v8::Object>::Cast(transferrable));
            if (arrayBuffers.contains(arrayBuffer)) {
                exceptionState.throwDOMException(DataCloneError, "ArrayBuffer at index " + String::number(i) + " is a duplicate of an earlier ArrayBuffer.");
                return false;
            }
            arrayBuffers.append(arrayBuffer.release());
        } else {
            exceptionState.throwDOMException(DataCloneError, "Value at index " + String::number(i) + " does not have a transferable type.");
            return false;
        }
    }
    return true;
}
v8::Handle<v8::Value> V8MessageEvent::portsAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
{
    INC_STATS("DOM.MessageEvent.ports");
    MessageEvent* event = V8MessageEvent::toNative(info.Holder());

    MessagePortArray* ports = event->ports();
    if (!ports || ports->isEmpty())
        return v8::Null();

    v8::Local<v8::Array> portArray = v8::Array::New(ports->size());
    for (size_t i = 0; i < ports->size(); ++i)
        portArray->Set(v8::Integer::New(i), toV8((*ports)[i].get()));

    return portArray;
}
Esempio n. 9
0
bool extractTransferables(v8::Local<v8::Value> value, MessagePortArray& ports, ArrayBufferArray& arrayBuffers)
{
    if (isUndefinedOrNull(value)) {
        ports.resize(0);
        arrayBuffers.resize(0);
        return true;
    }

    if (!value->IsObject()) {
        throwError("TransferArray argument must be an object");
        return false;
    }
    uint32_t length = 0;
    v8::Local<v8::Object> transferrables = v8::Local<v8::Object>::Cast(value);

    if (value->IsArray()) {
        v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(value);
        length = array->Length();
    } else {
        // Sequence-type object - get the length attribute
        v8::Local<v8::Value> sequenceLength = transferrables->Get(v8::String::New("length"));
        if (!sequenceLength->IsNumber()) {
            throwError("TransferArray argument has no length attribute");
            return false;
        }
        length = sequenceLength->Uint32Value();
    }

    // Validate the passed array of transferrables.
    for (unsigned int i = 0; i < length; ++i) {
        v8::Local<v8::Value> transferrable = transferrables->Get(i);
        // Validation of non-null objects, per HTML5 spec 10.3.3.
        if (isUndefinedOrNull(transferrable)) {
            throwError(DATA_CLONE_ERR);
            return false;
        }
        // Validation of Objects implementing an interface, per WebIDL spec 4.1.15.
        if (V8MessagePort::HasInstance(transferrable))
            ports.append(V8MessagePort::toNative(v8::Handle<v8::Object>::Cast(transferrable)));
        else if (V8ArrayBuffer::HasInstance(transferrable))
            arrayBuffers.append(V8ArrayBuffer::toNative(v8::Handle<v8::Object>::Cast(transferrable)));
        else {
            throwError("TransferArray argument must contain only Transferables");
            return false;
        }
    }
    return true;
}
Esempio n. 10
0
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());
}
Esempio n. 11
0
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
  // Odd sizes are handled in various ways, depending how they arrive.
  // Let's not worry about that case here.
  if (size % sizeof(UChar))
    return 0;

  // Used to control what kind of extra data is provided to the deserializer.
  unsigned hash = StringHasher::hashMemory(data, size);

  // If message ports are requested, make some.
  MessagePortArray* messagePorts = nullptr;
  if (hash & kFuzzMessagePorts) {
    messagePorts = new MessagePortArray(3);
    std::generate(messagePorts->begin(), messagePorts->end(), []() {
      WebMessagePortChannelUniquePtr channel(new WebMessagePortChannelImpl());
      MessagePort* port = MessagePort::create(pageHolder->document());
      port->entangle(std::move(channel));
      return port;
    });
  }

  // If blobs are requested, supply blob info.
  const auto* blobs = (hash & kFuzzBlobInfo) ? blobInfoArray : nullptr;

  // Set up.
  ScriptState* scriptState = ScriptState::forMainWorld(&pageHolder->frame());
  v8::Isolate* isolate = scriptState->isolate();
  ScriptState::Scope scope(scriptState);
  v8::TryCatch tryCatch(isolate);

  // Deserialize.
  RefPtr<SerializedScriptValue> serializedScriptValue =
      SerializedScriptValue::create(reinterpret_cast<const char*>(data), size);
  serializedScriptValue->deserialize(isolate, messagePorts, blobs);
  CHECK(!tryCatch.HasCaught())
      << "deserialize() should return null rather than throwing an exception.";

  // Clean up. We have to periodically run pending tasks so that scheduled
  // Oilpan GC occurs.
  static int iterations = 0;
  if (iterations++ == 2048) {
    testing::runPendingTasks();
    iterations = 0;
  }

  return 0;
}
void fillMessagePortArray(JSC::ExecState* exec, JSC::JSValue value, MessagePortArray& portArray, ArrayBufferArray& arrayBuffers)
{
    // Convert from the passed-in JS array-like object to a MessagePortArray.
    // Also validates the elements per sections 4.1.13 and 4.1.15 of the WebIDL spec and section 8.3.3 of the HTML5 spec.
    if (value.isUndefinedOrNull()) {
        portArray.resize(0);
        arrayBuffers.resize(0);
        return;
    }

    // Validation of sequence types, per WebIDL spec 4.1.13.
    unsigned length = 0;
    JSObject* object = toJSSequence(exec, value, length);
    if (exec->hadException())
        return;

    for (unsigned i = 0 ; i < length; ++i) {
        JSValue value = object->get(exec, i);
        if (exec->hadException())
            return;
        // Validation of non-null objects, per HTML5 spec 10.3.3.
        if (value.isUndefinedOrNull()) {
            setDOMException(exec, INVALID_STATE_ERR);
            return;
        }

        // Validation of Objects implementing an interface, per WebIDL spec 4.1.15.
        RefPtr<MessagePort> port = JSMessagePort::toWrapped(value);
        if (port) {
            // Check for duplicate ports.
            if (portArray.contains(port)) {
                setDOMException(exec, INVALID_STATE_ERR);
                return;
            }
            portArray.append(port.release());
        } else {
            RefPtr<ArrayBuffer> arrayBuffer = toArrayBuffer(value);
            if (arrayBuffer)
                arrayBuffers.append(arrayBuffer);
            else {
                throwTypeError(exec);
                return;
            }
        }
    }
}
Esempio n. 13
0
bool extractTransferables(v8::Local<v8::Value> value, MessagePortArray& ports, ArrayBufferArray& arrayBuffers, v8::Isolate* isolate)
{
    if (isUndefinedOrNull(value)) {
        ports.resize(0);
        arrayBuffers.resize(0);
        return true;
    }

    uint32_t length = 0;
    if (value->IsArray()) {
        v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(value);
        length = array->Length();
    } else {
        if (toV8Sequence(value, length).IsEmpty())
            return false;
    }

    v8::Local<v8::Object> transferrables = v8::Local<v8::Object>::Cast(value);

    // Validate the passed array of transferrables.
    for (unsigned int i = 0; i < length; ++i) {
        v8::Local<v8::Value> transferrable = transferrables->Get(i);
        // Validation of non-null objects, per HTML5 spec 10.3.3.
        if (isUndefinedOrNull(transferrable)) {
            setDOMException(INVALID_STATE_ERR, isolate);
            return false;
        }
        // Validation of Objects implementing an interface, per WebIDL spec 4.1.15.
        if (V8MessagePort::HasInstance(transferrable)) {
            RefPtr<MessagePort> port = V8MessagePort::toNative(v8::Handle<v8::Object>::Cast(transferrable));
            // Check for duplicate MessagePorts.
            if (ports.contains(port)) {
                setDOMException(INVALID_STATE_ERR, isolate);
                return false;
            }
            ports.append(port.release());
        } else if (V8ArrayBuffer::HasInstance(transferrable))
            arrayBuffers.append(V8ArrayBuffer::toNative(v8::Handle<v8::Object>::Cast(transferrable)));
        else {
            throwTypeError();
            return false;
        }
    }
    return true;
}
bool getMessagePortArray(v8::Local<v8::Value> value, MessagePortArray& portArray)
{
    if (isUndefinedOrNull(value)) {
        portArray.resize(0);
        return true;
    }

    if (!value->IsObject()) {
        throwError("MessagePortArray argument must be an object");
        return false;
    }
    uint32_t length = 0;
    v8::Local<v8::Object> ports = v8::Local<v8::Object>::Cast(value);

    if (value->IsArray()) {
        v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(value);
        length = array->Length();
    } else {
        // Sequence-type object - get the length attribute
        v8::Local<v8::Value> sequenceLength = ports->Get(v8::String::New("length"));
        if (!sequenceLength->IsNumber()) {
            throwError("MessagePortArray argument has no length attribute");
            return false;
        }
        length = sequenceLength->Uint32Value();
    }
    portArray.resize(length);

    for (unsigned int i = 0; i < length; ++i) {
        v8::Local<v8::Value> port = ports->Get(v8::Integer::New(i));
        // Validation of non-null objects, per HTML5 spec 8.3.3.
        if (isUndefinedOrNull(port)) {
            throwError(INVALID_STATE_ERR);
            return false;
        }
        // Validation of Objects implementing an interface, per WebIDL spec 4.1.15.
        if (!V8MessagePort::HasInstance(port)) {
            throwError("MessagePortArray argument must contain only MessagePorts");
            return false;
        }
        portArray[i] = V8DOMWrapper::convertToNativeObject<MessagePort>(V8ClassIndex::MESSAGEPORT, v8::Handle<v8::Object>::Cast(port));
    }
    return true;
}
Esempio n. 15
0
std::unique_ptr<MessagePortChannelArray> MessagePort::disentanglePorts(
    ExecutionContext* context,
    const MessagePortArray& ports,
    ExceptionState& exceptionState) {
  if (!ports.size())
    return nullptr;

  HeapHashSet<Member<MessagePort>> visited;

  // Walk the incoming array - if there are any duplicate ports, or null ports
  // or cloned ports, throw an error (per section 8.3.3 of the HTML5 spec).
  for (unsigned i = 0; i < ports.size(); ++i) {
    MessagePort* port = ports[i];
    if (!port || port->isNeutered() || visited.contains(port)) {
      String type;
      if (!port)
        type = "null";
      else if (port->isNeutered())
        type = "already neutered";
      else
        type = "a duplicate";
      exceptionState.throwDOMException(
          DataCloneError,
          "Port at index " + String::number(i) + " is " + type + ".");
      return nullptr;
    }
    visited.add(port);
  }

  UseCounter::count(context, UseCounter::MessagePortsTransferred);

  // Passed-in ports passed validity checks, so we can disentangle them.
  std::unique_ptr<MessagePortChannelArray> portArray =
      wrapUnique(new MessagePortChannelArray(ports.size()));
  for (unsigned i = 0; i < ports.size(); ++i)
    (*portArray)[i] = ports[i]->disentangle();
  return portArray;
}
Esempio n. 16
0
bool getMessagePortArray(v8::Local<v8::Value> value, const String& propertyName, MessagePortArray& ports, v8::Isolate* isolate)
{
    if (isUndefinedOrNull(value)) {
        ports.resize(0);
        return true;
    }
    if (!value->IsArray()) {
        throwTypeError(ExceptionMessages::notASequenceTypeProperty(propertyName), isolate);
        return false;
    }
    bool success = false;
    ports = toRefPtrNativeArray<MessagePort, V8MessagePort>(value, propertyName, isolate, &success);
    return success;
}
Esempio n. 17
0
bool getMessagePortArray(v8::Local<v8::Value> value, int argumentIndex, MessagePortArray& ports, v8::Isolate* isolate)
{
    if (isUndefinedOrNull(value)) {
        ports.resize(0);
        return true;
    }
    if (!value->IsArray()) {
        throwTypeError(ExceptionMessages::notAnArrayTypeArgumentOrValue(argumentIndex), isolate);
        return false;
    }
    bool success = false;
    ports = toRefPtrNativeArray<MessagePort, V8MessagePort>(value, argumentIndex, isolate, &success);
    return success;
}