LCOV - code coverage report
Current view: top level - dom/html - PluginDocument.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 113 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 23 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13