зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1414834 - re-land print IPC changes from bug 1319423; r=bobowen
With this patch print IPC no longer requires the child process to create files. Instead files are opened by the parent and a file descriptor is sent to the child. This will allow us to sandbox child processes more aggressively. MozReview-Commit-ID: GQWTYLV01kj --HG-- extra : rebase_source : 9b91e9b01708d73915a49684c2cec96457650e45
This commit is contained in:
Родитель
0c779a0480
Коммит
8cb6e552a8
|
@ -19,12 +19,6 @@ DrawEventRecorderPRFileDesc::RecordEvent(const gfx::RecordedEvent& aEvent)
|
|||
Flush();
|
||||
}
|
||||
|
||||
DrawEventRecorderPRFileDesc::DrawEventRecorderPRFileDesc(const char* aFilename)
|
||||
{
|
||||
mOutputStream.Open(aFilename);
|
||||
WriteHeader(mOutputStream);
|
||||
}
|
||||
|
||||
DrawEventRecorderPRFileDesc::~DrawEventRecorderPRFileDesc()
|
||||
{
|
||||
if (IsOpen()) {
|
||||
|
@ -45,11 +39,11 @@ DrawEventRecorderPRFileDesc::IsOpen()
|
|||
}
|
||||
|
||||
void
|
||||
DrawEventRecorderPRFileDesc::OpenNew(const char* aFilename)
|
||||
DrawEventRecorderPRFileDesc::OpenFD(PRFileDesc* aFd)
|
||||
{
|
||||
MOZ_ASSERT(!IsOpen());
|
||||
|
||||
mOutputStream.Open(aFilename);
|
||||
mOutputStream.OpenFD(aFd);
|
||||
WriteHeader(mOutputStream);
|
||||
}
|
||||
|
||||
|
|
|
@ -25,9 +25,10 @@ public:
|
|||
PRFileDescStream() : mFd(nullptr), mBuffer(nullptr), mBufferPos(0),
|
||||
mGood(true) {}
|
||||
|
||||
void Open(const char* aFilename) {
|
||||
void OpenFD(PRFileDesc* aFd)
|
||||
{
|
||||
MOZ_ASSERT(!IsOpen());
|
||||
mFd = PR_Open(aFilename, PR_RDWR | PR_CREATE_FILE, PR_IRUSR | PR_IWUSR);
|
||||
mFd = aFd;
|
||||
mGood = true;
|
||||
mBuffer.reset(new uint8_t[kBufferSize]);
|
||||
mBufferPos = 0;
|
||||
|
@ -118,7 +119,7 @@ class DrawEventRecorderPRFileDesc : public gfx::DrawEventRecorderPrivate
|
|||
{
|
||||
public:
|
||||
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawEventRecorderPRFileDesc, override)
|
||||
explicit DrawEventRecorderPRFileDesc(const char* aFilename);
|
||||
explicit DrawEventRecorderPRFileDesc(){};
|
||||
~DrawEventRecorderPRFileDesc();
|
||||
|
||||
void RecordEvent(const gfx::RecordedEvent& aEvent) override;
|
||||
|
@ -129,11 +130,9 @@ public:
|
|||
bool IsOpen();
|
||||
|
||||
/**
|
||||
* Opens new file with the provided name. The recorder does NOT forget which
|
||||
* objects it has recorded. This can be used with Close, so that a recording
|
||||
* can be processed in chunks. The file must not already be open.
|
||||
* Opens the recorder with the provided PRFileDesc *.
|
||||
*/
|
||||
void OpenNew(const char* aFilename);
|
||||
void OpenFD(PRFileDesc* aFd);
|
||||
|
||||
/**
|
||||
* Closes the file so that it can be processed. The recorder does NOT forget
|
||||
|
|
|
@ -22,9 +22,9 @@ parent:
|
|||
async InitializePrint(nsString aDocumentTitle, nsString aPrintToFile,
|
||||
int32_t aStartPage, int32_t aEndPage);
|
||||
|
||||
// Translate the stored page recording and play back the events to the real
|
||||
// print device.
|
||||
async ProcessPage(nsCString aPageFileName);
|
||||
// Translate the page recording writen into |fd| and play back the events to
|
||||
// the real print device.
|
||||
async ProcessPage();
|
||||
|
||||
// This informs the real print device that we've finished, so it can trigger
|
||||
// the actual print.
|
||||
|
@ -45,11 +45,13 @@ parent:
|
|||
|
||||
child:
|
||||
// Inform the child that the print has been initialized in the parent or has
|
||||
// failed with result aRv.
|
||||
async PrintInitializationResult(nsresult aRv);
|
||||
// failed with result aRv. Includes a file descriptor which the first page
|
||||
// can be written to.
|
||||
async PrintInitializationResult(nsresult aRv, FileDescriptor aFd);
|
||||
|
||||
// Inform the child that the latest page has been processed remotely.
|
||||
async PageProcessed();
|
||||
// Inform the child that the latest page has been processed remotely. Includes
|
||||
// a file descriptor which the next page can be written to.
|
||||
async PageProcessed(FileDescriptor aFd);
|
||||
|
||||
async __delete__();
|
||||
};
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "mozilla/Unused.h"
|
||||
#include "nsPagePrintTimer.h"
|
||||
#include "nsPrintEngine.h"
|
||||
#include "private/pprio.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layout {
|
||||
|
@ -36,26 +37,48 @@ RemotePrintJobChild::InitializePrint(const nsString& aDocumentTitle,
|
|||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
RemotePrintJobChild::RecvPrintInitializationResult(const nsresult& aRv)
|
||||
RemotePrintJobChild::RecvPrintInitializationResult(
|
||||
const nsresult& aRv,
|
||||
const mozilla::ipc::FileDescriptor& aFd)
|
||||
{
|
||||
mPrintInitialized = true;
|
||||
mInitializationResult = aRv;
|
||||
if (NS_SUCCEEDED(aRv)) {
|
||||
SetNextPageFD(aFd);
|
||||
}
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
PRFileDesc*
|
||||
RemotePrintJobChild::GetNextPageFD()
|
||||
{
|
||||
MOZ_ASSERT(mNextPageFD);
|
||||
PRFileDesc* fd = mNextPageFD;
|
||||
mNextPageFD = nullptr;
|
||||
return fd;
|
||||
}
|
||||
|
||||
void
|
||||
RemotePrintJobChild::ProcessPage(const nsCString& aPageFileName)
|
||||
RemotePrintJobChild::SetNextPageFD(const mozilla::ipc::FileDescriptor& aFd)
|
||||
{
|
||||
auto handle = aFd.ClonePlatformHandle();
|
||||
mNextPageFD = PR_ImportFile(PROsfd(handle.release()));
|
||||
}
|
||||
|
||||
void
|
||||
RemotePrintJobChild::ProcessPage()
|
||||
{
|
||||
MOZ_ASSERT(mPagePrintTimer);
|
||||
|
||||
mPagePrintTimer->WaitForRemotePrint();
|
||||
Unused << SendProcessPage(aPageFileName);
|
||||
Unused << SendProcessPage();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
RemotePrintJobChild::RecvPageProcessed()
|
||||
RemotePrintJobChild::RecvPageProcessed(const mozilla::ipc::FileDescriptor& aFd)
|
||||
{
|
||||
MOZ_ASSERT(mPagePrintTimer);
|
||||
SetNextPageFD(aFd);
|
||||
|
||||
mPagePrintTimer->RemotePrintFinished();
|
||||
return IPC_OK();
|
||||
|
|
|
@ -34,11 +34,13 @@ public:
|
|||
const int32_t& aStartPage,
|
||||
const int32_t& aEndPage);
|
||||
|
||||
mozilla::ipc::IPCResult RecvPrintInitializationResult(const nsresult& aRv) final;
|
||||
mozilla::ipc::IPCResult RecvPrintInitializationResult(
|
||||
const nsresult& aRv,
|
||||
const FileDescriptor& aFd) final;
|
||||
|
||||
void ProcessPage(const nsCString& aPageFileName);
|
||||
void ProcessPage();
|
||||
|
||||
mozilla::ipc::IPCResult RecvPageProcessed() final;
|
||||
mozilla::ipc::IPCResult RecvPageProcessed(const FileDescriptor& aFd) final;
|
||||
|
||||
mozilla::ipc::IPCResult RecvAbortPrint(const nsresult& aRv) final;
|
||||
|
||||
|
@ -46,13 +48,17 @@ public:
|
|||
|
||||
void SetPrintEngine(nsPrintEngine* aPrintEngine);
|
||||
|
||||
PRFileDesc* GetNextPageFD();
|
||||
|
||||
private:
|
||||
~RemotePrintJobChild() final;
|
||||
void SetNextPageFD(const mozilla::ipc::FileDescriptor& aFd);
|
||||
|
||||
bool mPrintInitialized = false;
|
||||
nsresult mInitializationResult = NS_OK;
|
||||
RefPtr<nsPagePrintTimer> mPagePrintTimer;
|
||||
RefPtr<nsPrintEngine> mPrintEngine;
|
||||
PRFileDesc* mNextPageFD = nullptr;
|
||||
};
|
||||
|
||||
} // namespace layout
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
#include "nsIPrintSettings.h"
|
||||
#include "nsIWebProgressListener.h"
|
||||
#include "PrintTranslator.h"
|
||||
#include "private/pprio.h"
|
||||
#include "nsAnonymousTemporaryFile.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layout {
|
||||
|
@ -38,14 +40,21 @@ RemotePrintJobParent::RecvInitializePrint(const nsString& aDocumentTitle,
|
|||
nsresult rv = InitializePrintDevice(aDocumentTitle, aPrintToFile, aStartPage,
|
||||
aEndPage);
|
||||
if (NS_FAILED(rv)) {
|
||||
Unused << SendPrintInitializationResult(rv);
|
||||
Unused << SendPrintInitializationResult(rv, FileDescriptor());
|
||||
Unused << Send__delete__(this);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mPrintTranslator.reset(new PrintTranslator(mPrintDeviceContext));
|
||||
Unused << SendPrintInitializationResult(NS_OK);
|
||||
FileDescriptor fd;
|
||||
rv = PrepareNextPageFD(&fd);
|
||||
if (NS_FAILED(rv)) {
|
||||
Unused << SendPrintInitializationResult(rv, FileDescriptor());
|
||||
Unused << Send__delete__(this);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
Unused << SendPrintInitializationResult(NS_OK, fd);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
|
@ -82,22 +91,49 @@ RemotePrintJobParent::InitializePrintDevice(const nsString& aDocumentTitle,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
RemotePrintJobParent::RecvProcessPage(const nsCString& aPageFileName)
|
||||
nsresult
|
||||
RemotePrintJobParent::PrepareNextPageFD(FileDescriptor* aFd)
|
||||
{
|
||||
nsresult rv = PrintPage(aPageFileName);
|
||||
PRFileDesc* prFd = nullptr;
|
||||
nsresult rv = NS_OpenAnonymousTemporaryFile(&prFd);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
*aFd = FileDescriptor(
|
||||
FileDescriptor::PlatformHandleType(PR_FileDesc2NativeHandle(prFd)));
|
||||
mCurrentPageStream.OpenFD(prFd);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
RemotePrintJobParent::RecvProcessPage()
|
||||
{
|
||||
if (!mCurrentPageStream.IsOpen()) {
|
||||
Unused << SendAbortPrint(NS_ERROR_FAILURE);
|
||||
return IPC_OK();
|
||||
}
|
||||
mCurrentPageStream.Seek(0, PR_SEEK_SET);
|
||||
nsresult rv = PrintPage(mCurrentPageStream);
|
||||
mCurrentPageStream.Close();
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
Unused << SendAbortPrint(rv);
|
||||
} else {
|
||||
Unused << SendPageProcessed();
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
FileDescriptor fd;
|
||||
rv = PrepareNextPageFD(&fd);
|
||||
if (NS_FAILED(rv)) {
|
||||
Unused << SendAbortPrint(rv);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
Unused << SendPageProcessed(fd);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
nsresult
|
||||
RemotePrintJobParent::PrintPage(const nsCString& aPageFileName)
|
||||
RemotePrintJobParent::PrintPage(PRFileDescStream& aRecording)
|
||||
{
|
||||
MOZ_ASSERT(mPrintDeviceContext);
|
||||
|
||||
|
@ -105,29 +141,7 @@ RemotePrintJobParent::PrintPage(const nsCString& aPageFileName)
|
|||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIFile> recordingFile;
|
||||
rv = NS_GetSpecialDirectory(NS_APP_CONTENT_PROCESS_TEMP_DIR,
|
||||
getter_AddRefs(recordingFile));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = recordingFile->AppendNative(aPageFileName);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsAutoCString recordingPath;
|
||||
rv = recordingFile->GetNativePath(recordingPath);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
PRFileDescStream recording;
|
||||
recording.Open(recordingPath.get());
|
||||
MOZ_ASSERT(recording.IsOpen());
|
||||
if (!mPrintTranslator->TranslateRecording(recording)) {
|
||||
if (!mPrintTranslator->TranslateRecording(aRecording)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -136,12 +150,6 @@ RemotePrintJobParent::PrintPage(const nsCString& aPageFileName)
|
|||
return rv;
|
||||
}
|
||||
|
||||
recording.Close();
|
||||
rv = recordingFile->Remove(/* recursive= */ false);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,11 +8,13 @@
|
|||
#define mozilla_layout_RemotePrintJobParent_h
|
||||
|
||||
#include "mozilla/layout/PRemotePrintJobParent.h"
|
||||
#include "mozilla/layout/printing/DrawEventRecorder.h"
|
||||
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "mozilla/gfx/RecordedEvent.h"
|
||||
|
||||
class nsDeviceContext;
|
||||
class nsIPrintSettings;
|
||||
|
@ -34,7 +36,7 @@ public:
|
|||
const int32_t& aStartPage,
|
||||
const int32_t& aEndPage) final;
|
||||
|
||||
mozilla::ipc::IPCResult RecvProcessPage(const nsCString& aPageFileName) final;
|
||||
mozilla::ipc::IPCResult RecvProcessPage() final;
|
||||
|
||||
mozilla::ipc::IPCResult RecvFinalizePrint() final;
|
||||
|
||||
|
@ -70,12 +72,15 @@ private:
|
|||
const int32_t& aStartPage,
|
||||
const int32_t& aEndPage);
|
||||
|
||||
nsresult PrintPage(const nsCString& aPageFileName);
|
||||
nsresult PrepareNextPageFD(FileDescriptor* aFd);
|
||||
|
||||
nsresult PrintPage(PRFileDescStream& aRecording);
|
||||
|
||||
nsCOMPtr<nsIPrintSettings> mPrintSettings;
|
||||
RefPtr<nsDeviceContext> mPrintDeviceContext;
|
||||
UniquePtr<PrintTranslator> mPrintTranslator;
|
||||
nsCOMArray<nsIWebProgressListener> mPrintProgressListeners;
|
||||
PRFileDescStream mCurrentPageStream;
|
||||
};
|
||||
|
||||
} // namespace layout
|
||||
|
|
|
@ -145,7 +145,8 @@ nsPagePrintTimer::Notify(nsITimer *timer)
|
|||
|
||||
if (mDocViewerPrint) {
|
||||
bool donePrePrint = true;
|
||||
if (mPrintEngine) {
|
||||
// Don't start to pre-print if we're waiting on the parent still.
|
||||
if (mPrintEngine && !mWaitingForRemotePrint) {
|
||||
donePrePrint = mPrintEngine->PrePrintPage();
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "nsIPrintSession.h"
|
||||
#include "nsIPrintSettings.h"
|
||||
#include "nsIUUIDGenerator.h"
|
||||
#include "private/pprio.h"
|
||||
|
||||
using mozilla::Unused;
|
||||
|
||||
|
@ -65,17 +66,6 @@ nsDeviceContextSpecProxy::Init(nsIWidget* aWidget,
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
rv = NS_GetSpecialDirectory(NS_APP_CONTENT_PROCESS_TEMP_DIR,
|
||||
getter_AddRefs(mRecordingDir));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
mUuidGenerator = do_GetService("@mozilla.org/uuid-generator;1", &rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -143,48 +133,12 @@ nsDeviceContextSpecProxy::GetPrintingScale()
|
|||
return mRealDeviceContextSpec->GetPrintingScale();
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDeviceContextSpecProxy::CreateUniqueTempPath(nsACString& aFilePath)
|
||||
{
|
||||
MOZ_ASSERT(mRecordingDir);
|
||||
MOZ_ASSERT(mUuidGenerator);
|
||||
|
||||
nsID uuid;
|
||||
nsresult rv = mUuidGenerator->GenerateUUIDInPlace(&uuid);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
char uuidChars[NSID_LENGTH];
|
||||
uuid.ToProvidedString(uuidChars);
|
||||
mRecordingFileName.AssignASCII(uuidChars);
|
||||
|
||||
nsCOMPtr<nsIFile> recordingFile;
|
||||
rv = mRecordingDir->Clone(getter_AddRefs(recordingFile));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = recordingFile->AppendNative(mRecordingFileName);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return recordingFile->GetNativePath(aFilePath);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDeviceContextSpecProxy::BeginDocument(const nsAString& aTitle,
|
||||
const nsAString& aPrintToFileName,
|
||||
int32_t aStartPage, int32_t aEndPage)
|
||||
{
|
||||
nsAutoCString recordingPath;
|
||||
nsresult rv = CreateUniqueTempPath(recordingPath);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
mRecorder = new mozilla::layout::DrawEventRecorderPRFileDesc(recordingPath.get());
|
||||
mRecorder = new mozilla::layout::DrawEventRecorderPRFileDesc();
|
||||
return mRemotePrintJob->InitializePrint(nsString(aTitle),
|
||||
nsString(aPrintToFileName),
|
||||
aStartPage, aEndPage);
|
||||
|
@ -207,16 +161,7 @@ nsDeviceContextSpecProxy::AbortDocument()
|
|||
NS_IMETHODIMP
|
||||
nsDeviceContextSpecProxy::BeginPage()
|
||||
{
|
||||
// Reopen the file, if necessary, ready for the next page.
|
||||
if (!mRecorder->IsOpen()) {
|
||||
nsAutoCString recordingPath;
|
||||
nsresult rv = CreateUniqueTempPath(recordingPath);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
mRecorder->OpenNew(recordingPath.get());
|
||||
}
|
||||
mRecorder->OpenFD(mRemotePrintJob->GetNextPageFD());
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -226,7 +171,7 @@ nsDeviceContextSpecProxy::EndPage()
|
|||
{
|
||||
// Send the page recording to the parent.
|
||||
mRecorder->Close();
|
||||
mRemotePrintJob->ProcessPage(mRecordingFileName);
|
||||
mRemotePrintJob->ProcessPage();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -54,16 +54,11 @@ public:
|
|||
private:
|
||||
~nsDeviceContextSpecProxy() {}
|
||||
|
||||
nsresult CreateUniqueTempPath(nsACString& aFilePath);
|
||||
|
||||
nsCOMPtr<nsIPrintSettings> mPrintSettings;
|
||||
nsCOMPtr<nsIPrintSession> mPrintSession;
|
||||
nsCOMPtr<nsIDeviceContextSpec> mRealDeviceContextSpec;
|
||||
RefPtr<mozilla::layout::RemotePrintJobChild> mRemotePrintJob;
|
||||
RefPtr<mozilla::layout::DrawEventRecorderPRFileDesc> mRecorder;
|
||||
nsCOMPtr<nsIFile> mRecordingDir;
|
||||
nsCOMPtr<nsIUUIDGenerator> mUuidGenerator;
|
||||
nsCString mRecordingFileName;
|
||||
};
|
||||
|
||||
#endif // nsDeviceContextSpecProxy_h
|
||||
|
|
Загрузка…
Ссылка в новой задаче