⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 94011 in webkit


Ignore:
Timestamp:
Aug 29, 2011, 1:47:06 PM (15 years ago)
Author:
commit-queue@webkit.org
Message:

Implement WebVTT Cue Text Parsing rules and DOM construction
https://bugs.webkit.org/show_bug.cgi?id=64132

Patch by Anna Cavender <annacc@chromium.org> on 2011-08-29
Reviewed by Adam Barth.

Tests in media/track, particularly track-webvtt-tc[022 - 028]*.

  • CMakeLists.txt:
  • GNUmakefile.list.am:
  • WebCore.gypi:
  • WebCore.pro:
  • WebCore.xcodeproj/project.pbxproj:
  • html/TextTrackCue.cpp:
  • html/TextTrackCue.h:
  • platform/track/CueParser.cpp:
  • platform/track/CueParser.h:
  • platform/track/WebVTTParser.cpp:
  • platform/track/WebVTTParser.h:
  • platform/track/WebVTTToken.h: Added.
  • platform/track/WebVTTTokenizer.cpp: Added.
  • platform/track/WebVTTTokenizer.h: Added.
Location:
trunk/Source/WebCore
Files:
2 added
12 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/CMakeLists.txt

    r93744 r94011  
    20402040        platform/track/CueParser.cpp
    20412041        platform/track/WebVTTParser.cpp
     2042        platform/track/WebVTTTokenizer.cpp
    20422043    )
    20432044ENDIF()
  • trunk/Source/WebCore/ChangeLog

    r94010 r94011  
     12011-08-29  Anna Cavender  <annacc@chromium.org>
     2
     3        Implement WebVTT Cue Text Parsing rules and DOM construction
     4        https://bugs.webkit.org/show_bug.cgi?id=64132
     5
     6        Reviewed by Adam Barth.
     7
     8        Tests in media/track, particularly track-webvtt-tc[022 - 028]*.
     9
     10        * CMakeLists.txt:
     11        * GNUmakefile.list.am:
     12        * WebCore.gypi:
     13        * WebCore.pro:
     14        * WebCore.xcodeproj/project.pbxproj:
     15        * html/TextTrackCue.cpp:
     16        * html/TextTrackCue.h:
     17        * platform/track/CueParser.cpp:
     18        * platform/track/CueParser.h:
     19        * platform/track/WebVTTParser.cpp:
     20        * platform/track/WebVTTParser.h:
     21        * platform/track/WebVTTToken.h: Added.
     22        * platform/track/WebVTTTokenizer.cpp: Added.
     23        * platform/track/WebVTTTokenizer.h: Added.
     24
    1252011-08-29  Patrick Gansterer  <paroga@webkit.org>
    226
  • trunk/Source/WebCore/GNUmakefile.list.am

    r93951 r94011  
    28762876        Source/WebCore/platform/track/WebVTTParser.cpp \
    28772877        Source/WebCore/platform/track/WebVTTParser.h \
     2878        Source/WebCore/platform/track/WebVTTToken.h \
     2879        Source/WebCore/platform/track/WebVTTTokenizer.h \
     2880        Source/WebCore/platform/track/WebVTTTokenizer.cpp \
    28782881        Source/WebCore/platform/TreeShared.h \
    28792882        Source/WebCore/platform/URLString.h \
  • trunk/Source/WebCore/WebCore.gypi

    r93951 r94011  
    43954395            'platform/track/WebVTTParser.cpp',
    43964396            'platform/track/WebVTTParser.h',
     4397            'platform/track/WebVTTToken.h',
     4398            'platform/track/WebVTTTokenizer.cpp',
     4399            'platform/track/WebVTTTokenizer.h',
    43974400            'platform/win/BString.cpp',
    43984401            'platform/win/BString.h',
  • trunk/Source/WebCore/WebCore.pro

    r93951 r94011  
    21222122    platform/track/CueParserPrivate.h \
    21232123    platform/track/WebVTTParser.h \
     2124    platform/track/WebVTTToken.h \
     2125    platform/track/WebVTTTokenizer.h \
    21242126    platform/Widget.h \
    21252127    platform/PlatformStrategies.h \
  • trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj

    r93980 r94011  
    40914091                ABDDFE7A0A5C6E7000A3E11D /* RenderMenuList.h in Headers */ = {isa = PBXBuildFile; fileRef = ABDDFE740A5C6E7000A3E11D /* RenderMenuList.h */; };
    40924092                ADDF1AD71257CD9A0003A759 /* RenderSVGPath.h in Headers */ = {isa = PBXBuildFile; fileRef = ADDF1AD51257CD9A0003A759 /* RenderSVGPath.h */; };
     4093                B10B6980140C174000BC1C26 /* WebVTTToken.h in Headers */ = {isa = PBXBuildFile; fileRef = B10B697D140C174000BC1C26 /* WebVTTToken.h */; };
     4094                B10B6981140C174000BC1C26 /* WebVTTTokenizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B10B697E140C174000BC1C26 /* WebVTTTokenizer.cpp */; };
     4095                B10B6982140C174000BC1C26 /* WebVTTTokenizer.h in Headers */ = {isa = PBXBuildFile; fileRef = B10B697F140C174000BC1C26 /* WebVTTTokenizer.h */; };
    40934096                B14353D5138EA8ED00D53276 /* MediaStreamList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B14353D1138EA8ED00D53276 /* MediaStreamList.cpp */; };
    40944097                B14353D6138EA8ED00D53276 /* MediaStreamList.h in Headers */ = {isa = PBXBuildFile; fileRef = B14353D2138EA8ED00D53276 /* MediaStreamList.h */; };
     
    1063310636                ADDF1AD41257CD9A0003A759 /* RenderSVGPath.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderSVGPath.cpp; sourceTree = "<group>"; };
    1063410637                ADDF1AD51257CD9A0003A759 /* RenderSVGPath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderSVGPath.h; sourceTree = "<group>"; };
     10638                B10B697D140C174000BC1C26 /* WebVTTToken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebVTTToken.h; path = platform/track/WebVTTToken.h; sourceTree = "<group>"; };
     10639                B10B697E140C174000BC1C26 /* WebVTTTokenizer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WebVTTTokenizer.cpp; path = platform/track/WebVTTTokenizer.cpp; sourceTree = "<group>"; };
     10640                B10B697F140C174000BC1C26 /* WebVTTTokenizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebVTTTokenizer.h; path = platform/track/WebVTTTokenizer.h; sourceTree = "<group>"; };
    1063510641                B14353D1138EA8ED00D53276 /* MediaStreamList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MediaStreamList.cpp; sourceTree = "<group>"; };
    1063610642                B14353D2138EA8ED00D53276 /* MediaStreamList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaStreamList.h; sourceTree = "<group>"; };
     
    1297612982                                65C97AF208EA908800ACD273 /* config.h */,
    1297712983                                EDEC98020AED7E170059137F /* WebCorePrefix.h */,
     12984                                B10B697D140C174000BC1C26 /* WebVTTToken.h */,
     12985                                B10B697E140C174000BC1C26 /* WebVTTTokenizer.cpp */,
     12986                                B10B697F140C174000BC1C26 /* WebVTTTokenizer.h */,
    1297812987                                9307061309E0CA8200B17FE4 /* DerivedSources.make */,
    1297912988                                93F19B1908245E59001E9ABC /* Info.plist */,
     
    2344023449                                D0A3A7311405A39800FB8ED3 /* ResourceLoaderOptions.h in Headers */,
    2344123450                                BCE43897140B0051005E437E /* EventConstructors.h in Headers */,
     23451                                B10B6980140C174000BC1C26 /* WebVTTToken.h in Headers */,
     23452                                B10B6982140C174000BC1C26 /* WebVTTTokenizer.h in Headers */,
    2344223453                        );
    2344323454                        runOnlyForDeploymentPostprocessing = 0;
     
    2624926260                                DF9AFD7313FC31D80015FEB7 /* MediaPlayerPrivateAVFoundationObjC.mm in Sources */,
    2625026261                                BCE4389A140B0073005E437E /* JSEventConstructors.cpp in Sources */,
     26262                                B10B6981140C174000BC1C26 /* WebVTTTokenizer.cpp in Sources */,
    2625126263                        );
    2625226264                        runOnlyForDeploymentPostprocessing = 0;
  • trunk/Source/WebCore/html/TextTrackCue.cpp

    r92538 r94011  
    4242namespace WebCore {
    4343
    44 TextTrackCue::TextTrackCue(const String& id, double start, double end, const String& content, const String& settings, bool pauseOnExit)
    45     : m_id(id)
     44TextTrackCue::TextTrackCue(ScriptExecutionContext* context, const String& id, double start, double end, const String& content, const String& settings, bool pauseOnExit)
     45    : ActiveDOMObject(context, this)
     46    , m_id(id)
    4647    , m_startTime(start)
    4748    , m_endTime(end)
     
    128129PassRefPtr<DocumentFragment> TextTrackCue::getCueAsHTML()
    129130{
    130     // FIXME(62883): Implement.
    131     return DocumentFragment::create(0);
     131    return m_documentFragment;
     132}
     133
     134void TextTrackCue::setCueHTML(PassRefPtr<DocumentFragment> fragment)
     135{
     136    m_documentFragment = fragment;
    132137}
    133138
     
    141146{
    142147    m_isActive = active;
     148}
     149
     150ScriptExecutionContext* TextTrackCue::scriptExecutionContext() const
     151{
     152    return ActiveDOMObject::scriptExecutionContext();
    143153}
    144154
     
    149159    unsigned position = 0;
    150160    while (position < input.length()) {
     161        // Discard any space characters between or after settings (not in the spec, but we think it should be).
     162        while (position < input.length() && WebVTTParser::isASpace(input[position]))
     163            position++;
     164
    151165        // 2-4 Settings - get the next character representing a settings.
    152166        char setting = input[position++];
     
    286300        }
    287301
    288         // Discard any remaining space characters between or after settings (not in the spec, but we think it should be).
    289         while (position < input.length() && WebVTTParser::isASpace(input[position]))
    290             position++;
    291302        continue;
    292303
  • trunk/Source/WebCore/html/TextTrackCue.h

    r92538 r94011  
    3434#if ENABLE(VIDEO_TRACK)
    3535
     36#include "ActiveDOMObject.h"
    3637#include "TextTrack.h"
    3738#include <wtf/PassOwnPtr.h>
     
    4142
    4243class DocumentFragment;
     44class ScriptExecutionContext;
    4345class TextTrack;
    4446
    45 class TextTrackCue : public RefCounted<TextTrackCue> {
     47class TextTrackCue : public RefCounted<TextTrackCue>, public ActiveDOMObject {
    4648public:
    47     static PassRefPtr<TextTrackCue> create(const String& id, double start, double end, const String& content, const String& settings, bool pauseOnExit)
     49    static PassRefPtr<TextTrackCue> create(ScriptExecutionContext* context, const String& id, double start, double end, const String& content, const String& settings, bool pauseOnExit)
    4850    {
    49         return adoptRef(new TextTrackCue(id, start, end, content, settings, pauseOnExit));
     51        return adoptRef(new TextTrackCue(context, id, start, end, content, settings, pauseOnExit));
    5052    }
    5153   
     
    7274    String getCueAsSource();
    7375    PassRefPtr<DocumentFragment> getCueAsHTML();
     76    void setCueHTML(PassRefPtr<DocumentFragment>);
    7477
    7578    bool isActive();
    7679    void setIsActive(bool);
     80   
     81    virtual ScriptExecutionContext* scriptExecutionContext() const;
    7782
    7883private:
    79     TextTrackCue(const String& id, double start, double end, const String& content, const String& settings, bool pauseOnExit);
     84    TextTrackCue(ScriptExecutionContext*, const String& id, double start, double end, const String& content, const String& settings, bool pauseOnExit);
    8085
    8186    void parseSettings(const String&);
     
    9499    int m_cueSize;
    95100    Alignment m_cueAlignment;
     101    RefPtr<DocumentFragment> m_documentFragment;
    96102
    97103    bool m_isActive;
  • trunk/Source/WebCore/platform/track/CueParser.cpp

    r93899 r94011  
    6262
    6363    m_client = client;
     64    m_scriptExecutionContext = context;
    6465
    6566    m_loader = ThreadableLoader::create(context, this, request, options);
     
    111112{
    112113    if (!m_private) {
    113         m_private = WebVTTParser::create(this);
     114        m_private = WebVTTParser::create(this, m_scriptExecutionContext);
    114115        m_client->trackLoadStarted();
    115116    }
  • trunk/Source/WebCore/platform/track/CueParser.h

    r92538 r94011  
    7070    void newCuesParsed();
    7171
     72protected:
     73    ScriptExecutionContext* m_scriptExecutionContext;
     74
    7275private:
    7376    void createWebVTTParser();
  • trunk/Source/WebCore/platform/track/WebVTTParser.cpp

    r92538 r94011  
    3535#include "WebVTTParser.h"
    3636
     37#include "HTMLElement.h"
     38#include "ProcessingInstruction.h"
     39#include "SegmentedString.h"
     40#include "Text.h"
    3741#include <wtf/text/WTFString.h>
    3842
     
    7983}
    8084
    81 WebVTTParser::WebVTTParser(CueParserPrivateClient* client)
    82     : m_state(Initial)
     85WebVTTParser::WebVTTParser(CueParserPrivateClient* client, ScriptExecutionContext* context)
     86    : m_scriptExecutionContext(context)
     87    , m_state(Initial)
     88    , m_tokenizer(WebVTTTokenizer::create())
    8389{
    8490    m_client = client;
     
    205211void WebVTTParser::processCueText()
    206212{
    207     // 51 - Cue text processing based on WebVTT cue text parsing rules and WebVTT cue text DOM construction rules.
    208     // FIXME(64132): Process the cue text as per the cue text parsing rules.
    209     //     Source: http://www.whatwg.org/specs/web-apps/current-work/multipage/the-iframe-element.html#webvtt-cue-text-parsing-rules
    210     RefPtr<TextTrackCue> cue = TextTrackCue::create(m_currentId, m_currentStartTime, m_currentEndTime, m_currentContent.toString(), m_currentSettings, false);
     213    // 51 - Cue text processing based on
     214    // 4.8.10.13.4 WebVTT cue text parsing rules and
     215    // 4.8.10.13.5 WebVTT cue text DOM construction rules.
     216    if (m_currentContent.length() <= 0)
     217        return;
     218
     219    ASSERT(m_scriptExecutionContext->isDocument());
     220    Document* document = static_cast<Document*>(m_scriptExecutionContext);
     221
     222    m_attachmentRoot = DocumentFragment::create(document);
     223    m_currentNode = m_attachmentRoot;
     224    m_tokenizer->reset();
     225    m_token.clear();
     226
     227    SegmentedString content(m_currentContent.toString());
     228    while (m_tokenizer->nextToken(content, m_token))
     229        constructTreeFromToken(document);
     230   
     231    RefPtr<TextTrackCue> cue = TextTrackCue::create(m_scriptExecutionContext, m_currentId, m_currentStartTime, m_currentEndTime, m_currentContent.toString(), m_currentSettings, false);
     232    cue->setCueHTML(m_attachmentRoot);
    211233    m_cuelist.append(cue);
    212234    m_client->newCuesParsed();
     
    282304}
    283305
     306void WebVTTParser::constructTreeFromToken(Document* document)
     307{
     308    AtomicString tokenTagName(m_token.name().data(), m_token.name().size());
     309    QualifiedName tagName(nullAtom, tokenTagName, xhtmlNamespaceURI);
     310
     311    switch (m_token.type()) {
     312    case WebVTTTokenTypes::Character: {
     313        String content(m_token.characters().data(), m_token.characters().size());
     314        RefPtr<Text> child = Text::create(document, content);
     315        m_currentNode->parserAddChild(child);
     316        break;
     317    }
     318    case WebVTTTokenTypes::StartTag: {
     319        RefPtr<HTMLElement> child;
     320        if (isRecognizedTag(tokenTagName))
     321            child = HTMLElement::create(tagName, document);
     322        else if (m_token.name().size() == 1 && m_token.name()[0] == 'c')
     323            child = HTMLElement::create(spanTag, document);
     324        else if (m_token.name().size() == 1 && m_token.name()[0] == 'v')
     325            child = HTMLElement::create(qTag, document);
     326
     327        if (child) {
     328            if (m_token.classes().size() > 0) {
     329                RefPtr<NamedNodeMap> attributeMap = NamedNodeMap::create();
     330                attributeMap->addAttribute(Attribute::createMapped(classAttr, AtomicString(m_token.classes().data(), m_token.classes().size())));
     331                child->setAttributeMap(attributeMap.release());
     332            }
     333            if (child->hasTagName(qTag))
     334                child->setAttribute(titleAttr, String(m_token.annotation().data(), m_token.annotation().size()));
     335            m_currentNode->parserAddChild(child);
     336            m_currentNode = child;
     337        }
     338        break;
     339    }
     340    case WebVTTTokenTypes::EndTag:
     341        if (isRecognizedTag(tokenTagName)
     342            || m_token.name().size() == 1 && m_token.name()[0] == 'c'
     343            || m_token.name().size() == 1 && m_token.name()[0] == 'v')
     344            if (m_currentNode->parentNode())
     345                m_currentNode = m_currentNode->parentNode();
     346        break;
     347    case WebVTTTokenTypes::TimestampTag: {
     348        unsigned position = 0;
     349        double time = collectTimeStamp(m_token.characters().data(), &position);
     350        if (time != malformedTime)
     351            m_currentNode->parserAddChild(ProcessingInstruction::create(document, "timestamp", String(m_token.characters().data(), m_token.characters().size())));
     352        break;
     353    }
     354    default:
     355        break;
     356    }
     357    m_token.clear();
     358}
     359
    284360void WebVTTParser::skipWhiteSpace(const String& line, unsigned* position)
    285361{
  • trunk/Source/WebCore/platform/track/WebVTTParser.h

    r92538 r94011  
    3535
    3636#include "CueParserPrivate.h"
     37#include "Document.h"
     38#include "DocumentFragment.h"
     39#include "HTMLNames.h"
     40#include "WebVTTTokenizer.h"
    3741#include <wtf/PassOwnPtr.h>
    3842#include <wtf/text/StringBuilder.h>
    3943
    4044namespace WebCore {
     45
     46using namespace HTMLNames;
    4147
    4248static const int secondsPerHour = 3600;
     
    5056    enum ParseState { Initial, Header, Id, TimingsAndSettings, CueText, BadCue };
    5157
    52     static PassOwnPtr<WebVTTParser> create(CueParserPrivateClient* client)
     58    static PassOwnPtr<WebVTTParser> create(CueParserPrivateClient* client, ScriptExecutionContext* context)
    5359    {
    54         return adoptPtr(new WebVTTParser(client));
     60        return adoptPtr(new WebVTTParser(client, context));
    5561    }
    5662   
    5763    static bool hasRequiredFileIdentifier(const char* data, unsigned length);
     64
     65    static inline bool isRecognizedTag(const AtomicString& tagName)
     66    {
     67        return tagName == iTag
     68            || tagName == bTag
     69            || tagName == uTag
     70            || tagName == rubyTag
     71            || tagName == rtTag;
     72    }
    5873
    5974    static inline bool isASpace(char c)
     
    7085
    7186protected:
    72     WebVTTParser(CueParserPrivateClient*);
     87    WebVTTParser(CueParserPrivateClient*, ScriptExecutionContext*);
    7388   
     89    ScriptExecutionContext* m_scriptExecutionContext;
    7490    ParseState m_state;
    7591
     
    86102    static void skipLineTerminator(const char* data, unsigned length, unsigned*);
    87103    static String collectNextLine(const char* data, unsigned length, unsigned*);
     104   
     105    void constructTreeFromToken(Document*);
    88106
    89107    String m_currentId;
     
    92110    StringBuilder m_currentContent;
    93111    String m_currentSettings;
     112   
     113    WebVTTToken m_token;
     114    OwnPtr<WebVTTTokenizer> m_tokenizer;
     115
     116    RefPtr<DocumentFragment> m_attachmentRoot;
     117    RefPtr<ContainerNode> m_currentNode;
    94118
    95119    CueParserPrivateClient* m_client;
  • trunk/Source/WebCore/platform/track/WebVTTTokenizer.h

    r94010 r94011  
    2929 */
    3030
    31 #ifndef CueParser_h
    32 #define CueParser_h
     31#ifndef WebVTTTokenizer_h
     32#define WebVTTTokenizer_h
    3333
    3434#if ENABLE(VIDEO_TRACK)
    3535
    36 #include "ThreadableLoader.h"
    37 #include "ThreadableLoaderClient.h"
    38 #include "WebVTTParser.h"
    39 #include <wtf/RefCounted.h>
    40 #include <wtf/Vector.h>
    41 #include <wtf/text/WTFString.h>
     36#include "MarkupTokenizerBase.h"
     37#include "SegmentedString.h"
     38#include "WebVTTToken.h"
    4239
    4340namespace WebCore {
    4441
    45 class ScriptExecutionContext;
    46 class TextTrackCue;
    47 
    48 class CueParserClient {
     42class WebVTTTokenizerState {
    4943public:
    50     virtual void newCuesParsed() = 0;
    51     virtual void trackLoadStarted() = 0;
    52     virtual void trackLoadError() = 0;
    53     virtual void trackLoadCompleted() = 0;
     44    enum State {
     45        DataState,
     46        EscapeState,
     47        TagState,
     48        StartTagState,
     49        StartTagClassState,
     50        StartTagAnnotationState,
     51        EndTagState,
     52        EndTagOpenState,
     53        TimestampTagState,
     54    };
    5455};
    5556
    56 class CueParser : public ThreadableLoaderClient, CueParserPrivateClient {
     57class WebVTTTokenizer : MarkupTokenizerBase<WebVTTToken, WebVTTTokenizerState> {
     58    WTF_MAKE_NONCOPYABLE(WebVTTTokenizer);
     59    WTF_MAKE_FAST_ALLOCATED;
    5760public:
    58     CueParser();
    59     virtual ~CueParser();
     61    static PassOwnPtr<WebVTTTokenizer> create() { return adoptPtr(new WebVTTTokenizer); }
    6062
    61     void didReceiveResponse(unsigned long, const ResourceResponse&);
    62     void didReceiveData(const char*, int);
    63     void didFinishLoading(unsigned long);
    64     void didFail(const ResourceError&);
    65 
    66     void load(const String&, ScriptExecutionContext*, CueParserClient*);
    67     bool supportsType(const String&);
    68 
    69     void fetchParsedCues(Vector<RefPtr<TextTrackCue> >&);
    70     void newCuesParsed();
     63    void reset();
     64   
     65    bool nextToken(SegmentedString&, WebVTTToken&);
    7166
    7267private:
    73     void createWebVTTParser();
    74  
    75     RefPtr<ThreadableLoader> m_loader;
    76     OwnPtr<CueParserPrivateInterface> m_private;
    77     CueParserClient* m_client;
     68    WebVTTTokenizer();
     69   
     70    Vector<UChar, 32> m_buffer;
    7871};
    7972
    80 } // namespace WebCore
     73}
    8174
    8275#endif
Note: See TracChangeset for help on using the changeset viewer.