diff options
Diffstat (limited to 'dom/html/VideoDocument.cpp')
-rw-r--r-- | dom/html/VideoDocument.cpp | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/dom/html/VideoDocument.cpp b/dom/html/VideoDocument.cpp new file mode 100644 index 000000000..1bd898564 --- /dev/null +++ b/dom/html/VideoDocument.cpp @@ -0,0 +1,155 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "MediaDocument.h" +#include "nsGkAtoms.h" +#include "nsNodeInfoManager.h" +#include "nsContentCreatorFunctions.h" +#include "mozilla/dom/HTMLMediaElement.h" +#include "nsIDocumentInlines.h" +#include "nsContentUtils.h" +#include "mozilla/dom/Element.h" + +namespace mozilla { +namespace dom { + +class VideoDocument final : public MediaDocument +{ +public: + virtual nsresult StartDocumentLoad(const char* aCommand, + nsIChannel* aChannel, + nsILoadGroup* aLoadGroup, + nsISupports* aContainer, + nsIStreamListener** aDocListener, + bool aReset = true, + nsIContentSink* aSink = nullptr); + virtual void SetScriptGlobalObject(nsIScriptGlobalObject* aScriptGlobalObject); + +protected: + + // Sets document <title> to reflect the file name and description. + void UpdateTitle(nsIChannel* aChannel); + + nsresult CreateSyntheticVideoDocument(nsIChannel* aChannel, + nsIStreamListener** aListener); + + RefPtr<MediaDocumentStreamListener> mStreamListener; +}; + +nsresult +VideoDocument::StartDocumentLoad(const char* aCommand, + nsIChannel* aChannel, + nsILoadGroup* aLoadGroup, + nsISupports* aContainer, + nsIStreamListener** aDocListener, + bool aReset, + nsIContentSink* aSink) +{ + nsresult rv = + MediaDocument::StartDocumentLoad(aCommand, aChannel, aLoadGroup, aContainer, + aDocListener, aReset, aSink); + NS_ENSURE_SUCCESS(rv, rv); + + mStreamListener = new MediaDocumentStreamListener(this); + + // Create synthetic document + rv = CreateSyntheticVideoDocument(aChannel, + getter_AddRefs(mStreamListener->mNextStream)); + NS_ENSURE_SUCCESS(rv, rv); + + NS_ADDREF(*aDocListener = mStreamListener); + return rv; +} + +void +VideoDocument::SetScriptGlobalObject(nsIScriptGlobalObject* aScriptGlobalObject) +{ + // Set the script global object on the superclass before doing + // anything that might require it.... + MediaDocument::SetScriptGlobalObject(aScriptGlobalObject); + + if (aScriptGlobalObject) { + if (!nsContentUtils::IsChildOfSameType(this) && + GetReadyStateEnum() != nsIDocument::READYSTATE_COMPLETE) { + LinkStylesheet(NS_LITERAL_STRING("resource://gre/res/TopLevelVideoDocument.css")); + LinkStylesheet(NS_LITERAL_STRING("chrome://global/skin/media/TopLevelVideoDocument.css")); + LinkScript(NS_LITERAL_STRING("chrome://global/content/TopLevelVideoDocument.js")); + } + BecomeInteractive(); + } +} + +nsresult +VideoDocument::CreateSyntheticVideoDocument(nsIChannel* aChannel, + nsIStreamListener** aListener) +{ + // make our generic document + nsresult rv = MediaDocument::CreateSyntheticDocument(); + NS_ENSURE_SUCCESS(rv, rv); + + Element* body = GetBodyElement(); + if (!body) { + NS_WARNING("no body on video document!"); + return NS_ERROR_FAILURE; + } + + // make content + RefPtr<mozilla::dom::NodeInfo> nodeInfo; + nodeInfo = mNodeInfoManager->GetNodeInfo(nsGkAtoms::video, nullptr, + kNameSpaceID_XHTML, + nsIDOMNode::ELEMENT_NODE); + + RefPtr<HTMLMediaElement> element = + static_cast<HTMLMediaElement*>(NS_NewHTMLVideoElement(nodeInfo.forget(), + NOT_FROM_PARSER)); + if (!element) + return NS_ERROR_OUT_OF_MEMORY; + element->SetAutoplay(true); + element->SetControls(true); + element->LoadWithChannel(aChannel, aListener); + UpdateTitle(aChannel); + + if (nsContentUtils::IsChildOfSameType(this)) { + // Video documents that aren't toplevel should fill their frames and + // not have margins + element->SetAttr(kNameSpaceID_None, nsGkAtoms::style, + NS_LITERAL_STRING("position:absolute; top:0; left:0; width:100%; height:100%"), + true); + } + + return body->AppendChildTo(element, false); +} + +void +VideoDocument::UpdateTitle(nsIChannel* aChannel) +{ + if (!aChannel) + return; + + nsAutoString fileName; + GetFileName(fileName, aChannel); + SetTitle(fileName); +} + +} // namespace dom +} // namespace mozilla + +nsresult +NS_NewVideoDocument(nsIDocument** aResult) +{ + mozilla::dom::VideoDocument* doc = new mozilla::dom::VideoDocument(); + + NS_ADDREF(doc); + nsresult rv = doc->Init(); + + if (NS_FAILED(rv)) { + NS_RELEASE(doc); + } + + *aResult = doc; + + return rv; +} |