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.

     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
    27 {
    28 public:
    29   PluginDocument();
    30   virtual ~PluginDocument();
    32   NS_DECL_ISUPPORTS_INHERITED
    33   NS_DECL_NSIPLUGINDOCUMENT
    35   virtual nsresult StartDocumentLoad(const char*         aCommand,
    36                                      nsIChannel*         aChannel,
    37                                      nsILoadGroup*       aLoadGroup,
    38                                      nsISupports*        aContainer,
    39                                      nsIStreamListener** aDocListener,
    40                                      bool                aReset = true,
    41                                      nsIContentSink*     aSink = nullptr);
    43   virtual void SetScriptGlobalObject(nsIScriptGlobalObject* aScriptGlobalObject);
    44   virtual bool CanSavePresentation(nsIRequest *aNewRequest);
    46   const nsCString& GetType() const { return mMimeType; }
    47   Element*         GetPluginContent() { return mPluginContent; }
    49   void StartLayout() { MediaDocument::StartLayout(); }
    51   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(PluginDocument, MediaDocument)
    52 protected:
    53   nsresult CreateSyntheticPluginDocument();
    55   nsCOMPtr<Element>                        mPluginContent;
    56   nsRefPtr<MediaDocumentStreamListener>    mStreamListener;
    57   nsCString                                mMimeType;
    58 };
    60 class PluginStreamListener : public MediaDocumentStreamListener
    61 {
    62 public:
    63   PluginStreamListener(PluginDocument* doc)
    64     : MediaDocumentStreamListener(doc)
    65     , mPluginDoc(doc)
    66   {}
    67   NS_IMETHOD OnStartRequest(nsIRequest* request, nsISupports *ctxt);
    68 private:
    69   nsRefPtr<PluginDocument> mPluginDoc;
    70 };
    73 NS_IMETHODIMP
    74 PluginStreamListener::OnStartRequest(nsIRequest* request, nsISupports *ctxt)
    75 {
    76   PROFILER_LABEL("PluginStreamListener", "OnStartRequest");
    78   nsCOMPtr<nsIContent> embed = mPluginDoc->GetPluginContent();
    79   nsCOMPtr<nsIObjectLoadingContent> objlc = do_QueryInterface(embed);
    80   nsCOMPtr<nsIStreamListener> objListener = do_QueryInterface(objlc);
    82   if (!objListener) {
    83     NS_NOTREACHED("PluginStreamListener without appropriate content node");
    84     return NS_BINDING_ABORTED;
    85   }
    87   SetStreamListener(objListener);
    89   // Sets up the ObjectLoadingContent tag as if it is waiting for a
    90   // channel, so it can proceed with a load normally once it gets OnStartRequest
    91   nsresult rv = objlc->InitializeFromChannel(request);
    92   if (NS_FAILED(rv)) {
    93     NS_NOTREACHED("InitializeFromChannel failed");
    94     return rv;
    95   }
    97   // Note that because we're now hooked up to a plugin listener, this will
    98   // likely spawn a plugin, which may re-enter.
    99   return MediaDocumentStreamListener::OnStartRequest(request, ctxt);
   100 }
   102   // NOTE! nsDocument::operator new() zeroes out all members, so don't
   103   // bother initializing members to 0.
   105 PluginDocument::PluginDocument()
   106 {}
   108 PluginDocument::~PluginDocument()
   109 {}
   112 NS_IMPL_CYCLE_COLLECTION_INHERITED(PluginDocument, MediaDocument,
   113                                    mPluginContent)
   115 NS_IMPL_ADDREF_INHERITED(PluginDocument, MediaDocument)
   116 NS_IMPL_RELEASE_INHERITED(PluginDocument, MediaDocument)
   118 NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(PluginDocument)
   119   NS_INTERFACE_TABLE_INHERITED(PluginDocument, nsIPluginDocument)
   120 NS_INTERFACE_TABLE_TAIL_INHERITING(MediaDocument)
   122 void
   123 PluginDocument::SetScriptGlobalObject(nsIScriptGlobalObject* aScriptGlobalObject)
   124 {
   125   // Set the script global object on the superclass before doing
   126   // anything that might require it....
   127   MediaDocument::SetScriptGlobalObject(aScriptGlobalObject);
   129   if (aScriptGlobalObject) {
   130     if (!mPluginContent) {
   131       // Create synthetic document
   132 #ifdef DEBUG
   133       nsresult rv =
   134 #endif
   135         CreateSyntheticPluginDocument();
   136       NS_ASSERTION(NS_SUCCEEDED(rv), "failed to create synthetic document");
   137     }
   138     BecomeInteractive();
   139   } else {
   140     mStreamListener = nullptr;
   141   }
   142 }
   145 bool
   146 PluginDocument::CanSavePresentation(nsIRequest *aNewRequest)
   147 {
   148   // Full-page plugins cannot be cached, currently, because we don't have
   149   // the stream listener data to feed to the plugin instance.
   150   return false;
   151 }
   154 nsresult
   155 PluginDocument::StartDocumentLoad(const char*         aCommand,
   156                                   nsIChannel*         aChannel,
   157                                   nsILoadGroup*       aLoadGroup,
   158                                   nsISupports*        aContainer,
   159                                   nsIStreamListener** aDocListener,
   160                                   bool                aReset,
   161                                   nsIContentSink*     aSink)
   162 {
   163   // do not allow message panes to host full-page plugins
   164   // returning an error causes helper apps to take over
   165   nsCOMPtr<nsIDocShellTreeItem> dsti (do_QueryInterface(aContainer));
   166   if (dsti) {
   167     bool isMsgPane = false;
   168     dsti->NameEquals(MOZ_UTF16("messagepane"), &isMsgPane);
   169     if (isMsgPane) {
   170       return NS_ERROR_FAILURE;
   171     }
   172   }
   174   nsresult rv =
   175     MediaDocument::StartDocumentLoad(aCommand, aChannel, aLoadGroup, aContainer,
   176                                      aDocListener, aReset, aSink);
   177   if (NS_FAILED(rv)) {
   178     return rv;
   179   }
   181   rv = aChannel->GetContentType(mMimeType);
   182   if (NS_FAILED(rv)) {
   183     return rv;
   184   }
   186   MediaDocument::UpdateTitleAndCharset(mMimeType);
   188   mStreamListener = new PluginStreamListener(this);
   189   NS_ASSERTION(aDocListener, "null aDocListener");
   190   NS_ADDREF(*aDocListener = mStreamListener);
   192   return rv;
   193 }
   195 nsresult
   196 PluginDocument::CreateSyntheticPluginDocument()
   197 {
   198   NS_ASSERTION(!GetShell() || !GetShell()->DidInitialize(),
   199                "Creating synthetic plugin document content too late");
   201   // make our generic document
   202   nsresult rv = MediaDocument::CreateSyntheticDocument();
   203   NS_ENSURE_SUCCESS(rv, rv);
   204   // then attach our plugin
   206   Element* body = GetBodyElement();
   207   if (!body) {
   208     NS_WARNING("no body on plugin document!");
   209     return NS_ERROR_FAILURE;
   210   }
   212   // remove margins from body
   213   NS_NAMED_LITERAL_STRING(zero, "0");
   214   body->SetAttr(kNameSpaceID_None, nsGkAtoms::marginwidth, zero, false);
   215   body->SetAttr(kNameSpaceID_None, nsGkAtoms::marginheight, zero, false);
   218   // make plugin content
   219   nsCOMPtr<nsINodeInfo> nodeInfo;
   220   nodeInfo = mNodeInfoManager->GetNodeInfo(nsGkAtoms::embed, nullptr,
   221                                            kNameSpaceID_XHTML,
   222                                            nsIDOMNode::ELEMENT_NODE);
   223   rv = NS_NewHTMLElement(getter_AddRefs(mPluginContent), nodeInfo.forget(),
   224                          NOT_FROM_PARSER);
   225   NS_ENSURE_SUCCESS(rv, rv);
   227   // make it a named element
   228   mPluginContent->SetAttr(kNameSpaceID_None, nsGkAtoms::name,
   229                           NS_LITERAL_STRING("plugin"), false);
   231   // fill viewport and auto-resize
   232   NS_NAMED_LITERAL_STRING(percent100, "100%");
   233   mPluginContent->SetAttr(kNameSpaceID_None, nsGkAtoms::width, percent100,
   234                           false);
   235   mPluginContent->SetAttr(kNameSpaceID_None, nsGkAtoms::height, percent100,
   236                           false);
   238   // set URL
   239   nsAutoCString src;
   240   mDocumentURI->GetSpec(src);
   241   mPluginContent->SetAttr(kNameSpaceID_None, nsGkAtoms::src,
   242                           NS_ConvertUTF8toUTF16(src), false);
   244   // set mime type
   245   mPluginContent->SetAttr(kNameSpaceID_None, nsGkAtoms::type,
   246                           NS_ConvertUTF8toUTF16(mMimeType), false);
   248   // nsHTML(Shared)ObjectElement does not kick off a load on BindToTree if it is
   249   // to a PluginDocument
   250   body->AppendChildTo(mPluginContent, false);
   252   return NS_OK;
   255 }
   257 NS_IMETHODIMP
   258 PluginDocument::Print()
   259 {
   260   NS_ENSURE_TRUE(mPluginContent, NS_ERROR_FAILURE);
   262   nsIObjectFrame* objectFrame =
   263     do_QueryFrame(mPluginContent->GetPrimaryFrame());
   264   if (objectFrame) {
   265     nsRefPtr<nsNPAPIPluginInstance> pi;
   266     objectFrame->GetPluginInstance(getter_AddRefs(pi));
   267     if (pi) {
   268       NPPrint npprint;
   269       npprint.mode = NP_FULL;
   270       npprint.print.fullPrint.pluginPrinted = false;
   271       npprint.print.fullPrint.printOne = false;
   272       npprint.print.fullPrint.platformPrint = nullptr;
   274       pi->Print(&npprint);
   275     }
   276   }
   278   return NS_OK;
   279 }
   281 } // namespace dom
   282 } // namespace mozilla
   284 nsresult
   285 NS_NewPluginDocument(nsIDocument** aResult)
   286 {
   287   mozilla::dom::PluginDocument* doc = new mozilla::dom::PluginDocument();
   289   NS_ADDREF(doc);
   290   nsresult rv = doc->Init();
   292   if (NS_FAILED(rv)) {
   293     NS_RELEASE(doc);
   294   }
   296   *aResult = doc;
   298   return rv;
   299 }

mercurial