diff options
Diffstat (limited to 'Source/WebCore/html/MediaDocument.cpp')
-rw-r--r-- | Source/WebCore/html/MediaDocument.cpp | 185 |
1 files changed, 115 insertions, 70 deletions
diff --git a/Source/WebCore/html/MediaDocument.cpp b/Source/WebCore/html/MediaDocument.cpp index a4ac2d67d..f4813d960 100644 --- a/Source/WebCore/html/MediaDocument.cpp +++ b/Source/WebCore/html/MediaDocument.cpp @@ -24,26 +24,34 @@ */ #include "config.h" +#include "MediaDocument.h" #if ENABLE(VIDEO) -#include "MediaDocument.h" +#include "Chrome.h" +#include "ChromeClient.h" #include "DocumentLoader.h" #include "EventNames.h" -#include "ExceptionCodePlaceholder.h" #include "Frame.h" #include "FrameLoader.h" #include "FrameLoaderClient.h" +#include "HTMLBodyElement.h" #include "HTMLEmbedElement.h" +#include "HTMLHeadElement.h" #include "HTMLHtmlElement.h" +#include "HTMLMetaElement.h" #include "HTMLNames.h" #include "HTMLSourceElement.h" #include "HTMLVideoElement.h" #include "KeyboardEvent.h" #include "NodeList.h" +#include "Page.h" #include "RawDataDocumentParser.h" +#include "RuntimeEnabledFeatures.h" #include "ScriptController.h" #include "ShadowRoot.h" +#include "TypedElementDescendantIterator.h" +#include <wtf/text/StringBuilder.h> namespace WebCore { @@ -52,61 +60,90 @@ using namespace HTMLNames; // FIXME: Share more code with PluginDocumentParser. class MediaDocumentParser final : public RawDataDocumentParser { public: - static PassRefPtr<MediaDocumentParser> create(MediaDocument& document) + static Ref<MediaDocumentParser> create(MediaDocument& document) { - return adoptRef(new MediaDocumentParser(document)); + return adoptRef(*new MediaDocumentParser(document)); } private: - MediaDocumentParser(Document& document) + MediaDocumentParser(MediaDocument& document) : RawDataDocumentParser(document) , m_mediaElement(0) { + m_outgoingReferrer = document.outgoingReferrer(); } - virtual void appendBytes(DocumentWriter&, const char*, size_t) override; + void appendBytes(DocumentWriter&, const char*, size_t) override; void createDocumentStructure(); HTMLMediaElement* m_mediaElement; + String m_outgoingReferrer; }; void MediaDocumentParser::createDocumentStructure() { - RefPtr<Element> rootElement = document()->createElement(htmlTag, false); - document()->appendChild(rootElement, IGNORE_EXCEPTION); - document()->setCSSTarget(rootElement.get()); - toHTMLHtmlElement(rootElement.get())->insertedByParser(); + auto& document = *this->document(); - if (document()->frame()) - document()->frame()->injectUserScripts(InjectAtDocumentStart); + auto rootElement = HTMLHtmlElement::create(document); + document.appendChild(rootElement); + document.setCSSTarget(rootElement.ptr()); + rootElement->insertedByParser(); - RefPtr<Element> body = document()->createElement(bodyTag, false); - rootElement->appendChild(body, IGNORE_EXCEPTION); + if (document.frame()) + document.frame()->injectUserScripts(InjectAtDocumentStart); - RefPtr<Element> mediaElement = document()->createElement(videoTag, false); +#if PLATFORM(IOS) + auto headElement = HTMLHeadElement::create(document); + rootElement->appendChild(headElement); - m_mediaElement = toHTMLVideoElement(mediaElement.get()); - m_mediaElement->setAttribute(controlsAttr, ""); - m_mediaElement->setAttribute(autoplayAttr, ""); + auto metaElement = HTMLMetaElement::create(document); + metaElement->setAttributeWithoutSynchronization(nameAttr, AtomicString("viewport", AtomicString::ConstructFromLiteral)); + metaElement->setAttributeWithoutSynchronization(contentAttr, AtomicString("width=device-width,initial-scale=1", AtomicString::ConstructFromLiteral)); + headElement->appendChild(metaElement); +#endif - m_mediaElement->setAttribute(nameAttr, "media"); + auto body = HTMLBodyElement::create(document); + if (RuntimeEnabledFeatures::sharedFeatures().modernMediaControlsEnabled()) { + StringBuilder bodyStyle; + bodyStyle.appendLiteral("margin: 0; padding: 0;"); + bodyStyle.appendLiteral("background-color: rgb(38, 38, 38);"); + bodyStyle.appendLiteral("display: flex; justify-content: center; align-items: center;"); + body->setAttribute(styleAttr, bodyStyle.toString()); + } + rootElement->appendChild(body); + + auto videoElement = HTMLVideoElement::create(document); + m_mediaElement = videoElement.ptr(); + videoElement->setAttributeWithoutSynchronization(controlsAttr, emptyAtom); + videoElement->setAttributeWithoutSynchronization(autoplayAttr, emptyAtom); + videoElement->setAttributeWithoutSynchronization(nameAttr, AtomicString("media", AtomicString::ConstructFromLiteral)); + + StringBuilder elementStyle; + elementStyle.appendLiteral("max-width: 100%; max-height: 100%;"); +#if PLATFORM(IOS) + elementStyle.appendLiteral("width: 100%; height: auto;"); +#endif + if (RuntimeEnabledFeatures::sharedFeatures().modernMediaControlsEnabled()) { + elementStyle.appendLiteral("min-height: 50px;"); + } + videoElement->setAttribute(styleAttr, elementStyle.toString()); - RefPtr<Element> sourceElement = document()->createElement(sourceTag, false); - HTMLSourceElement& source = toHTMLSourceElement(*sourceElement); - source.setSrc(document()->url()); + auto sourceElement = HTMLSourceElement::create(document); + sourceElement->setSrc(document.url()); - if (DocumentLoader* loader = document()->loader()) - source.setType(loader->responseMIMEType()); + if (auto* loader = document.loader()) + sourceElement->setType(loader->responseMIMEType()); - m_mediaElement->appendChild(sourceElement, IGNORE_EXCEPTION); - body->appendChild(mediaElement, IGNORE_EXCEPTION); + videoElement->appendChild(sourceElement); + body->appendChild(videoElement); - Frame* frame = document()->frame(); + Frame* frame = document.frame(); if (!frame) return; frame->loader().activeDocumentLoader()->setMainResourceDataBufferingPolicy(DoNotBufferData); + frame->loader().setOutgoingReferrer(document.completeURL(m_outgoingReferrer)); } void MediaDocumentParser::appendBytes(DocumentWriter&, const char*, size_t) @@ -120,10 +157,12 @@ void MediaDocumentParser::appendBytes(DocumentWriter&, const char*, size_t) MediaDocument::MediaDocument(Frame* frame, const URL& url) : HTMLDocument(frame, url, MediaDocumentClass) - , m_replaceMediaElementTimer(this, &MediaDocument::replaceMediaElementTimerFired) + , m_replaceMediaElementTimer(*this, &MediaDocument::replaceMediaElementTimerFired) { - setCompatibilityMode(QuirksMode); + setCompatibilityMode(DocumentCompatibilityMode::QuirksMode); lockCompatibilityMode(); + if (frame) + m_outgoingReferrer = frame->loader().outgoingReferrer(); } MediaDocument::~MediaDocument() @@ -131,70 +170,65 @@ MediaDocument::~MediaDocument() ASSERT(!m_replaceMediaElementTimer.isActive()); } -PassRefPtr<DocumentParser> MediaDocument::createParser() +Ref<DocumentParser> MediaDocument::createParser() { return MediaDocumentParser::create(*this); } -static inline HTMLVideoElement* descendentVideoElement(ContainerNode& node) +static inline HTMLVideoElement* descendantVideoElement(ContainerNode& node) { - if (isHTMLVideoElement(node)) - return toHTMLVideoElement(&node); + if (is<HTMLVideoElement>(node)) + return downcast<HTMLVideoElement>(&node); - RefPtr<NodeList> nodeList = node.getElementsByTagNameNS(videoTag.namespaceURI(), videoTag.localName()); - - if (nodeList.get()->length() > 0) - return toHTMLVideoElement(nodeList.get()->item(0)); - - return 0; + return descendantsOfType<HTMLVideoElement>(node).first(); } static inline HTMLVideoElement* ancestorVideoElement(Node* node) { - while (node && !node->hasTagName(videoTag)) + while (node && !is<HTMLVideoElement>(*node)) node = node->parentOrShadowHostNode(); - return toHTMLVideoElement(node); + return downcast<HTMLVideoElement>(node); } -void MediaDocument::defaultEventHandler(Event* event) +void MediaDocument::defaultEventHandler(Event& event) { // Match the default Quicktime plugin behavior to allow // clicking and double-clicking to pause and play the media. - Node* targetNode = event->target()->toNode(); + Node* targetNode = event.target()->toNode(); if (!targetNode) return; if (HTMLVideoElement* video = ancestorVideoElement(targetNode)) { - if (event->type() == eventNames().clickEvent) { + if (event.type() == eventNames().clickEvent) { if (!video->canPlay()) { video->pause(); - event->setDefaultHandled(); + event.setDefaultHandled(); } - } else if (event->type() == eventNames().dblclickEvent) { + } else if (event.type() == eventNames().dblclickEvent) { if (video->canPlay()) { video->play(); - event->setDefaultHandled(); + event.setDefaultHandled(); } } } - if (!targetNode->isContainerNode()) + if (!is<ContainerNode>(*targetNode)) return; - ContainerNode& targetContainer = toContainerNode(*targetNode); - if (event->type() == eventNames().keydownEvent && event->isKeyboardEvent()) { - HTMLVideoElement* video = descendentVideoElement(targetContainer); + ContainerNode& targetContainer = downcast<ContainerNode>(*targetNode); + if (event.type() == eventNames().keydownEvent && is<KeyboardEvent>(event)) { + HTMLVideoElement* video = descendantVideoElement(targetContainer); if (!video) return; - KeyboardEvent* keyboardEvent = static_cast<KeyboardEvent*>(event); - if (keyboardEvent->keyIdentifier() == "U+0020") { // space + KeyboardEvent& keyboardEvent = downcast<KeyboardEvent>(event); + if (keyboardEvent.keyIdentifier() == "U+0020") { // space if (video->paused()) { if (video->canPlay()) video->play(); } else video->pause(); - event->setDefaultHandled(); + keyboardEvent.setDefaultHandled(); } } } @@ -209,33 +243,44 @@ void MediaDocument::mediaElementSawUnsupportedTracks() m_replaceMediaElementTimer.startOneShot(0); } -void MediaDocument::replaceMediaElementTimerFired(Timer<MediaDocument>&) +void MediaDocument::replaceMediaElementTimerFired() { - HTMLElement* htmlBody = body(); + auto* htmlBody = bodyOrFrameset(); if (!htmlBody) return; // Set body margin width and height to 0 as that is what a PluginDocument uses. - htmlBody->setAttribute(marginwidthAttr, "0"); - htmlBody->setAttribute(marginheightAttr, "0"); + htmlBody->setAttributeWithoutSynchronization(marginwidthAttr, AtomicString("0", AtomicString::ConstructFromLiteral)); + htmlBody->setAttributeWithoutSynchronization(marginheightAttr, AtomicString("0", AtomicString::ConstructFromLiteral)); - if (HTMLVideoElement* videoElement = descendentVideoElement(*htmlBody)) { - RefPtr<Element> element = Document::createElement(embedTag, false); - HTMLEmbedElement* embedElement = toHTMLEmbedElement(element.get()); + if (auto* videoElement = descendantVideoElement(*htmlBody)) { + auto embedElement = HTMLEmbedElement::create(*this); - embedElement->setAttribute(widthAttr, "100%"); - embedElement->setAttribute(heightAttr, "100%"); - embedElement->setAttribute(nameAttr, "plugin"); - embedElement->setAttribute(srcAttr, url().string()); + embedElement->setAttributeWithoutSynchronization(widthAttr, AtomicString("100%", AtomicString::ConstructFromLiteral)); + embedElement->setAttributeWithoutSynchronization(heightAttr, AtomicString("100%", AtomicString::ConstructFromLiteral)); + embedElement->setAttributeWithoutSynchronization(nameAttr, AtomicString("plugin", AtomicString::ConstructFromLiteral)); + embedElement->setAttributeWithoutSynchronization(srcAttr, url().string()); - DocumentLoader* documentLoader = loader(); - ASSERT(documentLoader); - if (documentLoader) - embedElement->setAttribute(typeAttr, documentLoader->writer().mimeType()); + ASSERT(loader()); + if (auto* loader = this->loader()) + embedElement->setAttributeWithoutSynchronization(typeAttr, loader->writer().mimeType()); - videoElement->parentNode()->replaceChild(embedElement, videoElement, IGNORE_EXCEPTION); + videoElement->parentNode()->replaceChild(embedElement, *videoElement); } } +void MediaDocument::mediaElementNaturalSizeChanged(const IntSize& newSize) +{ + if (ownerElement()) + return; + + if (newSize.isZero()) + return; + + if (page()) + page()->chrome().client().imageOrMediaDocumentSizeChanged(newSize); } + +} + #endif |