Bug 1399787 - Part 2.a. Add functions to load the content of a PDF from a FileDescriptor.
All the functions added in Part 2 are utilities for sharing EMF/PDF contents
between processes.
MozReview-Commit-ID: 3qKosXH56kY
--- a/modules/pdfium/pdfium.def
+++ b/modules/pdfium/pdfium.def
@@ -2,13 +2,14 @@
; 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/.
LIBRARY pdfium
EXPORTS
FPDF_InitLibrary
FPDF_DestroyLibrary
FPDF_LoadDocument
+ FPDF_LoadCustomDocument
FPDF_CloseDocument
FPDF_GetPageCount
FPDF_LoadPage
FPDF_ClosePage
FPDF_RenderPage
--- a/widget/windows/PDFViaEMFPrintHelper.cpp
+++ b/widget/windows/PDFViaEMFPrintHelper.cpp
@@ -20,16 +20,17 @@ float ComputeScaleFactor(int aDCWidth, i
return (aDCWidth >= aPageWidth && aDCHeight >= aPageHeight)
? 1.0 /* If page fits DC - no scaling needed. */
: std::min(static_cast<float>(aDCWidth) / static_cast<float>(aPageWidth), static_cast<float>(aDCHeight) / static_cast<float>(aPageHeight));
}
PDFViaEMFPrintHelper::PDFViaEMFPrintHelper()
: mPDFDoc(nullptr)
+ , mPrfile(nullptr)
{
}
PDFViaEMFPrintHelper::~PDFViaEMFPrintHelper()
{
CloseDocument();
}
@@ -70,16 +71,48 @@ PDFViaEMFPrintHelper::OpenDocument(const
NS_ENSURE_TRUE(CreatePDFiumEngineIfNeed(), NS_ERROR_FAILURE);
mPDFDoc = mPDFiumEngine->LoadDocument(aFileName, nullptr);
NS_ENSURE_TRUE(mPDFDoc, NS_ERROR_FAILURE);
return NS_OK;
}
+nsresult
+PDFViaEMFPrintHelper::OpenDocument(const FileDescriptor& aFD)
+{
+ MOZ_ASSERT(!mPrfile, "Forget to call CloseDocument?");
+
+ if (mPDFDoc) {
+ MOZ_ASSERT_UNREACHABLE("We can only open one PDF at a time, "
+ "Use CloseDocument() to close the opened file "
+ "before calling OpenDocument()");
+ return NS_ERROR_FAILURE;
+ }
+
+ NS_ENSURE_TRUE(CreatePDFiumEngineIfNeed(), NS_ERROR_FAILURE);
+
+ auto rawFD = aFD.ClonePlatformHandle();
+ PRFileDesc* prfile = PR_ImportFile(PROsfd(rawFD.release()));
+ NS_ENSURE_TRUE(prfile, NS_ERROR_FAILURE);
+
+ mPDFDoc = mPDFiumEngine->LoadDocument(prfile, nullptr);
+ if (!mPDFDoc) {
+ PR_Close(prfile);
+ return NS_ERROR_FAILURE;
+ }
+
+ // mPDFiumEngine keeps using this handle until we close mPDFDoc. Instead of
+ // closing this HANDLE here, we close it in
+ // PDFViaEMFPrintHelper::CloseDocument.
+ mPrfile = prfile;
+
+ return NS_OK;
+}
+
bool
PDFViaEMFPrintHelper::RenderPageToDC(HDC aDC, unsigned int aPageIndex,
int aPageWidth, int aPageHeight)
{
MOZ_ASSERT(aDC && mPDFDoc);
MOZ_ASSERT(static_cast<int>(aPageIndex) <
mPDFiumEngine->GetPageCount(mPDFDoc));
@@ -171,16 +204,21 @@ PDFViaEMFPrintHelper::DrawPageToFile(con
void
PDFViaEMFPrintHelper::CloseDocument()
{
if (mPDFDoc) {
mPDFiumEngine->CloseDocument(mPDFDoc);
mPDFDoc = nullptr;
}
+
+ if (mPrfile) {
+ PR_Close(mPrfile);
+ mPrfile = nullptr;
+ }
}
bool
PDFViaEMFPrintHelper::CreatePDFiumEngineIfNeed()
{
if (!mPDFiumEngine) {
mPDFiumEngine = PDFiumEngineShim::GetInstanceOrNull();
}
--- a/widget/windows/PDFViaEMFPrintHelper.h
+++ b/widget/windows/PDFViaEMFPrintHelper.h
@@ -4,16 +4,17 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef PDFVIAEMFPRINTHELPER_H_
#define PDFVIAEMFPRINTHELPER_H_
#include "nsCOMPtr.h"
#include "PDFiumEngineShim.h"
#include "mozilla/Vector.h"
+#include "mozilla/ipc/FileDescriptor.h"
/* include windows.h for the HDC definitions that we need. */
#include <windows.h>
class nsIFile;
class nsFileInputStream;
namespace mozilla {
@@ -23,22 +24,25 @@ namespace widget {
* This class helps draw a PDF file to a given Windows DC.
* To do that it first converts the PDF file to EMF.
* Windows EMF:
* https://msdn.microsoft.com/en-us/windows/hardware/drivers/print/emf-data-type
*/
class PDFViaEMFPrintHelper
{
public:
+ typedef mozilla::ipc::FileDescriptor FileDescriptor;
+
PDFViaEMFPrintHelper();
virtual ~PDFViaEMFPrintHelper();
/** Loads the specified PDF file. */
NS_IMETHOD OpenDocument(nsIFile *aFile);
NS_IMETHOD OpenDocument(const char* aFileName);
+ NS_IMETHOD OpenDocument(const FileDescriptor& aFD);
/** Releases document buffer. */
void CloseDocument();
int GetPageCount() const { return mPDFiumEngine->GetPageCount(mPDFDoc); }
/** Convert specified PDF page to EMF and draw the EMF onto the given DC. */
bool DrawPage(HDC aPrinterDC, unsigned int aPageIndex,
@@ -50,14 +54,15 @@ public:
protected:
virtual bool CreatePDFiumEngineIfNeed();
bool RenderPageToDC(HDC aDC, unsigned int aPageIndex,
int aPageWidth, int aPageHeight);
RefPtr<PDFiumEngineShim> mPDFiumEngine;
FPDF_DOCUMENT mPDFDoc;
+ PRFileDesc* mPrfile;
};
} // namespace widget
} // namespace mozilla
#endif /* PDFVIAEMFPRINTHELPER_H_ */
--- a/widget/windows/PDFiumEngineShim.cpp
+++ b/widget/windows/PDFiumEngineShim.cpp
@@ -1,15 +1,15 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* 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 "PDFiumEngineShim.h"
-
+#include "private/pprio.h"
namespace mozilla {
namespace widget {
static PDFiumEngineShim* sPDFiumEngineShim;
/* static */
already_AddRefed<PDFiumEngineShim>
@@ -82,16 +82,20 @@ PDFiumEngineShim::Init(const nsCString&
mFPDF_DestroyLibrary = (FPDF_DestroyLibrary_Pfn)PR_FindFunctionSymbol(
mPRLibrary, "FPDF_DestroyLibrary");
NS_ENSURE_TRUE(mFPDF_DestroyLibrary, false);
mFPDF_LoadDocument = (FPDF_LoadDocument_Pfn)PR_FindFunctionSymbol(
mPRLibrary, "FPDF_LoadDocument");
NS_ENSURE_TRUE(mFPDF_LoadDocument, false);
+ mFPDF_LoadCustomDocument = (FPDF_LoadCustomDocument_Pfn)PR_FindFunctionSymbol(
+ mPRLibrary, "FPDF_LoadCustomDocument");
+ NS_ENSURE_TRUE(mFPDF_LoadCustomDocument, false);
+
mFPDF_CloseDocument = (FPDF_CloseDocument_Pfn)PR_FindFunctionSymbol(
mPRLibrary, "FPDF_CloseDocument");
NS_ENSURE_TRUE(mFPDF_CloseDocument, false);
mFPDF_GetPageCount = (FPDF_GetPageCount_Pfn)PR_FindFunctionSymbol(
mPRLibrary, "FPDF_GetPageCount");
NS_ENSURE_TRUE(mFPDF_GetPageCount, false);
@@ -115,16 +119,50 @@ PDFiumEngineShim::Init(const nsCString&
FPDF_DOCUMENT
PDFiumEngineShim::LoadDocument(FPDF_STRING file_path,
FPDF_BYTESTRING aPassword)
{
MOZ_ASSERT(mInitialized);
return mFPDF_LoadDocument(file_path, aPassword);
}
+FPDF_DOCUMENT
+PDFiumEngineShim::LoadDocument(PRFileDesc* aPrfile,
+ FPDF_BYTESTRING aPassword)
+{
+ MOZ_ASSERT(mInitialized && aPrfile);
+
+ PROffset32 fileLength = PR_Seek64(aPrfile, 0, PR_SEEK_END);
+ if (fileLength == -1) {
+ NS_WARNING("Failed to access the given FD.");
+ return nullptr;
+ }
+
+ FPDF_FILEACCESS fileAccess;
+ fileAccess.m_FileLen = static_cast<unsigned long>(fileLength);
+ fileAccess.m_Param = reinterpret_cast<void*>(aPrfile);
+ fileAccess.m_GetBlock =
+ [](void* param, unsigned long pos, unsigned char* buf, unsigned long size)
+ {
+ PRFileDesc* prfile = reinterpret_cast<PRFileDesc*>(param);
+
+ if (PR_Seek64(prfile, pos, PR_SEEK_SET) != pos) {
+ return 0;
+ }
+
+ if (PR_Read(prfile, buf, size) <= 0) {
+ return 0;
+ }
+
+ return 1;
+ };
+
+ return mFPDF_LoadCustomDocument(&fileAccess, aPassword);
+}
+
void
PDFiumEngineShim::CloseDocument(FPDF_DOCUMENT aDocument)
{
MOZ_ASSERT(mInitialized);
mFPDF_CloseDocument(aDocument);
}
int
--- a/widget/windows/PDFiumEngineShim.h
+++ b/widget/windows/PDFiumEngineShim.h
@@ -6,26 +6,28 @@
#ifndef PDFIUMENGINESHIM_H
#define PDFIUMENGINESHIM_H
#include "prlink.h"
#include "fpdfview.h"
/* include windows.h for the HDC definitions that we need. */
#include <windows.h>
+#include "private/pprio.h"
namespace mozilla {
namespace widget {
typedef void (STDCALL *FPDF_InitLibrary_Pfn)();
typedef void (STDCALL *FPDF_DestroyLibrary_Pfn)();
typedef FPDF_DOCUMENT (STDCALL *FPDF_LoadDocument_Pfn)(FPDF_STRING file_path,
FPDF_BYTESTRING password);
-
+typedef FPDF_DOCUMENT (STDCALL *FPDF_LoadCustomDocument_Pfn)(FPDF_FILEACCESS* pFileAccess,
+ FPDF_BYTESTRING password);
typedef void(STDCALL *FPDF_CloseDocument_Pfn)(FPDF_DOCUMENT aDocument);
typedef int (STDCALL *FPDF_GetPageCount_Pfn)(FPDF_DOCUMENT aDocument);
typedef FPDF_PAGE (STDCALL *FPDF_LoadPage_Pfn)(FPDF_DOCUMENT aDocument,
int aPageIndex);
typedef void (STDCALL *FPDF_ClosePage_Pfn)(FPDF_PAGE aPage);
typedef void (STDCALL *FPDF_RenderPage_Pfn)(HDC aDC,
@@ -50,16 +52,18 @@ public:
static already_AddRefed<PDFiumEngineShim> GetInstanceOrNull();
// This function is used for testing purpose only, do not call it in regular
// code.
static already_AddRefed<PDFiumEngineShim>
GetInstanceOrNull(const nsCString& aLibrary);
FPDF_DOCUMENT LoadDocument(FPDF_STRING file_path,
FPDF_BYTESTRING aPassword);
+ FPDF_DOCUMENT LoadDocument(PRFileDesc* aPrfile,
+ FPDF_BYTESTRING aPassword);
void CloseDocument(FPDF_DOCUMENT aDocument);
int GetPageCount(FPDF_DOCUMENT aDocument);
int GetPageSizeByIndex(FPDF_DOCUMENT aDocument, int aPageIndex,
double* aWidth, double* aHeight);
FPDF_PAGE LoadPage(FPDF_DOCUMENT aDocument, int aPageIndex);
void ClosePage(FPDF_PAGE aPage);
void RenderPage(HDC aDC, FPDF_PAGE aPage,
@@ -72,16 +76,17 @@ private:
~PDFiumEngineShim();
bool Init(const nsCString& aLibrary);
bool mInitialized ;
FPDF_InitLibrary_Pfn mFPDF_InitLibrary;
FPDF_DestroyLibrary_Pfn mFPDF_DestroyLibrary;
FPDF_LoadDocument_Pfn mFPDF_LoadDocument;
+ FPDF_LoadCustomDocument_Pfn mFPDF_LoadCustomDocument;
FPDF_CloseDocument_Pfn mFPDF_CloseDocument;
FPDF_GetPageCount_Pfn mFPDF_GetPageCount;
FPDF_LoadPage_Pfn mFPDF_LoadPage;
FPDF_ClosePage_Pfn mFPDF_ClosePage;
FPDF_RenderPage_Pfn mFPDF_RenderPage;
PRLibrary* mPRLibrary;
};
--- a/widget/windows/gtest/moz.build
+++ b/widget/windows/gtest/moz.build
@@ -4,16 +4,17 @@
# 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/.
UNIFIED_SOURCES = [
'TestEMFConversion.cpp',
]
LOCAL_INCLUDES += [
+ '/ipc/chromium/src',
'/modules/pdfium/pdfium/public',
'/widget/windows',
]
TEST_HARNESS_FILES.gtest += [
'pdfium_ref_x64.dll',
'pdfium_ref_x86.dll',
'PrinterTestPage.pdf',