#include "config.h"
#if ENABLE(VIDEO_TRACK)
#include "DataCue.h"
#include "Logging.h"
#include "TextTrack.h"
#include "TextTrackCueList.h"
#include <runtime/JSCInlines.h>
#include <runtime/Protect.h>
using namespace JSC;
namespace WebCore {
DataCue::DataCue(ScriptExecutionContext& context, const MediaTime& start, const MediaTime& end, ArrayBuffer& data, const String& type)
: TextTrackCue(context, start, end)
, m_type(type)
{
setData(data);
}
DataCue::DataCue(ScriptExecutionContext& context, const MediaTime& start, const MediaTime& end, const void* data, unsigned length)
: TextTrackCue(context, start, end)
, m_data(ArrayBuffer::create(data, length))
{
}
DataCue::DataCue(ScriptExecutionContext& context, const MediaTime& start, const MediaTime& end, RefPtr<SerializedPlatformRepresentation>&& platformValue, const String& type)
: TextTrackCue(context, start, end)
, m_type(type)
, m_platformValue(WTFMove(platformValue))
{
}
DataCue::DataCue(ScriptExecutionContext& context, const MediaTime& start, const MediaTime& end, JSC::JSValue value, const String& type)
: TextTrackCue(context, start, end)
, m_type(type)
, m_value(value)
{
if (m_value)
JSC::gcProtect(m_value);
}
DataCue::~DataCue()
{
if (m_value)
JSC::gcUnprotect(m_value);
}
RefPtr<ArrayBuffer> DataCue::data() const
{
if (m_platformValue)
return m_platformValue->data();
if (!m_data)
return nullptr;
return ArrayBuffer::create(*m_data);
}
void DataCue::setData(ArrayBuffer& data)
{
m_platformValue = nullptr;
if (m_value)
JSC::gcUnprotect(m_value);
m_value = JSC::JSValue();
m_data = ArrayBuffer::create(data);
}
DataCue* toDataCue(TextTrackCue* cue)
{
ASSERT_WITH_SECURITY_IMPLICATION(cue->cueType() == TextTrackCue::Data);
return static_cast<DataCue*>(cue);
}
const DataCue* toDataCue(const TextTrackCue* cue)
{
ASSERT_WITH_SECURITY_IMPLICATION(cue->cueType() == TextTrackCue::Data);
return static_cast<const DataCue*>(cue);
}
bool DataCue::cueContentsMatch(const TextTrackCue& cue) const
{
if (cue.cueType() != TextTrackCue::Data)
return false;
const DataCue* dataCue = toDataCue(&cue);
RefPtr<ArrayBuffer> otherData = dataCue->data();
if ((otherData && !m_data) || (!otherData && m_data))
return false;
if (m_data && m_data->byteLength() != otherData->byteLength())
return false;
if (m_data && m_data->data() && memcmp(m_data->data(), otherData->data(), m_data->byteLength()))
return false;
const SerializedPlatformRepresentation* otherPlatformValue = dataCue->platformValue();
if ((otherPlatformValue && !m_platformValue) || (!otherPlatformValue && m_platformValue))
return false;
if (m_platformValue && !m_platformValue->isEqual(*otherPlatformValue))
return false;
JSC::JSValue thisValue = valueOrNull();
JSC::JSValue otherValue = dataCue->valueOrNull();
if ((otherValue && !thisValue) || (!otherValue && thisValue))
return false;
if (!JSC::JSValue::strictEqual(nullptr, thisValue, otherValue))
return false;
return true;
}
bool DataCue::isEqual(const TextTrackCue& cue, TextTrackCue::CueMatchRules match) const
{
if (!TextTrackCue::isEqual(cue, match))
return false;
if (cue.cueType() != TextTrackCue::Data)
return false;
return cueContentsMatch(cue);
}
bool DataCue::doesExtendCue(const TextTrackCue& cue) const
{
if (!cueContentsMatch(cue))
return false;
return TextTrackCue::doesExtendCue(cue);
}
JSC::JSValue DataCue::value(JSC::ExecState& state) const
{
if (m_platformValue)
return m_platformValue->deserialize(&state);
if (m_value)
return m_value;
return JSC::jsNull();
}
void DataCue::setValue(JSC::ExecState&, JSC::JSValue value)
{
if (m_value)
JSC::gcUnprotect(m_value);
m_value = value;
if (m_value)
JSC::gcProtect(m_value);
m_platformValue = nullptr;
m_data = nullptr;
}
JSValue DataCue::valueOrNull() const
{
if (m_value)
return m_value;
return jsNull();
}
}
#endif