Bumping gaia.json for 8 gaia revision(s) a=gaia-bump
[gecko.git] / dom / html / PluginDocument.cpp
blob71ece19445332049c0a2f0a5338890b6db76b181
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "MediaDocument.h"
7 #include "nsIPluginDocument.h"
8 #include "nsGkAtoms.h"
9 #include "nsIPresShell.h"
10 #include "nsIObjectFrame.h"
11 #include "nsNPAPIPluginInstance.h"
12 #include "nsIDocumentInlines.h"
13 #include "nsIDocShellTreeItem.h"
14 #include "nsNodeInfoManager.h"
15 #include "nsContentCreatorFunctions.h"
16 #include "nsContentPolicyUtils.h"
17 #include "nsIPropertyBag2.h"
18 #include "mozilla/dom/Element.h"
19 #include "nsObjectLoadingContent.h"
20 #include "GeckoProfiler.h"
22 namespace mozilla {
23 namespace dom {
25 class PluginDocument MOZ_FINAL : public MediaDocument
26 , public nsIPluginDocument
28 public:
29 PluginDocument();
31 NS_DECL_ISUPPORTS_INHERITED
32 NS_DECL_NSIPLUGINDOCUMENT
34 virtual nsresult StartDocumentLoad(const char* aCommand,
35 nsIChannel* aChannel,
36 nsILoadGroup* aLoadGroup,
37 nsISupports* aContainer,
38 nsIStreamListener** aDocListener,
39 bool aReset = true,
40 nsIContentSink* aSink = nullptr) MOZ_OVERRIDE;
42 virtual void SetScriptGlobalObject(nsIScriptGlobalObject* aScriptGlobalObject) MOZ_OVERRIDE;
43 virtual bool CanSavePresentation(nsIRequest *aNewRequest) MOZ_OVERRIDE;
45 const nsCString& GetType() const { return mMimeType; }
46 Element* GetPluginContent() { return mPluginContent; }
48 void StartLayout() { MediaDocument::StartLayout(); }
50 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(PluginDocument, MediaDocument)
51 protected:
52 virtual ~PluginDocument();
54 nsresult CreateSyntheticPluginDocument();
56 nsCOMPtr<Element> mPluginContent;
57 nsRefPtr<MediaDocumentStreamListener> mStreamListener;
58 nsCString mMimeType;
61 class PluginStreamListener : public MediaDocumentStreamListener
63 public:
64 explicit PluginStreamListener(PluginDocument* aDoc)
65 : MediaDocumentStreamListener(aDoc)
66 , mPluginDoc(aDoc)
68 NS_IMETHOD OnStartRequest(nsIRequest* request, nsISupports *ctxt);
69 private:
70 nsRefPtr<PluginDocument> mPluginDoc;
74 NS_IMETHODIMP
75 PluginStreamListener::OnStartRequest(nsIRequest* request, nsISupports *ctxt)
77 PROFILER_LABEL("PluginStreamListener", "OnStartRequest",
78 js::ProfileEntry::Category::NETWORK);
80 nsCOMPtr<nsIContent> embed = mPluginDoc->GetPluginContent();
81 nsCOMPtr<nsIObjectLoadingContent> objlc = do_QueryInterface(embed);
82 nsCOMPtr<nsIStreamListener> objListener = do_QueryInterface(objlc);
84 if (!objListener) {
85 NS_NOTREACHED("PluginStreamListener without appropriate content node");
86 return NS_BINDING_ABORTED;
89 SetStreamListener(objListener);
91 // Sets up the ObjectLoadingContent tag as if it is waiting for a
92 // channel, so it can proceed with a load normally once it gets OnStartRequest
93 nsresult rv = objlc->InitializeFromChannel(request);
94 if (NS_FAILED(rv)) {
95 NS_NOTREACHED("InitializeFromChannel failed");
96 return rv;
99 // Note that because we're now hooked up to a plugin listener, this will
100 // likely spawn a plugin, which may re-enter.
101 return MediaDocumentStreamListener::OnStartRequest(request, ctxt);
104 // NOTE! nsDocument::operator new() zeroes out all members, so don't
105 // bother initializing members to 0.
107 PluginDocument::PluginDocument()
110 PluginDocument::~PluginDocument()
114 NS_IMPL_CYCLE_COLLECTION_INHERITED(PluginDocument, MediaDocument,
115 mPluginContent)
117 NS_IMPL_ADDREF_INHERITED(PluginDocument, MediaDocument)
118 NS_IMPL_RELEASE_INHERITED(PluginDocument, MediaDocument)
120 NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(PluginDocument)
121 NS_INTERFACE_TABLE_INHERITED(PluginDocument, nsIPluginDocument)
122 NS_INTERFACE_TABLE_TAIL_INHERITING(MediaDocument)
124 void
125 PluginDocument::SetScriptGlobalObject(nsIScriptGlobalObject* aScriptGlobalObject)
127 // Set the script global object on the superclass before doing
128 // anything that might require it....
129 MediaDocument::SetScriptGlobalObject(aScriptGlobalObject);
131 if (aScriptGlobalObject) {
132 if (!mPluginContent) {
133 // Create synthetic document
134 #ifdef DEBUG
135 nsresult rv =
136 #endif
137 CreateSyntheticPluginDocument();
138 NS_ASSERTION(NS_SUCCEEDED(rv), "failed to create synthetic document");
140 BecomeInteractive();
141 } else {
142 mStreamListener = nullptr;
147 bool
148 PluginDocument::CanSavePresentation(nsIRequest *aNewRequest)
150 // Full-page plugins cannot be cached, currently, because we don't have
151 // the stream listener data to feed to the plugin instance.
152 return false;
156 nsresult
157 PluginDocument::StartDocumentLoad(const char* aCommand,
158 nsIChannel* aChannel,
159 nsILoadGroup* aLoadGroup,
160 nsISupports* aContainer,
161 nsIStreamListener** aDocListener,
162 bool aReset,
163 nsIContentSink* aSink)
165 // do not allow message panes to host full-page plugins
166 // returning an error causes helper apps to take over
167 nsCOMPtr<nsIDocShellTreeItem> dsti (do_QueryInterface(aContainer));
168 if (dsti) {
169 bool isMsgPane = false;
170 dsti->NameEquals(MOZ_UTF16("messagepane"), &isMsgPane);
171 if (isMsgPane) {
172 return NS_ERROR_FAILURE;
176 nsresult rv =
177 MediaDocument::StartDocumentLoad(aCommand, aChannel, aLoadGroup, aContainer,
178 aDocListener, aReset, aSink);
179 if (NS_FAILED(rv)) {
180 return rv;
183 rv = aChannel->GetContentType(mMimeType);
184 if (NS_FAILED(rv)) {
185 return rv;
188 MediaDocument::UpdateTitleAndCharset(mMimeType, aChannel);
190 mStreamListener = new PluginStreamListener(this);
191 NS_ASSERTION(aDocListener, "null aDocListener");
192 NS_ADDREF(*aDocListener = mStreamListener);
194 return rv;
197 nsresult
198 PluginDocument::CreateSyntheticPluginDocument()
200 NS_ASSERTION(!GetShell() || !GetShell()->DidInitialize(),
201 "Creating synthetic plugin document content too late");
203 // make our generic document
204 nsresult rv = MediaDocument::CreateSyntheticDocument();
205 NS_ENSURE_SUCCESS(rv, rv);
206 // then attach our plugin
208 Element* body = GetBodyElement();
209 if (!body) {
210 NS_WARNING("no body on plugin document!");
211 return NS_ERROR_FAILURE;
214 // remove margins from body
215 NS_NAMED_LITERAL_STRING(zero, "0");
216 body->SetAttr(kNameSpaceID_None, nsGkAtoms::marginwidth, zero, false);
217 body->SetAttr(kNameSpaceID_None, nsGkAtoms::marginheight, zero, false);
220 // make plugin content
221 nsRefPtr<mozilla::dom::NodeInfo> nodeInfo;
222 nodeInfo = mNodeInfoManager->GetNodeInfo(nsGkAtoms::embed, nullptr,
223 kNameSpaceID_XHTML,
224 nsIDOMNode::ELEMENT_NODE);
225 rv = NS_NewHTMLElement(getter_AddRefs(mPluginContent), nodeInfo.forget(),
226 NOT_FROM_PARSER);
227 NS_ENSURE_SUCCESS(rv, rv);
229 // make it a named element
230 mPluginContent->SetAttr(kNameSpaceID_None, nsGkAtoms::name,
231 NS_LITERAL_STRING("plugin"), false);
233 // fill viewport and auto-resize
234 NS_NAMED_LITERAL_STRING(percent100, "100%");
235 mPluginContent->SetAttr(kNameSpaceID_None, nsGkAtoms::width, percent100,
236 false);
237 mPluginContent->SetAttr(kNameSpaceID_None, nsGkAtoms::height, percent100,
238 false);
240 // set URL
241 nsAutoCString src;
242 mDocumentURI->GetSpec(src);
243 mPluginContent->SetAttr(kNameSpaceID_None, nsGkAtoms::src,
244 NS_ConvertUTF8toUTF16(src), false);
246 // set mime type
247 mPluginContent->SetAttr(kNameSpaceID_None, nsGkAtoms::type,
248 NS_ConvertUTF8toUTF16(mMimeType), false);
250 // nsHTML(Shared)ObjectElement does not kick off a load on BindToTree if it is
251 // to a PluginDocument
252 body->AppendChildTo(mPluginContent, false);
254 return NS_OK;
259 NS_IMETHODIMP
260 PluginDocument::Print()
262 NS_ENSURE_TRUE(mPluginContent, NS_ERROR_FAILURE);
264 nsIObjectFrame* objectFrame =
265 do_QueryFrame(mPluginContent->GetPrimaryFrame());
266 if (objectFrame) {
267 nsRefPtr<nsNPAPIPluginInstance> pi;
268 objectFrame->GetPluginInstance(getter_AddRefs(pi));
269 if (pi) {
270 NPPrint npprint;
271 npprint.mode = NP_FULL;
272 npprint.print.fullPrint.pluginPrinted = false;
273 npprint.print.fullPrint.printOne = false;
274 npprint.print.fullPrint.platformPrint = nullptr;
276 pi->Print(&npprint);
280 return NS_OK;
283 } // namespace dom
284 } // namespace mozilla
286 nsresult
287 NS_NewPluginDocument(nsIDocument** aResult)
289 mozilla::dom::PluginDocument* doc = new mozilla::dom::PluginDocument();
291 NS_ADDREF(doc);
292 nsresult rv = doc->Init();
294 if (NS_FAILED(rv)) {
295 NS_RELEASE(doc);
298 *aResult = doc;
300 return rv;