1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "MediaDocument.h"
9 #include "nsNodeInfoManager.h"
10 #include "nsContentCreatorFunctions.h"
11 #include "mozilla/dom/HTMLMediaElement.h"
12 #include "DocumentInlines.h"
13 #include "nsContentUtils.h"
14 #include "mozilla/dom/Element.h"
16 namespace mozilla::dom
{
18 class VideoDocument final
: public MediaDocument
{
20 enum MediaDocumentKind
MediaDocumentKind() const override
{
21 return MediaDocumentKind::Video
;
24 virtual nsresult
StartDocumentLoad(const char* aCommand
, nsIChannel
* aChannel
,
25 nsILoadGroup
* aLoadGroup
,
26 nsISupports
* aContainer
,
27 nsIStreamListener
** aDocListener
,
28 bool aReset
= true) override
;
29 virtual void SetScriptGlobalObject(
30 nsIScriptGlobalObject
* aScriptGlobalObject
) override
;
32 virtual void Destroy() override
{
33 if (mStreamListener
) {
34 mStreamListener
->DropDocumentRef();
36 MediaDocument::Destroy();
39 nsresult
StartLayout() override
;
42 nsresult
CreateVideoElement();
43 // Sets document <title> to reflect the file name and description.
44 void UpdateTitle(nsIChannel
* aChannel
);
46 RefPtr
<MediaDocumentStreamListener
> mStreamListener
;
49 nsresult
VideoDocument::StartDocumentLoad(
50 const char* aCommand
, nsIChannel
* aChannel
, nsILoadGroup
* aLoadGroup
,
51 nsISupports
* aContainer
, nsIStreamListener
** aDocListener
, bool aReset
) {
52 nsresult rv
= MediaDocument::StartDocumentLoad(
53 aCommand
, aChannel
, aLoadGroup
, aContainer
, aDocListener
, aReset
);
54 NS_ENSURE_SUCCESS(rv
, rv
);
56 mStreamListener
= new MediaDocumentStreamListener(this);
57 NS_ADDREF(*aDocListener
= mStreamListener
);
61 nsresult
VideoDocument::StartLayout() {
62 // Create video element, and begin loading the media resource. Note we
63 // delay creating the video element until now (we're called from
64 // MediaDocumentStreamListener::OnStartRequest) as the PresShell is likely
65 // to have been created by now, so the MediaDecoder will be able to tell
66 // what kind of compositor we have, so the video element knows whether
67 // it can create a hardware accelerated video decoder or not.
68 nsresult rv
= CreateVideoElement();
69 NS_ENSURE_SUCCESS(rv
, rv
);
71 rv
= MediaDocument::StartLayout();
72 NS_ENSURE_SUCCESS(rv
, rv
);
77 void VideoDocument::SetScriptGlobalObject(
78 nsIScriptGlobalObject
* aScriptGlobalObject
) {
79 // Set the script global object on the superclass before doing
80 // anything that might require it....
81 MediaDocument::SetScriptGlobalObject(aScriptGlobalObject
);
83 if (aScriptGlobalObject
&& !InitialSetupHasBeenDone()) {
84 DebugOnly
<nsresult
> rv
= CreateSyntheticDocument();
85 NS_ASSERTION(NS_SUCCEEDED(rv
), "failed to create synthetic video document");
87 if (!nsContentUtils::IsChildOfSameType(this)) {
88 LinkStylesheet(nsLiteralString(
89 u
"resource://content-accessible/TopLevelVideoDocument.css"));
90 LinkScript(u
"chrome://global/content/TopLevelVideoDocument.js"_ns
);
96 nsresult
VideoDocument::CreateVideoElement() {
97 RefPtr
<Element
> body
= GetBodyElement();
99 NS_WARNING("no body on video document!");
100 return NS_ERROR_FAILURE
;
104 RefPtr
<mozilla::dom::NodeInfo
> nodeInfo
;
105 nodeInfo
= mNodeInfoManager
->GetNodeInfo(
106 nsGkAtoms::video
, nullptr, kNameSpaceID_XHTML
, nsINode::ELEMENT_NODE
);
108 RefPtr
<HTMLMediaElement
> element
= static_cast<HTMLMediaElement
*>(
109 NS_NewHTMLVideoElement(nodeInfo
.forget(), NOT_FROM_PARSER
));
110 if (!element
) return NS_ERROR_OUT_OF_MEMORY
;
111 element
->SetAutoplay(true, IgnoreErrors());
112 element
->SetControls(true, IgnoreErrors());
113 element
->LoadWithChannel(mChannel
,
114 getter_AddRefs(mStreamListener
->mNextStream
));
115 UpdateTitle(mChannel
);
117 if (nsContentUtils::IsChildOfSameType(this)) {
118 // Video documents that aren't toplevel should fill their frames and
121 kNameSpaceID_None
, nsGkAtoms::style
,
123 u
"position:absolute; top:0; left:0; width:100%; height:100%"),
128 body
->AppendChildTo(element
, false, rv
);
129 return rv
.StealNSResult();
132 void VideoDocument::UpdateTitle(nsIChannel
* aChannel
) {
133 if (!aChannel
) return;
135 nsAutoString fileName
;
136 GetFileName(fileName
, aChannel
);
137 IgnoredErrorResult ignored
;
138 SetTitle(fileName
, ignored
);
141 } // namespace mozilla::dom
143 nsresult
NS_NewVideoDocument(mozilla::dom::Document
** aResult
,
144 nsIPrincipal
* aPrincipal
,
145 nsIPrincipal
* aPartitionedPrincipal
) {
146 auto* doc
= new mozilla::dom::VideoDocument();
149 nsresult rv
= doc
->Init(aPrincipal
, aPartitionedPrincipal
);