forked from mirrors/gecko-dev
		
	There are no code changes, only #include changes. It was a fairly mechanical process: Search for all "AUTO_PROFILER_LABEL", and in each file, if only labels are used, convert "GeckoProfiler.h" into "ProfilerLabels.h" (or just add that last one where needed). In some files, there were also some marker calls but no other profiler-related calls, in these cases "GeckoProfiler.h" was replaced with both "ProfilerLabels.h" and "ProfilerMarkers.h", which still helps in reducing the use of the all-encompassing "GeckoProfiler.h". Differential Revision: https://phabricator.services.mozilla.com/D104588
		
			
				
	
	
		
			259 lines
		
	
	
	
		
			8.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			259 lines
		
	
	
	
		
			8.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 | 
						|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
 | 
						|
/* This Source Code Form is subject to the terms of the Mozilla Public
 | 
						|
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 | 
						|
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | 
						|
 | 
						|
#include "MediaDocument.h"
 | 
						|
#include "nsIPluginDocument.h"
 | 
						|
#include "nsGkAtoms.h"
 | 
						|
#include "nsNPAPIPluginInstance.h"
 | 
						|
#include "DocumentInlines.h"
 | 
						|
#include "nsIDocShellTreeItem.h"
 | 
						|
#include "nsNodeInfoManager.h"
 | 
						|
#include "nsContentCreatorFunctions.h"
 | 
						|
#include "nsContentPolicyUtils.h"
 | 
						|
#include "mozilla/dom/Element.h"
 | 
						|
#include "mozilla/PresShell.h"
 | 
						|
#include "mozilla/ProfilerLabels.h"
 | 
						|
#include "nsObjectLoadingContent.h"
 | 
						|
 | 
						|
namespace mozilla::dom {
 | 
						|
 | 
						|
class PluginDocument final : public MediaDocument, public nsIPluginDocument {
 | 
						|
 public:
 | 
						|
  PluginDocument();
 | 
						|
 | 
						|
  NS_DECL_ISUPPORTS_INHERITED
 | 
						|
  NS_DECL_NSIPLUGINDOCUMENT
 | 
						|
 | 
						|
  enum MediaDocumentKind MediaDocumentKind() const override {
 | 
						|
    return MediaDocumentKind::Plugin;
 | 
						|
  }
 | 
						|
 | 
						|
  nsresult StartDocumentLoad(const char* aCommand, nsIChannel* aChannel,
 | 
						|
                             nsILoadGroup* aLoadGroup, nsISupports* aContainer,
 | 
						|
                             nsIStreamListener** aDocListener,
 | 
						|
                             bool aReset = true,
 | 
						|
                             nsIContentSink* aSink = nullptr) override;
 | 
						|
 | 
						|
  void SetScriptGlobalObject(
 | 
						|
      nsIScriptGlobalObject* aScriptGlobalObject) override;
 | 
						|
  bool CanSavePresentation(nsIRequest* aNewRequest,
 | 
						|
                           uint16_t& aBFCacheStatus) override;
 | 
						|
 | 
						|
  const nsCString& GetType() const { return mMimeType; }
 | 
						|
  Element* GetPluginContent() { return mPluginContent; }
 | 
						|
 | 
						|
  virtual void Destroy() override {
 | 
						|
    if (mStreamListener) {
 | 
						|
      mStreamListener->DropDocumentRef();
 | 
						|
    }
 | 
						|
    MediaDocument::Destroy();
 | 
						|
  }
 | 
						|
 | 
						|
  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(PluginDocument, MediaDocument)
 | 
						|
 protected:
 | 
						|
  ~PluginDocument() override;
 | 
						|
 | 
						|
  nsresult CreateSyntheticPluginDocument();
 | 
						|
 | 
						|
  nsCOMPtr<Element> mPluginContent;
 | 
						|
  RefPtr<MediaDocumentStreamListener> mStreamListener;
 | 
						|
  nsCString mMimeType;
 | 
						|
};
 | 
						|
 | 
						|
class PluginStreamListener : public MediaDocumentStreamListener {
 | 
						|
 public:
 | 
						|
  explicit PluginStreamListener(PluginDocument* aDoc)
 | 
						|
      : MediaDocumentStreamListener(aDoc), mPluginDoc(aDoc) {}
 | 
						|
  NS_IMETHOD OnStartRequest(nsIRequest* request) override;
 | 
						|
 | 
						|
 private:
 | 
						|
  RefPtr<PluginDocument> mPluginDoc;
 | 
						|
};
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
PluginStreamListener::OnStartRequest(nsIRequest* request) {
 | 
						|
  AUTO_PROFILER_LABEL("PluginStreamListener::OnStartRequest", NETWORK);
 | 
						|
 | 
						|
  nsCOMPtr<nsIContent> embed = mPluginDoc->GetPluginContent();
 | 
						|
  nsCOMPtr<nsIObjectLoadingContent> objlc = do_QueryInterface(embed);
 | 
						|
  nsCOMPtr<nsIStreamListener> objListener = do_QueryInterface(objlc);
 | 
						|
 | 
						|
  if (!objListener) {
 | 
						|
    MOZ_ASSERT_UNREACHABLE(
 | 
						|
        "PluginStreamListener without appropriate content "
 | 
						|
        "node");
 | 
						|
    return NS_BINDING_ABORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  SetStreamListener(objListener);
 | 
						|
 | 
						|
  // Sets up the ObjectLoadingContent tag as if it is waiting for a
 | 
						|
  // channel, so it can proceed with a load normally once it gets OnStartRequest
 | 
						|
  nsresult rv = objlc->InitializeFromChannel(request);
 | 
						|
  if (NS_FAILED(rv)) {
 | 
						|
    MOZ_ASSERT_UNREACHABLE("InitializeFromChannel failed");
 | 
						|
    return rv;
 | 
						|
  }
 | 
						|
 | 
						|
  // Note that because we're now hooked up to a plugin listener, this will
 | 
						|
  // likely spawn a plugin, which may re-enter.
 | 
						|
  return MediaDocumentStreamListener::OnStartRequest(request);
 | 
						|
}
 | 
						|
 | 
						|
PluginDocument::PluginDocument() = default;
 | 
						|
 | 
						|
PluginDocument::~PluginDocument() = default;
 | 
						|
 | 
						|
NS_IMPL_CYCLE_COLLECTION_INHERITED(PluginDocument, MediaDocument,
 | 
						|
                                   mPluginContent)
 | 
						|
 | 
						|
NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED(PluginDocument, MediaDocument,
 | 
						|
                                             nsIPluginDocument)
 | 
						|
 | 
						|
void PluginDocument::SetScriptGlobalObject(
 | 
						|
    nsIScriptGlobalObject* aScriptGlobalObject) {
 | 
						|
  // Set the script global object on the superclass before doing
 | 
						|
  // anything that might require it....
 | 
						|
  MediaDocument::SetScriptGlobalObject(aScriptGlobalObject);
 | 
						|
 | 
						|
  if (aScriptGlobalObject) {
 | 
						|
    if (!InitialSetupHasBeenDone()) {
 | 
						|
      // Create synthetic document
 | 
						|
#ifdef DEBUG
 | 
						|
      nsresult rv =
 | 
						|
#endif
 | 
						|
          CreateSyntheticPluginDocument();
 | 
						|
      NS_ASSERTION(NS_SUCCEEDED(rv), "failed to create synthetic document");
 | 
						|
      InitialSetupDone();
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    mStreamListener = nullptr;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
bool PluginDocument::CanSavePresentation(nsIRequest* aNewRequest,
 | 
						|
                                         uint16_t& aBFCacheStatus) {
 | 
						|
  // Full-page plugins cannot be cached, currently, because we don't have
 | 
						|
  // the stream listener data to feed to the plugin instance.
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
nsresult PluginDocument::StartDocumentLoad(const char* aCommand,
 | 
						|
                                           nsIChannel* aChannel,
 | 
						|
                                           nsILoadGroup* aLoadGroup,
 | 
						|
                                           nsISupports* aContainer,
 | 
						|
                                           nsIStreamListener** aDocListener,
 | 
						|
                                           bool aReset, nsIContentSink* aSink) {
 | 
						|
  // do not allow message panes to host full-page plugins
 | 
						|
  // returning an error causes helper apps to take over
 | 
						|
  nsCOMPtr<nsIDocShellTreeItem> dsti(do_QueryInterface(aContainer));
 | 
						|
  if (dsti) {
 | 
						|
    bool isMsgPane = false;
 | 
						|
    dsti->NameEquals(u"messagepane"_ns, &isMsgPane);
 | 
						|
    if (isMsgPane) {
 | 
						|
      return NS_ERROR_FAILURE;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  nsresult rv = MediaDocument::StartDocumentLoad(
 | 
						|
      aCommand, aChannel, aLoadGroup, aContainer, aDocListener, aReset, aSink);
 | 
						|
  if (NS_FAILED(rv)) {
 | 
						|
    return rv;
 | 
						|
  }
 | 
						|
 | 
						|
  rv = aChannel->GetContentType(mMimeType);
 | 
						|
  if (NS_FAILED(rv)) {
 | 
						|
    return rv;
 | 
						|
  }
 | 
						|
 | 
						|
  MediaDocument::UpdateTitleAndCharset(mMimeType, aChannel);
 | 
						|
 | 
						|
  mStreamListener = new PluginStreamListener(this);
 | 
						|
  NS_ASSERTION(aDocListener, "null aDocListener");
 | 
						|
  NS_ADDREF(*aDocListener = mStreamListener);
 | 
						|
 | 
						|
  return rv;
 | 
						|
}
 | 
						|
 | 
						|
nsresult PluginDocument::CreateSyntheticPluginDocument() {
 | 
						|
  NS_ASSERTION(!GetPresShell() || !GetPresShell()->DidInitialize(),
 | 
						|
               "Creating synthetic plugin document content too late");
 | 
						|
 | 
						|
  // make our generic document
 | 
						|
  nsresult rv = MediaDocument::CreateSyntheticDocument();
 | 
						|
  NS_ENSURE_SUCCESS(rv, rv);
 | 
						|
  // then attach our plugin
 | 
						|
 | 
						|
  RefPtr<Element> body = GetBodyElement();
 | 
						|
  if (!body) {
 | 
						|
    NS_WARNING("no body on plugin document!");
 | 
						|
    return NS_ERROR_FAILURE;
 | 
						|
  }
 | 
						|
 | 
						|
  // remove margins from body
 | 
						|
  constexpr auto zero = u"0"_ns;
 | 
						|
  body->SetAttr(kNameSpaceID_None, nsGkAtoms::marginwidth, zero, false);
 | 
						|
  body->SetAttr(kNameSpaceID_None, nsGkAtoms::marginheight, zero, false);
 | 
						|
 | 
						|
  // make plugin content
 | 
						|
  RefPtr<mozilla::dom::NodeInfo> nodeInfo;
 | 
						|
  nodeInfo = mNodeInfoManager->GetNodeInfo(
 | 
						|
      nsGkAtoms::embed, nullptr, kNameSpaceID_XHTML, nsINode::ELEMENT_NODE);
 | 
						|
  rv = NS_NewHTMLElement(getter_AddRefs(mPluginContent), nodeInfo.forget(),
 | 
						|
                         NOT_FROM_PARSER);
 | 
						|
  NS_ENSURE_SUCCESS(rv, rv);
 | 
						|
 | 
						|
  // make it a named element
 | 
						|
  mPluginContent->SetAttr(kNameSpaceID_None, nsGkAtoms::name, u"plugin"_ns,
 | 
						|
                          false);
 | 
						|
 | 
						|
  // fill viewport and auto-resize
 | 
						|
  constexpr auto percent100 = u"100%"_ns;
 | 
						|
  mPluginContent->SetAttr(kNameSpaceID_None, nsGkAtoms::width, percent100,
 | 
						|
                          false);
 | 
						|
  mPluginContent->SetAttr(kNameSpaceID_None, nsGkAtoms::height, percent100,
 | 
						|
                          false);
 | 
						|
 | 
						|
  // set URL
 | 
						|
  nsAutoCString src;
 | 
						|
  mDocumentURI->GetSpec(src);
 | 
						|
  mPluginContent->SetAttr(kNameSpaceID_None, nsGkAtoms::src,
 | 
						|
                          NS_ConvertUTF8toUTF16(src), false);
 | 
						|
 | 
						|
  // set mime type
 | 
						|
  mPluginContent->SetAttr(kNameSpaceID_None, nsGkAtoms::type,
 | 
						|
                          NS_ConvertUTF8toUTF16(mMimeType), false);
 | 
						|
 | 
						|
  // nsHTML(Shared)ObjectElement does not kick off a load on BindToTree if it is
 | 
						|
  // to a PluginDocument
 | 
						|
  body->AppendChildTo(mPluginContent, false);
 | 
						|
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
PluginDocument::Print() {
 | 
						|
  NS_ENSURE_TRUE(mPluginContent, NS_ERROR_FAILURE);
 | 
						|
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
}  // namespace mozilla::dom
 | 
						|
 | 
						|
nsresult NS_NewPluginDocument(mozilla::dom::Document** aResult) {
 | 
						|
  auto* doc = new mozilla::dom::PluginDocument();
 | 
						|
 | 
						|
  NS_ADDREF(doc);
 | 
						|
  nsresult rv = doc->Init();
 | 
						|
 | 
						|
  if (NS_FAILED(rv)) {
 | 
						|
    NS_RELEASE(doc);
 | 
						|
  }
 | 
						|
 | 
						|
  *aResult = doc;
 | 
						|
 | 
						|
  return rv;
 | 
						|
}
 |