content/html/document/src/PluginDocument.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial