import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo

This commit is contained in:
Roy Tam 2018-01-19 03:59:58 +08:00
commit dcd9973243
150858 changed files with 23884658 additions and 0 deletions

View file

@ -0,0 +1,102 @@
/* -*- 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 "PrintTranslator.h"
#include "gfxContext.h"
#include "nsDeviceContext.h"
#include "mozilla/gfx/RecordedEvent.h"
#include "mozilla/gfx/RecordingTypes.h"
#include "mozilla/UniquePtr.h"
using namespace mozilla::gfx;
namespace mozilla {
namespace layout {
PrintTranslator::PrintTranslator(nsDeviceContext* aDeviceContext)
: mDeviceContext(aDeviceContext)
{
RefPtr<gfxContext> context = mDeviceContext->CreateReferenceRenderingContext();
mBaseDT = context->GetDrawTarget();
}
bool
PrintTranslator::TranslateRecording(std::istream& aRecording)
{
uint32_t magicInt;
ReadElement(aRecording, magicInt);
if (magicInt != mozilla::gfx::kMagicInt) {
return false;
}
uint16_t majorRevision;
ReadElement(aRecording, majorRevision);
if (majorRevision != kMajorRevision) {
return false;
}
uint16_t minorRevision;
ReadElement(aRecording, minorRevision);
if (minorRevision > kMinorRevision) {
return false;
}
int32_t eventType;
ReadElement(aRecording, eventType);
while (aRecording.good()) {
UniquePtr<RecordedEvent> recordedEvent(
RecordedEvent::LoadEventFromStream(aRecording,
static_cast<RecordedEvent::EventType>(eventType)));
// Make sure that the whole event was read from the stream successfully.
if (!aRecording.good() || !recordedEvent) {
return false;
}
if (!recordedEvent->PlayEvent(this)) {
return false;
}
ReadElement(aRecording, eventType);
}
return true;
}
already_AddRefed<DrawTarget>
PrintTranslator::CreateDrawTarget(ReferencePtr aRefPtr,
const gfx::IntSize &aSize,
gfx::SurfaceFormat aFormat)
{
RefPtr<gfxContext> context = mDeviceContext->CreateRenderingContext();
if (!context) {
NS_WARNING("Failed to create rendering context for print.");
return nullptr;
}
RefPtr<DrawTarget> drawTarget = context->GetDrawTarget();
AddDrawTarget(aRefPtr, drawTarget);
return drawTarget.forget();
}
FontType
PrintTranslator::GetDesiredFontType()
{
switch (mBaseDT->GetBackendType()) {
case BackendType::DIRECT2D:
return FontType::DWRITE;
case BackendType::CAIRO:
return FontType::CAIRO;
case BackendType::SKIA:
return FontType::SKIA;
default:
return FontType::CAIRO;
}
}
} // namespace layout
} // namespace mozilla

View file

@ -0,0 +1,178 @@
/* -*- 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/. */
#ifndef mozilla_layout_PrintTranslator_h
#define mozilla_layout_PrintTranslator_h
#include <istream>
#include "mozilla/gfx/2D.h"
#include "mozilla/gfx/Filters.h"
#include "mozilla/gfx/RecordedEvent.h"
#include "nsRefPtrHashtable.h"
class nsDeviceContext;
namespace mozilla {
namespace layout {
using gfx::Translator;
using gfx::ReferencePtr;
using gfx::DrawTarget;
using gfx::Path;
using gfx::SourceSurface;
using gfx::FilterNode;
using gfx::GradientStops;
using gfx::ScaledFont;
using gfx::NativeFontResource;
class PrintTranslator final : public Translator
{
public:
explicit PrintTranslator(nsDeviceContext* aDeviceContext);
bool TranslateRecording(std::istream& aRecording);
DrawTarget* LookupDrawTarget(ReferencePtr aRefPtr) final
{
DrawTarget* result = mDrawTargets.GetWeak(aRefPtr);
MOZ_ASSERT(result);
return result;
}
Path* LookupPath(ReferencePtr aRefPtr) final
{
Path* result = mPaths.GetWeak(aRefPtr);
MOZ_ASSERT(result);
return result;
}
SourceSurface* LookupSourceSurface(ReferencePtr aRefPtr) final
{
SourceSurface* result = mSourceSurfaces.GetWeak(aRefPtr);
MOZ_ASSERT(result);
return result;
}
FilterNode* LookupFilterNode(ReferencePtr aRefPtr) final
{
FilterNode* result = mFilterNodes.GetWeak(aRefPtr);
MOZ_ASSERT(result);
return result;
}
GradientStops* LookupGradientStops(ReferencePtr aRefPtr) final
{
GradientStops* result = mGradientStops.GetWeak(aRefPtr);
MOZ_ASSERT(result);
return result;
}
ScaledFont* LookupScaledFont(ReferencePtr aRefPtr) final
{
ScaledFont* result = mScaledFonts.GetWeak(aRefPtr);
MOZ_ASSERT(result);
return result;
}
NativeFontResource* LookupNativeFontResource(uint64_t aKey) final
{
NativeFontResource* result = mNativeFontResources.GetWeak(aKey);
MOZ_ASSERT(result);
return result;
}
void AddDrawTarget(ReferencePtr aRefPtr, DrawTarget *aDT) final
{
mDrawTargets.Put(aRefPtr, aDT);
}
void AddPath(ReferencePtr aRefPtr, Path *aPath) final
{
mPaths.Put(aRefPtr, aPath);
}
void AddSourceSurface(ReferencePtr aRefPtr, SourceSurface *aSurface) final
{
mSourceSurfaces.Put(aRefPtr, aSurface);
}
void AddFilterNode(ReferencePtr aRefPtr, FilterNode *aFilter) final
{
mFilterNodes.Put(aRefPtr, aFilter);
}
void AddGradientStops(ReferencePtr aRefPtr, GradientStops *aStops) final
{
mGradientStops.Put(aRefPtr, aStops);
}
void AddScaledFont(ReferencePtr aRefPtr, ScaledFont *aScaledFont) final
{
mScaledFonts.Put(aRefPtr, aScaledFont);
}
void AddNativeFontResource(uint64_t aKey,
NativeFontResource *aScaledFontResouce) final
{
mNativeFontResources.Put(aKey, aScaledFontResouce);
}
void RemoveDrawTarget(ReferencePtr aRefPtr) final
{
mDrawTargets.Remove(aRefPtr);
}
void RemovePath(ReferencePtr aRefPtr) final
{
mPaths.Remove(aRefPtr);
}
void RemoveSourceSurface(ReferencePtr aRefPtr) final
{
mSourceSurfaces.Remove(aRefPtr);
}
void RemoveFilterNode(ReferencePtr aRefPtr) final
{
mFilterNodes.Remove(aRefPtr);
}
void RemoveGradientStops(ReferencePtr aRefPtr) final
{
mGradientStops.Remove(aRefPtr);
}
void RemoveScaledFont(ReferencePtr aRefPtr) final
{
mScaledFonts.Remove(aRefPtr);
}
already_AddRefed<DrawTarget> CreateDrawTarget(ReferencePtr aRefPtr,
const gfx::IntSize &aSize,
gfx::SurfaceFormat aFormat) final;
mozilla::gfx::DrawTarget* GetReferenceDrawTarget() final { return mBaseDT; }
mozilla::gfx::FontType GetDesiredFontType() final;
private:
RefPtr<nsDeviceContext> mDeviceContext;
RefPtr<DrawTarget> mBaseDT;
nsRefPtrHashtable<nsPtrHashKey<void>, DrawTarget> mDrawTargets;
nsRefPtrHashtable<nsPtrHashKey<void>, Path> mPaths;
nsRefPtrHashtable<nsPtrHashKey<void>, SourceSurface> mSourceSurfaces;
nsRefPtrHashtable<nsPtrHashKey<void>, FilterNode> mFilterNodes;
nsRefPtrHashtable<nsPtrHashKey<void>, GradientStops> mGradientStops;
nsRefPtrHashtable<nsPtrHashKey<void>, ScaledFont> mScaledFonts;
nsRefPtrHashtable<nsUint64HashKey, NativeFontResource> mNativeFontResources;
};
} // namespace layout
} // namespace mozilla
#endif // mozilla_layout_PrintTranslator_h

View file

@ -0,0 +1,10 @@
<html class="reftest-print"><head>
<title>Crash [@ nsViewManager::CreateView][@ nsCSSFrameConstructor::AddFrameConstructionItemsInternal] on closing print preview with -moz-transform, position: fixed table displays</title>
</head><body>
<div style="position: fixed;">
<div style="display: table-header-group; -moz-transform: rotate(1deg);">
<div style="position: relative;"></div>
<div style="display: table-row;page-break-before: always;"></div>
</div>
</body>
</html>

View file

@ -0,0 +1,8 @@
<html style="position: fixed; -moz-transform: scale(0.000001);" class="reftest-print">
<head>
</head>
<body>
<div style="display: table-row;"></div>
<div style="display: table-row; page-break-before: right;"></div>
</body>
</html>

View file

@ -0,0 +1,9 @@
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:mathml="http://www.w3.org/1998/Math/MathML" class="reftest-print">
<mathml:mfenced style="position: fixed;">
<span style="position: inherit; float: right;"><span style="position:fixed;">b</span></span>
</mathml:mfenced>
<div style="page-break-before: always; "/>
m
</html>

View file

@ -0,0 +1,10 @@
<html class="reftest-print">
<head>
<title>crash in nsContentList::nsContentList on print preview</title>
</head><body>
<iframe onload="window.location.reload()" src="data:text/html,">
</iframe>
</body></html>

View file

@ -0,0 +1,4 @@
load 509839-1.html
load 509839-2.html
asserts-if(browserIsRemote,4) load 576878.xhtml
load 793844.html

View file

@ -0,0 +1,58 @@
/* -*- 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 protocol PPrinting;
namespace mozilla {
namespace layout {
async protocol PRemotePrintJob
{
manager PPrinting;
both:
// Tell either side to abort printing and clean up.
async AbortPrint(nsresult aRv);
parent:
// Initialize the real print device with the given information.
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);
// This informs the real print device that we've finished, so it can trigger
// the actual print.
async FinalizePrint();
// Report a state change to listeners in the parent process.
async StateChange(long aStateFlags,
nsresult aStatus);
// Report a progress change to listeners in the parent process.
async ProgressChange(long aCurSelfProgress,
long aMaxSelfProgress,
long aCurTotalProgress,
long aMaxTotalProgress);
// Report a status change to listeners in the parent process.
async StatusChange(nsresult aStatus);
child:
// Inform the child that the print has been initialized in the parent or has
// failed with result aRv.
async PrintInitializationResult(nsresult aRv);
// Inform the child that the latest page has been processed remotely.
async PageProcessed();
async __delete__();
};
} // namespace layout
} // namespace mozilla

View file

@ -0,0 +1,155 @@
/* -*- 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 "RemotePrintJobChild.h"
#include "mozilla/Unused.h"
#include "nsPagePrintTimer.h"
#include "nsPrintEngine.h"
namespace mozilla {
namespace layout {
NS_IMPL_ISUPPORTS(RemotePrintJobChild,
nsIWebProgressListener)
RemotePrintJobChild::RemotePrintJobChild()
{
MOZ_COUNT_CTOR(RemotePrintJobChild);
}
nsresult
RemotePrintJobChild::InitializePrint(const nsString& aDocumentTitle,
const nsString& aPrintToFile,
const int32_t& aStartPage,
const int32_t& aEndPage)
{
// Print initialization can sometimes display a dialog in the parent, so we
// need to spin a nested event loop until initialization completes.
Unused << SendInitializePrint(aDocumentTitle, aPrintToFile, aStartPage,
aEndPage);
while (!mPrintInitialized) {
Unused << NS_ProcessNextEvent();
}
return mInitializationResult;
}
bool
RemotePrintJobChild::RecvPrintInitializationResult(const nsresult& aRv)
{
mPrintInitialized = true;
mInitializationResult = aRv;
return true;
}
void
RemotePrintJobChild::ProcessPage(const nsCString& aPageFileName)
{
MOZ_ASSERT(mPagePrintTimer);
mPagePrintTimer->WaitForRemotePrint();
Unused << SendProcessPage(aPageFileName);
}
bool
RemotePrintJobChild::RecvPageProcessed()
{
MOZ_ASSERT(mPagePrintTimer);
mPagePrintTimer->RemotePrintFinished();
return true;
}
bool
RemotePrintJobChild::RecvAbortPrint(const nsresult& aRv)
{
MOZ_ASSERT(mPrintEngine);
mPrintEngine->CleanupOnFailure(aRv, true);
return true;
}
void
RemotePrintJobChild::SetPagePrintTimer(nsPagePrintTimer* aPagePrintTimer)
{
MOZ_ASSERT(aPagePrintTimer);
mPagePrintTimer = aPagePrintTimer;
}
void
RemotePrintJobChild::SetPrintEngine(nsPrintEngine* aPrintEngine)
{
MOZ_ASSERT(aPrintEngine);
mPrintEngine = aPrintEngine;
}
// nsIWebProgressListener
NS_IMETHODIMP
RemotePrintJobChild::OnStateChange(nsIWebProgress* aProgress,
nsIRequest* aRequest, uint32_t aStateFlags,
nsresult aStatus)
{
Unused << SendStateChange(aStateFlags, aStatus);
return NS_OK;
}
NS_IMETHODIMP
RemotePrintJobChild::OnProgressChange(nsIWebProgress * aProgress,
nsIRequest * aRequest,
int32_t aCurSelfProgress,
int32_t aMaxSelfProgress,
int32_t aCurTotalProgress,
int32_t aMaxTotalProgress)
{
Unused << SendProgressChange(aCurSelfProgress, aMaxSelfProgress,
aCurTotalProgress, aMaxTotalProgress);
return NS_OK;
}
NS_IMETHODIMP
RemotePrintJobChild::OnLocationChange(nsIWebProgress* aProgress,
nsIRequest* aRequest, nsIURI* aURI,
uint32_t aFlags)
{
return NS_OK;
}
NS_IMETHODIMP
RemotePrintJobChild::OnStatusChange(nsIWebProgress* aProgress,
nsIRequest* aRequest, nsresult aStatus,
const char16_t* aMessage)
{
Unused << SendStatusChange(aStatus);
return NS_OK;
}
NS_IMETHODIMP
RemotePrintJobChild::OnSecurityChange(nsIWebProgress* aProgress,
nsIRequest* aRequest, uint32_t aState)
{
return NS_OK;
}
// End of nsIWebProgressListener
RemotePrintJobChild::~RemotePrintJobChild()
{
MOZ_COUNT_DTOR(RemotePrintJobChild);
}
void
RemotePrintJobChild::ActorDestroy(ActorDestroyReason aWhy)
{
mPagePrintTimer = nullptr;
mPrintEngine = nullptr;
}
} // namespace layout
} // namespace mozilla

View file

@ -0,0 +1,61 @@
/* -*- 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/. */
#ifndef mozilla_layout_RemotePrintJobChild_h
#define mozilla_layout_RemotePrintJobChild_h
#include "mozilla/layout/PRemotePrintJobChild.h"
#include "mozilla/RefPtr.h"
#include "nsIWebProgressListener.h"
class nsPagePrintTimer;
class nsPrintEngine;
namespace mozilla {
namespace layout {
class RemotePrintJobChild final : public PRemotePrintJobChild
, public nsIWebProgressListener
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIWEBPROGRESSLISTENER
RemotePrintJobChild();
void ActorDestroy(ActorDestroyReason aWhy) final;
nsresult InitializePrint(const nsString& aDocumentTitle,
const nsString& aPrintToFile,
const int32_t& aStartPage,
const int32_t& aEndPage);
bool RecvPrintInitializationResult(const nsresult& aRv) final;
void ProcessPage(const nsCString& aPageFileName);
bool RecvPageProcessed() final;
bool RecvAbortPrint(const nsresult& aRv) final;
void SetPagePrintTimer(nsPagePrintTimer* aPagePrintTimer);
void SetPrintEngine(nsPrintEngine* aPrintEngine);
private:
~RemotePrintJobChild() final;
bool mPrintInitialized = false;
nsresult mInitializationResult = NS_OK;
RefPtr<nsPagePrintTimer> mPagePrintTimer;
RefPtr<nsPrintEngine> mPrintEngine;
};
} // namespace layout
} // namespace mozilla
#endif // mozilla_layout_RemotePrintJobChild_h

View file

@ -0,0 +1,244 @@
/* -*- 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 "RemotePrintJobParent.h"
#include <fstream>
#include "gfxContext.h"
#include "mozilla/Attributes.h"
#include "mozilla/Unused.h"
#include "nsAppDirectoryServiceDefs.h"
#include "nsComponentManagerUtils.h"
#include "nsDirectoryServiceUtils.h"
#include "nsDeviceContext.h"
#include "nsIDeviceContextSpec.h"
#include "nsIPrintSettings.h"
#include "nsIWebProgressListener.h"
#include "PrintTranslator.h"
namespace mozilla {
namespace layout {
RemotePrintJobParent::RemotePrintJobParent(nsIPrintSettings* aPrintSettings)
: mPrintSettings(aPrintSettings)
{
MOZ_COUNT_CTOR(RemotePrintJobParent);
}
bool
RemotePrintJobParent::RecvInitializePrint(const nsString& aDocumentTitle,
const nsString& aPrintToFile,
const int32_t& aStartPage,
const int32_t& aEndPage)
{
nsresult rv = InitializePrintDevice(aDocumentTitle, aPrintToFile, aStartPage,
aEndPage);
if (NS_FAILED(rv)) {
Unused << SendPrintInitializationResult(rv);
Unused << Send__delete__(this);
return true;
}
mPrintTranslator.reset(new PrintTranslator(mPrintDeviceContext));
Unused << SendPrintInitializationResult(NS_OK);
return true;
}
nsresult
RemotePrintJobParent::InitializePrintDevice(const nsString& aDocumentTitle,
const nsString& aPrintToFile,
const int32_t& aStartPage,
const int32_t& aEndPage)
{
nsresult rv;
nsCOMPtr<nsIDeviceContextSpec> deviceContextSpec =
do_CreateInstance("@mozilla.org/gfx/devicecontextspec;1", &rv);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = deviceContextSpec->Init(nullptr, mPrintSettings, false);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
mPrintDeviceContext = new nsDeviceContext();
rv = mPrintDeviceContext->InitForPrinting(deviceContextSpec);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = mPrintDeviceContext->BeginDocument(aDocumentTitle, aPrintToFile,
aStartPage, aEndPage);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
bool
RemotePrintJobParent::RecvProcessPage(const nsCString& aPageFileName)
{
nsresult rv = PrintPage(aPageFileName);
if (NS_FAILED(rv)) {
Unused << SendAbortPrint(rv);
} else {
Unused << SendPageProcessed();
}
return true;
}
nsresult
RemotePrintJobParent::PrintPage(const nsCString& aPageFileName)
{
MOZ_ASSERT(mPrintDeviceContext);
nsresult rv = mPrintDeviceContext->BeginPage();
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;
}
std::ifstream recording(recordingPath.get(), std::ifstream::binary);
if (!mPrintTranslator->TranslateRecording(recording)) {
return NS_ERROR_FAILURE;
}
rv = mPrintDeviceContext->EndPage();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
recording.close();
rv = recordingFile->Remove(/* recursive= */ false);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
bool
RemotePrintJobParent::RecvFinalizePrint()
{
// EndDocument is sometimes called in the child even when BeginDocument has
// not been called. See bug 1223332.
if (mPrintDeviceContext) {
DebugOnly<nsresult> rv = mPrintDeviceContext->EndDocument();
// Too late to abort the child just log.
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "EndDocument failed");
}
Unused << Send__delete__(this);
return true;
}
bool
RemotePrintJobParent::RecvAbortPrint(const nsresult& aRv)
{
if (mPrintDeviceContext) {
Unused << mPrintDeviceContext->AbortDocument();
}
Unused << Send__delete__(this);
return true;
}
bool
RemotePrintJobParent::RecvStateChange(const long& aStateFlags,
const nsresult& aStatus)
{
uint32_t numberOfListeners = mPrintProgressListeners.Length();
for (uint32_t i = 0; i < numberOfListeners; ++i) {
nsIWebProgressListener* listener = mPrintProgressListeners.SafeElementAt(i);
listener->OnStateChange(nullptr, nullptr, aStateFlags, aStatus);
}
return true;
}
bool
RemotePrintJobParent::RecvProgressChange(const long& aCurSelfProgress,
const long& aMaxSelfProgress,
const long& aCurTotalProgress,
const long& aMaxTotalProgress)
{
uint32_t numberOfListeners = mPrintProgressListeners.Length();
for (uint32_t i = 0; i < numberOfListeners; ++i) {
nsIWebProgressListener* listener = mPrintProgressListeners.SafeElementAt(i);
listener->OnProgressChange(nullptr, nullptr,
aCurSelfProgress, aMaxSelfProgress,
aCurTotalProgress, aMaxTotalProgress);
}
return true;
}
bool
RemotePrintJobParent::RecvStatusChange(const nsresult& aStatus)
{
uint32_t numberOfListeners = mPrintProgressListeners.Length();
for (uint32_t i = 0; i < numberOfListeners; ++i) {
nsIWebProgressListener* listener = mPrintProgressListeners.SafeElementAt(i);
listener->OnStatusChange(nullptr, nullptr, aStatus, nullptr);
}
return true;
}
void
RemotePrintJobParent::RegisterListener(nsIWebProgressListener* aListener)
{
MOZ_ASSERT(aListener);
mPrintProgressListeners.AppendElement(aListener);
}
already_AddRefed<nsIPrintSettings>
RemotePrintJobParent::GetPrintSettings()
{
nsCOMPtr<nsIPrintSettings> printSettings = mPrintSettings;
return printSettings.forget();
}
RemotePrintJobParent::~RemotePrintJobParent()
{
MOZ_COUNT_DTOR(RemotePrintJobParent);
}
void
RemotePrintJobParent::ActorDestroy(ActorDestroyReason aWhy)
{
}
} // namespace layout
} // namespace mozilla

View file

@ -0,0 +1,84 @@
/* -*- 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/. */
#ifndef mozilla_layout_RemotePrintJobParent_h
#define mozilla_layout_RemotePrintJobParent_h
#include "mozilla/layout/PRemotePrintJobParent.h"
#include "nsCOMArray.h"
#include "nsCOMPtr.h"
#include "mozilla/RefPtr.h"
#include "mozilla/UniquePtr.h"
class nsDeviceContext;
class nsIPrintSettings;
class nsIWebProgressListener;
class PrintTranslator;
namespace mozilla {
namespace layout {
class RemotePrintJobParent final : public PRemotePrintJobParent
{
public:
explicit RemotePrintJobParent(nsIPrintSettings* aPrintSettings);
void ActorDestroy(ActorDestroyReason aWhy) final;
bool RecvInitializePrint(const nsString& aDocumentTitle,
const nsString& aPrintToFile,
const int32_t& aStartPage,
const int32_t& aEndPage) final;
bool RecvProcessPage(const nsCString& aPageFileName) final;
bool RecvFinalizePrint() final;
bool RecvAbortPrint(const nsresult& aRv) final;
bool RecvStateChange(const long& aStateFlags,
const nsresult& aStatus) final;
bool RecvProgressChange(const long& aCurSelfProgress,
const long& aMaxSelfProgress,
const long& aCurTotalProgress,
const long& aMaxTotalProgress) final;
bool RecvStatusChange(const nsresult& aStatus) final;
/**
* Register a progress listener to receive print progress updates.
*
* @param aListener the progress listener to register. Must not be null.
*/
void RegisterListener(nsIWebProgressListener* aListener);
/**
* @return the print settings for this remote print job.
*/
already_AddRefed<nsIPrintSettings> GetPrintSettings();
private:
~RemotePrintJobParent() final;
nsresult InitializePrintDevice(const nsString& aDocumentTitle,
const nsString& aPrintToFile,
const int32_t& aStartPage,
const int32_t& aEndPage);
nsresult PrintPage(const nsCString& aPageFileName);
nsCOMPtr<nsIPrintSettings> mPrintSettings;
RefPtr<nsDeviceContext> mPrintDeviceContext;
UniquePtr<PrintTranslator> mPrintTranslator;
nsCOMArray<nsIWebProgressListener> mPrintProgressListeners;
};
} // namespace layout
} // namespace mozilla
#endif // mozilla_layout_RemotePrintJobParent_h

37
layout/printing/moz.build Normal file
View file

@ -0,0 +1,37 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
XPIDL_SOURCES += [
'nsIPrintProgress.idl',
'nsIPrintProgressParams.idl',
'nsIPrintStatusFeedback.idl',
]
EXPORTS.mozilla.layout += [
'ipc/RemotePrintJobChild.h',
'ipc/RemotePrintJobParent.h',
]
XPIDL_MODULE = 'layout_printing'
UNIFIED_SOURCES += [
'ipc/RemotePrintJobChild.cpp',
'ipc/RemotePrintJobParent.cpp',
'nsPagePrintTimer.cpp',
'nsPrintData.cpp',
'nsPrintEngine.cpp',
'nsPrintObject.cpp',
'nsPrintPreviewListener.cpp',
'PrintTranslator.cpp',
]
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'
LOCAL_INCLUDES += [
'../base',
'/dom/base',
]

View file

@ -0,0 +1,43 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 "nsIWebProgressListener.idl"
interface mozIDOMWindowProxy;
interface nsIObserver;
interface nsIPrompt;
[scriptable, uuid(05f4fb88-e568-4d35-b394-ce0aa3eea6fc)]
interface nsIPrintProgress: nsIWebProgressListener {
/* Open the progress dialog
you can specify parameters through an xpcom object
*/
void openProgressDialog(in mozIDOMWindowProxy parent,
in string dialogURL,
in nsISupports parameters,
in nsIObserver openDialogObserver,
out boolean notifyOnOpen);
/* Close the progress dialog */
void closeProgressDialog(in boolean forceClose);
/* Register a Web Progress Listener */
void registerListener(in nsIWebProgressListener listener);
/* Unregister a Web Progress Listener */
void unregisterListener(in nsIWebProgressListener listener);
/* This method is called after the dialog that shows the progress has been shown
*/
void doneIniting();
/* Retrieve the prompter, needed to display modal dialog on top of progress dialog */
nsIPrompt getPrompter();
/* Indicated if the user asked to cancel the current process */
attribute boolean processCanceledByUser;
};

View file

@ -0,0 +1,14 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 "nsISupports.idl"
[scriptable, uuid(CA89B55B-6FAF-4051-9645-1C03EF5108F8)]
interface nsIPrintProgressParams: nsISupports {
/* message subject */
attribute wstring docTitle;
attribute wstring docURL;
};

View file

@ -0,0 +1,23 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 "nsISupports.idl"
interface nsIDocShell;
interface mozIDOMWindowProxy;
/**
* XXX This interface seems to be unimplemented and unused.
*/
[scriptable, uuid(8eb6ffc9-715c-487e-927c-c56139229548)]
interface nsIPrintStatusFeedback : nsISupports {
void showStatusString(in wstring status);
void startMeteors();
void stopMeteors();
void showProgress(in long percent);
[noscript] void setDocShell(in nsIDocShell shell, in mozIDOMWindowProxy window);
void closeWindow();
};

View file

@ -0,0 +1,224 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 "nsPagePrintTimer.h"
#include "mozilla/Unused.h"
#include "nsIContentViewer.h"
#include "nsIServiceManager.h"
#include "nsPrintEngine.h"
NS_IMPL_ISUPPORTS_INHERITED(nsPagePrintTimer, mozilla::Runnable, nsITimerCallback)
nsPagePrintTimer::~nsPagePrintTimer()
{
// "Destroy" the document viewer; this normally doesn't actually
// destroy it because of the IncrementDestroyRefCount call below
// XXX This is messy; the document viewer should use a single approach
// to keep itself alive during printing
nsCOMPtr<nsIContentViewer> cv(do_QueryInterface(mDocViewerPrint));
if (cv) {
cv->Destroy();
}
}
nsresult
nsPagePrintTimer::StartTimer(bool aUseDelay)
{
nsresult result;
mTimer = do_CreateInstance("@mozilla.org/timer;1", &result);
if (NS_FAILED(result)) {
NS_WARNING("unable to start the timer");
} else {
uint32_t delay = 0;
if (aUseDelay) {
if (mFiringCount < 10) {
// Longer delay for the few first pages.
delay = mDelay + ((10 - mFiringCount) * 100);
} else {
delay = mDelay;
}
}
mTimer->InitWithCallback(this, delay, nsITimer::TYPE_ONE_SHOT);
}
return result;
}
nsresult
nsPagePrintTimer::StartWatchDogTimer()
{
nsresult result;
if (mWatchDogTimer) {
mWatchDogTimer->Cancel();
}
mWatchDogTimer = do_CreateInstance("@mozilla.org/timer;1", &result);
if (NS_FAILED(result)) {
NS_WARNING("unable to start the timer");
} else {
// Instead of just doing one timer for a long period do multiple so we
// can check if the user cancelled the printing.
mWatchDogTimer->InitWithCallback(this, WATCH_DOG_INTERVAL,
nsITimer::TYPE_ONE_SHOT);
}
return result;
}
void
nsPagePrintTimer::StopWatchDogTimer()
{
if (mWatchDogTimer) {
mWatchDogTimer->Cancel();
mWatchDogTimer = nullptr;
}
}
//nsRunnable
NS_IMETHODIMP
nsPagePrintTimer::Run()
{
bool initNewTimer = true;
// Check to see if we are done
// inRange will be true if a page is actually printed
bool inRange;
bool donePrinting;
// donePrinting will be true if it completed successfully or
// if the printing was cancelled
donePrinting = !mPrintEngine || mPrintEngine->PrintPage(mPrintObj, inRange);
if (donePrinting) {
// now clean up print or print the next webshell
if (!mPrintEngine || mPrintEngine->DonePrintingPages(mPrintObj, NS_OK)) {
initNewTimer = false;
mDone = true;
}
}
// Note that the Stop() destroys this after the print job finishes
// (The PrintEngine stops holding a reference when DonePrintingPages
// returns true.)
Stop();
if (initNewTimer) {
++mFiringCount;
nsresult result = StartTimer(inRange);
if (NS_FAILED(result)) {
mDone = true; // had a failure.. we are finished..
if (mPrintEngine) {
mPrintEngine->SetIsPrinting(false);
}
}
}
return NS_OK;
}
// nsITimerCallback
NS_IMETHODIMP
nsPagePrintTimer::Notify(nsITimer *timer)
{
// When finished there may be still pending notifications, which we can just
// ignore.
if (mDone) {
return NS_OK;
}
// There are four things that call Notify with different values for timer:
// 1) the delay between pages (timer == mTimer)
// 2) canvasPrintState done (timer == null)
// 3) the watch dog timer (timer == mWatchDogTimer)
// 4) the waiting for remote print "timer" (timer == mWaitingForRemotePrint)
if (!timer) {
// Reset the counter since a mozPrintCallback has finished.
mWatchDogCount = 0;
} else if (timer == mTimer) {
// Reset the watchdog timer before the start of every page.
mWatchDogCount = 0;
mTimer = nullptr;
} else if (timer == mWaitingForRemotePrint) {
mWaitingForRemotePrint = nullptr;
// If we are still waiting for the page delay timer, don't let the
// notification from the remote print job trigger the next page.
if (mTimer) {
return NS_OK;
}
} else if (timer == mWatchDogTimer) {
mWatchDogCount++;
if (mWatchDogCount > WATCH_DOG_MAX_COUNT) {
Fail();
return NS_OK;
}
}
if (mDocViewerPrint) {
bool donePrePrint = true;
if (mPrintEngine) {
donePrePrint = mPrintEngine->PrePrintPage();
}
if (donePrePrint && !mWaitingForRemotePrint) {
StopWatchDogTimer();
NS_DispatchToMainThread(this);
} else {
// Start the watch dog if we're waiting for preprint to ensure that if any
// mozPrintCallbacks take to long we error out.
StartWatchDogTimer();
}
}
return NS_OK;
}
void
nsPagePrintTimer::WaitForRemotePrint()
{
nsresult result;
mWaitingForRemotePrint = do_CreateInstance("@mozilla.org/timer;1", &result);
if (NS_FAILED(result)) {
NS_WARNING("Failed to wait for remote print, we might time-out.");
mWaitingForRemotePrint = nullptr;
}
}
void
nsPagePrintTimer::RemotePrintFinished()
{
if (!mWaitingForRemotePrint) {
return;
}
mozilla::Unused <<
mWaitingForRemotePrint->InitWithCallback(this, 0, nsITimer::TYPE_ONE_SHOT);
}
nsresult
nsPagePrintTimer::Start(nsPrintObject* aPO)
{
mPrintObj = aPO;
mDone = false;
return StartTimer(false);
}
void
nsPagePrintTimer::Stop()
{
if (mTimer) {
mTimer->Cancel();
mTimer = nullptr;
}
StopWatchDogTimer();
}
void
nsPagePrintTimer::Fail()
{
NS_WARNING("nsPagePrintTimer::Fail called");
mDone = true;
Stop();
if (mPrintEngine) {
mPrintEngine->CleanupOnFailure(NS_OK, false);
}
}

View file

@ -0,0 +1,93 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#ifndef nsPagePrintTimer_h___
#define nsPagePrintTimer_h___
// Timer Includes
#include "nsITimer.h"
#include "nsIDocumentViewerPrint.h"
#include "nsPrintObject.h"
#include "mozilla/Attributes.h"
#include "nsThreadUtils.h"
class nsPrintEngine;
//---------------------------------------------------
//-- Page Timer Class
//---------------------------------------------------
class nsPagePrintTimer final : public mozilla::Runnable,
public nsITimerCallback
{
public:
NS_DECL_ISUPPORTS_INHERITED
nsPagePrintTimer(nsPrintEngine* aPrintEngine,
nsIDocumentViewerPrint* aDocViewerPrint,
uint32_t aDelay)
: mPrintEngine(aPrintEngine)
, mDocViewerPrint(aDocViewerPrint)
, mDelay(aDelay)
, mFiringCount(0)
, mPrintObj(nullptr)
, mWatchDogCount(0)
, mDone(false)
{
mDocViewerPrint->IncrementDestroyRefCount();
}
NS_DECL_NSITIMERCALLBACK
nsresult Start(nsPrintObject* aPO);
NS_IMETHOD Run() override;
void Stop();
void WaitForRemotePrint();
void RemotePrintFinished();
void Disconnect()
{
mPrintEngine = nullptr;
mPrintObj = nullptr;
}
private:
~nsPagePrintTimer();
nsresult StartTimer(bool aUseDelay);
nsresult StartWatchDogTimer();
void StopWatchDogTimer();
void Fail();
nsPrintEngine* mPrintEngine;
nsCOMPtr<nsIDocumentViewerPrint> mDocViewerPrint;
nsCOMPtr<nsITimer> mTimer;
nsCOMPtr<nsITimer> mWatchDogTimer;
nsCOMPtr<nsITimer> mWaitingForRemotePrint;
uint32_t mDelay;
uint32_t mFiringCount;
nsPrintObject * mPrintObj;
uint32_t mWatchDogCount;
bool mDone;
static const uint32_t WATCH_DOG_INTERVAL = 1000;
static const uint32_t WATCH_DOG_MAX_COUNT =
#ifdef DEBUG
// Debug builds are very slow (on Mac at least) and can need extra time
30
#else
10
#endif
;
};
nsresult
NS_NewPagePrintTimer(nsPagePrintTimer **aResult);
#endif /* nsPagePrintTimer_h___ */

View file

@ -0,0 +1,140 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 "nsPrintData.h"
#include "nsIStringBundle.h"
#include "nsIServiceManager.h"
#include "nsPrintObject.h"
#include "nsPrintPreviewListener.h"
#include "nsIWebProgressListener.h"
#include "mozilla/Services.h"
//-----------------------------------------------------
// PR LOGGING
#include "mozilla/Logging.h"
#define DUMP_LAYOUT_LEVEL 9 // this turns on the dumping of each doucment's layout info
static mozilla::LazyLogModule gPrintingLog("printing");
#define PR_PL(_p1) MOZ_LOG(gPrintingLog, mozilla::LogLevel::Debug, _p1);
//---------------------------------------------------
//-- nsPrintData Class Impl
//---------------------------------------------------
nsPrintData::nsPrintData(ePrintDataType aType) :
mType(aType), mDebugFilePtr(nullptr), mPrintObject(nullptr), mSelectedPO(nullptr),
mPrintDocList(0), mIsIFrameSelected(false),
mIsParentAFrameSet(false), mOnStartSent(false),
mIsAborted(false), mPreparingForPrint(false), mDocWasToBeDestroyed(false),
mShrinkToFit(false), mPrintFrameType(nsIPrintSettings::kFramesAsIs),
mNumPrintablePages(0), mNumPagesPrinted(0),
mShrinkRatio(1.0), mOrigDCScale(1.0), mPPEventListeners(nullptr),
mBrandName(nullptr)
{
nsCOMPtr<nsIStringBundle> brandBundle;
nsCOMPtr<nsIStringBundleService> svc =
mozilla::services::GetStringBundleService();
if (svc) {
svc->CreateBundle( "chrome://branding/locale/brand.properties", getter_AddRefs( brandBundle ) );
if (brandBundle) {
brandBundle->GetStringFromName(u"brandShortName", &mBrandName );
}
}
if (!mBrandName) {
mBrandName = ToNewUnicode(NS_LITERAL_STRING("Mozilla Document"));
}
}
nsPrintData::~nsPrintData()
{
// remove the event listeners
if (mPPEventListeners) {
mPPEventListeners->RemoveListeners();
NS_RELEASE(mPPEventListeners);
}
// Only Send an OnEndPrinting if we have started printing
if (mOnStartSent && mType != eIsPrintPreview) {
OnEndPrinting();
}
if (mPrintDC && !mDebugFilePtr) {
PR_PL(("****************** End Document ************************\n"));
PR_PL(("\n"));
bool isCancelled = false;
mPrintSettings->GetIsCancelled(&isCancelled);
nsresult rv = NS_OK;
if (mType == eIsPrinting) {
if (!isCancelled && !mIsAborted) {
rv = mPrintDC->EndDocument();
} else {
rv = mPrintDC->AbortDocument();
}
if (NS_FAILED(rv)) {
// XXX nsPrintData::ShowPrintErrorDialog(rv);
}
}
}
delete mPrintObject;
if (mBrandName) {
free(mBrandName);
}
}
void nsPrintData::OnStartPrinting()
{
if (!mOnStartSent) {
DoOnProgressChange(0, 0, true, nsIWebProgressListener::STATE_START|nsIWebProgressListener::STATE_IS_DOCUMENT|nsIWebProgressListener::STATE_IS_NETWORK);
mOnStartSent = true;
}
}
void nsPrintData::OnEndPrinting()
{
DoOnProgressChange(100, 100, true, nsIWebProgressListener::STATE_STOP|nsIWebProgressListener::STATE_IS_DOCUMENT);
DoOnProgressChange(100, 100, true, nsIWebProgressListener::STATE_STOP|nsIWebProgressListener::STATE_IS_NETWORK);
}
void
nsPrintData::DoOnProgressChange(int32_t aProgress,
int32_t aMaxProgress,
bool aDoStartStop,
int32_t aFlag)
{
size_t numberOfListeners = mPrintProgressListeners.Length();
for (size_t i = 0; i < numberOfListeners; ++i) {
nsCOMPtr<nsIWebProgressListener> listener =
mPrintProgressListeners.SafeElementAt(i);
if (NS_WARN_IF(!listener)) {
continue;
}
listener->OnProgressChange(nullptr, nullptr, aProgress, aMaxProgress,
aProgress, aMaxProgress);
if (aDoStartStop) {
listener->OnStateChange(nullptr, nullptr, aFlag, NS_OK);
}
}
}
void
nsPrintData::DoOnStatusChange(nsresult aStatus)
{
size_t numberOfListeners = mPrintProgressListeners.Length();
for (size_t i = 0; i < numberOfListeners; ++i) {
nsCOMPtr<nsIWebProgressListener> listener =
mPrintProgressListeners.SafeElementAt(i);
if (NS_WARN_IF(!listener)) {
continue;
}
listener->OnStatusChange(nullptr, nullptr, aStatus, nullptr);
}
}

View file

@ -0,0 +1,96 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#ifndef nsPrintData_h___
#define nsPrintData_h___
#include "mozilla/Attributes.h"
// Interfaces
#include "nsDeviceContext.h"
#include "nsIPrintProgressParams.h"
#include "nsIPrintSettings.h"
#include "nsISupportsImpl.h"
#include "nsTArray.h"
#include "nsCOMArray.h"
// Classes
class nsPrintObject;
class nsPrintPreviewListener;
class nsIWebProgressListener;
//------------------------------------------------------------------------
// nsPrintData Class
//
// mPreparingForPrint - indicates that we have started Printing but
// have not gone to the timer to start printing the pages. It gets turned
// off right before we go to the timer.
//
// mDocWasToBeDestroyed - Gets set when "someone" tries to unload the document
// while we were prparing to Print. This typically happens if a user starts
// to print while a page is still loading. If they start printing and pause
// at the print dialog and then the page comes in, we then abort printing
// because the document is no longer stable.
//
//------------------------------------------------------------------------
class nsPrintData {
public:
typedef enum {eIsPrinting, eIsPrintPreview } ePrintDataType;
explicit nsPrintData(ePrintDataType aType);
NS_INLINE_DECL_REFCOUNTING(nsPrintData)
// Listener Helper Methods
void OnEndPrinting();
void OnStartPrinting();
void DoOnProgressChange(int32_t aProgress,
int32_t aMaxProgress,
bool aDoStartStop,
int32_t aFlag);
void DoOnStatusChange(nsresult aStatus);
ePrintDataType mType; // the type of data this is (Printing or Print Preview)
RefPtr<nsDeviceContext> mPrintDC;
FILE *mDebugFilePtr; // a file where information can go to when printing
nsPrintObject * mPrintObject;
nsPrintObject * mSelectedPO;
nsCOMArray<nsIWebProgressListener> mPrintProgressListeners;
nsCOMPtr<nsIPrintProgressParams> mPrintProgressParams;
nsCOMPtr<nsPIDOMWindowOuter> mCurrentFocusWin; // cache a pointer to the currently focused window
nsTArray<nsPrintObject*> mPrintDocList;
bool mIsIFrameSelected;
bool mIsParentAFrameSet;
bool mOnStartSent;
bool mIsAborted; // tells us the document is being aborted
bool mPreparingForPrint; // see comments above
bool mDocWasToBeDestroyed; // see comments above
bool mShrinkToFit;
int16_t mPrintFrameType;
int32_t mNumPrintablePages;
int32_t mNumPagesPrinted;
float mShrinkRatio;
float mOrigDCScale;
nsCOMPtr<nsIPrintSettings> mPrintSettings;
nsPrintPreviewListener* mPPEventListeners;
char16_t* mBrandName; // needed as a substitute name for a document
private:
nsPrintData() = delete;
nsPrintData& operator=(const nsPrintData& aOther) = delete;
~nsPrintData(); // non-virtual
};
#endif /* nsPrintData_h___ */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,305 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#ifndef nsPrintEngine_h___
#define nsPrintEngine_h___
#include "mozilla/Attributes.h"
#include "mozilla/UniquePtr.h"
#include "nsCOMPtr.h"
#include "nsPrintObject.h"
#include "nsPrintData.h"
#include "nsFrameList.h"
#include "nsIFrame.h"
#include "nsIWebProgress.h"
#include "mozilla/dom/HTMLCanvasElement.h"
#include "nsIWebProgressListener.h"
#include "nsWeakReference.h"
// Interfaces
#include "nsIObserver.h"
// Classes
class nsPagePrintTimer;
class nsIDocShell;
class nsIDocument;
class nsIDocumentViewerPrint;
class nsPrintObject;
class nsIDocShell;
class nsIPageSequenceFrame;
//------------------------------------------------------------------------
// nsPrintEngine Class
//
//------------------------------------------------------------------------
class nsPrintEngine final : public nsIObserver,
public nsIWebProgressListener,
public nsSupportsWeakReference
{
public:
// nsISupports interface...
NS_DECL_ISUPPORTS
// nsIObserver
NS_DECL_NSIOBSERVER
NS_DECL_NSIWEBPROGRESSLISTENER
// Old nsIWebBrowserPrint methods; not cleaned up yet
NS_IMETHOD Print(nsIPrintSettings* aPrintSettings,
nsIWebProgressListener* aWebProgressListener);
NS_IMETHOD PrintPreview(nsIPrintSettings* aPrintSettings,
mozIDOMWindowProxy* aChildDOMWin,
nsIWebProgressListener* aWebProgressListener);
NS_IMETHOD GetIsFramesetDocument(bool *aIsFramesetDocument);
NS_IMETHOD GetIsIFrameSelected(bool *aIsIFrameSelected);
NS_IMETHOD GetIsRangeSelection(bool *aIsRangeSelection);
NS_IMETHOD GetIsFramesetFrameSelected(bool *aIsFramesetFrameSelected);
NS_IMETHOD GetPrintPreviewNumPages(int32_t *aPrintPreviewNumPages);
NS_IMETHOD EnumerateDocumentNames(uint32_t* aCount, char16_t*** aResult);
static nsresult GetGlobalPrintSettings(nsIPrintSettings** aPrintSettings);
NS_IMETHOD GetDoingPrint(bool *aDoingPrint);
NS_IMETHOD GetDoingPrintPreview(bool *aDoingPrintPreview);
NS_IMETHOD GetCurrentPrintSettings(nsIPrintSettings **aCurrentPrintSettings);
// This enum tells indicates what the default should be for the title
// if the title from the document is null
enum eDocTitleDefault {
eDocTitleDefBlank,
eDocTitleDefURLDoc
};
nsPrintEngine();
void Destroy();
void DestroyPrintingData();
nsresult Initialize(nsIDocumentViewerPrint* aDocViewerPrint,
nsIDocShell* aContainer,
nsIDocument* aDocument,
float aScreenDPI,
FILE* aDebugFile);
nsresult GetSeqFrameAndCountPages(nsIFrame*& aSeqFrame, int32_t& aCount);
//
// The following three methods are used for printing...
//
nsresult DocumentReadyForPrinting();
nsresult GetSelectionDocument(nsIDeviceContextSpec * aDevSpec,
nsIDocument ** aNewDoc);
nsresult SetupToPrintContent();
nsresult EnablePOsForPrinting();
nsPrintObject* FindSmallestSTF();
bool PrintDocContent(nsPrintObject* aPO, nsresult& aStatus);
nsresult DoPrint(nsPrintObject * aPO);
void SetPrintPO(nsPrintObject* aPO, bool aPrint);
void TurnScriptingOn(bool aDoTurnOn);
bool CheckDocumentForPPCaching();
void InstallPrintPreviewListener();
// nsIDocumentViewerPrint Printing Methods
bool HasPrintCallbackCanvas();
bool PrePrintPage();
bool PrintPage(nsPrintObject* aPOect, bool& aInRange);
bool DonePrintingPages(nsPrintObject* aPO, nsresult aResult);
//---------------------------------------------------------------------
void BuildDocTree(nsIDocShell * aParentNode,
nsTArray<nsPrintObject*> * aDocList,
nsPrintObject * aPO);
nsresult ReflowDocList(nsPrintObject * aPO, bool aSetPixelScale);
nsresult ReflowPrintObject(nsPrintObject * aPO);
void CheckForChildFrameSets(nsPrintObject* aPO);
void CalcNumPrintablePages(int32_t& aNumPages);
void ShowPrintProgress(bool aIsForPrinting, bool& aDoNotify);
nsresult CleanupOnFailure(nsresult aResult, bool aIsPrinting);
// If FinishPrintPreview() fails, caller may need to reset the state of the
// object, for example by calling CleanupOnFailure().
nsresult FinishPrintPreview();
static void CloseProgressDialog(nsIWebProgressListener* aWebProgressListener);
void SetDocAndURLIntoProgress(nsPrintObject* aPO,
nsIPrintProgressParams* aParams);
void EllipseLongString(nsAString& aStr, const uint32_t aLen, bool aDoFront);
nsresult CheckForPrinters(nsIPrintSettings* aPrintSettings);
void CleanupDocTitleArray(char16_t**& aArray, int32_t& aCount);
bool IsThereARangeSelection(nsPIDOMWindowOuter* aDOMWin);
void FirePrintingErrorEvent(nsresult aPrintError);
//---------------------------------------------------------------------
// Timer Methods
nsresult StartPagePrintTimer(nsPrintObject* aPO);
bool IsWindowsInOurSubTree(nsPIDOMWindowOuter* aDOMWindow);
static bool IsParentAFrameSet(nsIDocShell * aParent);
bool IsThereAnIFrameSelected(nsIDocShell* aDocShell,
nsPIDOMWindowOuter* aDOMWin,
bool& aIsParentFrameSet);
static nsPrintObject* FindPrintObjectByDOMWin(nsPrintObject* aParentObject,
nsPIDOMWindowOuter* aDOMWin);
// get the currently infocus frame for the document viewer
already_AddRefed<nsPIDOMWindowOuter> FindFocusedDOMWindow();
//---------------------------------------------------------------------
// Static Methods
//---------------------------------------------------------------------
static void GetDocumentTitleAndURL(nsIDocument* aDoc,
nsAString& aTitle,
nsAString& aURLStr);
void GetDisplayTitleAndURL(nsPrintObject* aPO,
nsAString& aTitle,
nsAString& aURLStr,
eDocTitleDefault aDefType);
static bool HasFramesetChild(nsIContent* aContent);
bool CheckBeforeDestroy();
nsresult Cancelled();
nsIPresShell* GetPrintPreviewPresShell() {return mPrtPreview->mPrintObject->mPresShell;}
float GetPrintPreviewScale() { return mPrtPreview->mPrintObject->
mPresContext->GetPrintPreviewScale(); }
static nsIPresShell* GetPresShellFor(nsIDocShell* aDocShell);
// These calls also update the DocViewer
void SetIsPrinting(bool aIsPrinting);
bool GetIsPrinting()
{
return mIsDoingPrinting;
}
void SetIsPrintPreview(bool aIsPrintPreview);
bool GetIsPrintPreview()
{
return mIsDoingPrintPreview;
}
void SetIsCreatingPrintPreview(bool aIsCreatingPrintPreview)
{
mIsCreatingPrintPreview = aIsCreatingPrintPreview;
}
bool GetIsCreatingPrintPreview()
{
return mIsCreatingPrintPreview;
}
void SetDisallowSelectionPrint(bool aDisallowSelectionPrint)
{
mDisallowSelectionPrint = aDisallowSelectionPrint;
}
protected:
~nsPrintEngine();
nsresult CommonPrint(bool aIsPrintPreview, nsIPrintSettings* aPrintSettings,
nsIWebProgressListener* aWebProgressListener,
nsIDOMDocument* aDoc);
nsresult DoCommonPrint(bool aIsPrintPreview, nsIPrintSettings* aPrintSettings,
nsIWebProgressListener* aWebProgressListener,
nsIDOMDocument* aDoc);
void FirePrintCompletionEvent();
static nsresult GetSeqFrameAndCountPagesInternal(nsPrintObject* aPO,
nsIFrame*& aSeqFrame,
int32_t& aCount);
static nsresult FindSelectionBoundsWithList(nsFrameList::Enumerator& aChildFrames,
nsIFrame * aParentFrame,
nsRect& aRect,
nsIFrame *& aStartFrame,
nsRect& aStartRect,
nsIFrame *& aEndFrame,
nsRect& aEndRect);
static nsresult FindSelectionBounds(nsIFrame * aParentFrame,
nsRect& aRect,
nsIFrame *& aStartFrame,
nsRect& aStartRect,
nsIFrame *& aEndFrame,
nsRect& aEndRect);
static nsresult GetPageRangeForSelection(nsIPageSequenceFrame* aPageSeqFrame,
nsIFrame** aStartFrame,
int32_t& aStartPageNum,
nsRect& aStartRect,
nsIFrame** aEndFrame,
int32_t& aEndPageNum,
nsRect& aEndRect);
static void MapContentForPO(nsPrintObject* aPO, nsIContent* aContent);
static void MapContentToWebShells(nsPrintObject* aRootPO, nsPrintObject* aPO);
static void SetPrintAsIs(nsPrintObject* aPO, bool aAsIs = true);
void DisconnectPagePrintTimer();
// Static member variables
bool mIsCreatingPrintPreview;
bool mIsDoingPrinting;
bool mIsDoingPrintPreview; // per DocumentViewer
bool mProgressDialogIsShown;
nsCOMPtr<nsIDocumentViewerPrint> mDocViewerPrint;
nsWeakPtr mContainer;
float mScreenDPI;
// We are the primary owner of our nsPrintData member vars. These vars
// are refcounted so that functions (e.g. nsPrintData methods) can create
// temporary owning references when they need to fire a callback that
// could conceivably destroy this nsPrintEngine owner object and all its
// member-data.
RefPtr<nsPrintData> mPrt;
nsPagePrintTimer* mPagePrintTimer;
nsWeakFrame mPageSeqFrame;
// Print Preview
RefPtr<nsPrintData> mPrtPreview;
RefPtr<nsPrintData> mOldPrtPreview;
nsCOMPtr<nsIDocument> mDocument;
FILE* mDebugFile;
int32_t mLoadCounter;
bool mDidLoadDataForPrinting;
bool mIsDestroying;
bool mDisallowSelectionPrint;
nsresult AfterNetworkPrint(bool aHandleError);
nsresult SetRootView(nsPrintObject* aPO,
bool& aDoReturn,
bool& aDocumentIsTopLevel,
nsSize& aAdjSize);
nsView* GetParentViewForRoot();
bool DoSetPixelScale();
void UpdateZoomRatio(nsPrintObject* aPO, bool aSetPixelScale);
nsresult ReconstructAndReflow(bool aDoSetPixelScale);
nsresult UpdateSelectionAndShrinkPrintObject(nsPrintObject* aPO,
bool aDocumentIsTopLevel);
nsresult InitPrintDocConstruction(bool aHandleError);
void FirePrintPreviewUpdateEvent();
private:
nsPrintEngine& operator=(const nsPrintEngine& aOther) = delete;
};
#endif /* nsPrintEngine_h___ */

View file

@ -0,0 +1,113 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 "nsPrintObject.h"
#include "nsIContentViewer.h"
#include "nsIDOMDocument.h"
#include "nsContentUtils.h" // for nsAutoScriptBlocker
#include "nsIInterfaceRequestorUtils.h"
#include "nsPIDOMWindow.h"
#include "nsGkAtoms.h"
#include "nsComponentManagerUtils.h"
#include "nsIDocShellTreeItem.h"
#include "nsIBaseWindow.h"
#include "nsIDocument.h"
//---------------------------------------------------
//-- nsPrintObject Class Impl
//---------------------------------------------------
nsPrintObject::nsPrintObject() :
mContent(nullptr), mFrameType(eFrame), mParent(nullptr),
mHasBeenPrinted(false), mDontPrint(true), mPrintAsIs(false),
mInvisible(false), mDidCreateDocShell(false),
mShrinkRatio(1.0), mZoomRatio(1.0)
{
MOZ_COUNT_CTOR(nsPrintObject);
}
nsPrintObject::~nsPrintObject()
{
MOZ_COUNT_DTOR(nsPrintObject);
for (uint32_t i=0;i<mKids.Length();i++) {
nsPrintObject* po = mKids[i];
delete po;
}
DestroyPresentation();
if (mDidCreateDocShell && mDocShell) {
nsCOMPtr<nsIBaseWindow> baseWin(do_QueryInterface(mDocShell));
if (baseWin) {
baseWin->Destroy();
}
}
mDocShell = nullptr;
mTreeOwner = nullptr; // mTreeOwner must be released after mDocShell;
}
//------------------------------------------------------------------
nsresult
nsPrintObject::Init(nsIDocShell* aDocShell, nsIDOMDocument* aDoc,
bool aPrintPreview)
{
mPrintPreview = aPrintPreview;
if (mPrintPreview || mParent) {
mDocShell = aDocShell;
} else {
mTreeOwner = do_GetInterface(aDocShell);
// Create a container docshell for printing.
mDocShell = do_CreateInstance("@mozilla.org/docshell;1");
NS_ENSURE_TRUE(mDocShell, NS_ERROR_OUT_OF_MEMORY);
mDidCreateDocShell = true;
mDocShell->SetItemType(aDocShell->ItemType());
mDocShell->SetTreeOwner(mTreeOwner);
}
NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
// Keep the document related to this docshell alive
nsCOMPtr<nsIDOMDocument> dummy = do_GetInterface(mDocShell);
mozilla::Unused << dummy;
nsCOMPtr<nsIContentViewer> viewer;
mDocShell->GetContentViewer(getter_AddRefs(viewer));
NS_ENSURE_STATE(viewer);
nsCOMPtr<nsIDocument> doc = do_QueryInterface(aDoc);
NS_ENSURE_STATE(doc);
if (mParent) {
nsCOMPtr<nsPIDOMWindowOuter> window = doc->GetWindow();
if (window) {
mContent = window->GetFrameElementInternal();
}
mDocument = doc;
return NS_OK;
}
mDocument = doc->CreateStaticClone(mDocShell);
nsCOMPtr<nsIDOMDocument> clonedDOMDoc = do_QueryInterface(mDocument);
NS_ENSURE_STATE(clonedDOMDoc);
viewer->SetDOMDocument(clonedDOMDoc);
return NS_OK;
}
//------------------------------------------------------------------
// Resets PO by destroying the presentation
void
nsPrintObject::DestroyPresentation()
{
if (mPresShell) {
mPresShell->EndObservingDocument();
nsAutoScriptBlocker scriptBlocker;
nsCOMPtr<nsIPresShell> shell = mPresShell;
mPresShell = nullptr;
shell->Destroy();
}
mPresContext = nullptr;
mViewManager = nullptr;
}

View file

@ -0,0 +1,71 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#ifndef nsPrintObject_h___
#define nsPrintObject_h___
#include "mozilla/Attributes.h"
// Interfaces
#include "nsCOMPtr.h"
#include "nsIPresShell.h"
#include "nsViewManager.h"
#include "nsIDocShell.h"
#include "nsIDocShellTreeOwner.h"
class nsIContent;
class nsIDocument;
class nsPresContext;
// nsPrintObject Document Type
enum PrintObjectType {eDoc = 0, eFrame = 1, eIFrame = 2, eFrameSet = 3};
//---------------------------------------------------
//-- nsPrintObject Class
//---------------------------------------------------
class nsPrintObject
{
public:
nsPrintObject();
~nsPrintObject(); // non-virtual
// Methods
nsresult Init(nsIDocShell* aDocShell, nsIDOMDocument* aDoc,
bool aPrintPreview);
bool IsPrintable() { return !mDontPrint; }
void DestroyPresentation();
// Data Members
nsCOMPtr<nsIDocShell> mDocShell;
nsCOMPtr<nsIDocShellTreeOwner> mTreeOwner;
nsCOMPtr<nsIDocument> mDocument;
RefPtr<nsPresContext> mPresContext;
nsCOMPtr<nsIPresShell> mPresShell;
RefPtr<nsViewManager> mViewManager;
nsCOMPtr<nsIContent> mContent;
PrintObjectType mFrameType;
nsTArray<nsPrintObject*> mKids;
nsPrintObject* mParent;
bool mHasBeenPrinted;
bool mDontPrint;
bool mPrintAsIs;
bool mInvisible; // Indicates PO is set to not visible by CSS
bool mPrintPreview;
bool mDidCreateDocShell;
float mShrinkRatio;
float mZoomRatio;
private:
nsPrintObject& operator=(const nsPrintObject& aOther) = delete;
};
#endif /* nsPrintObject_h___ */

View file

@ -0,0 +1,212 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 "nsPrintPreviewListener.h"
#include "mozilla/TextEvents.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent()
#include "nsIDOMWindow.h"
#include "nsPIDOMWindow.h"
#include "nsIDOMElement.h"
#include "nsIDOMKeyEvent.h"
#include "nsIDOMEvent.h"
#include "nsIDocument.h"
#include "nsIDocShell.h"
#include "nsPresContext.h"
#include "nsFocusManager.h"
#include "nsLiteralString.h"
using namespace mozilla;
using namespace mozilla::dom;
NS_IMPL_ISUPPORTS(nsPrintPreviewListener, nsIDOMEventListener)
//
// nsPrintPreviewListener ctor
//
nsPrintPreviewListener::nsPrintPreviewListener(EventTarget* aTarget)
: mEventTarget(aTarget)
{
NS_ADDREF_THIS();
} // ctor
nsPrintPreviewListener::~nsPrintPreviewListener()
{
}
//-------------------------------------------------------
//
// AddListeners
//
// Subscribe to the events that will allow us to track various events.
//
nsresult
nsPrintPreviewListener::AddListeners()
{
if (mEventTarget) {
mEventTarget->AddEventListener(NS_LITERAL_STRING("click"), this, true);
mEventTarget->AddEventListener(NS_LITERAL_STRING("contextmenu"), this, true);
mEventTarget->AddEventListener(NS_LITERAL_STRING("keydown"), this, true);
mEventTarget->AddEventListener(NS_LITERAL_STRING("keypress"), this, true);
mEventTarget->AddEventListener(NS_LITERAL_STRING("keyup"), this, true);
mEventTarget->AddEventListener(NS_LITERAL_STRING("mousedown"), this, true);
mEventTarget->AddEventListener(NS_LITERAL_STRING("mousemove"), this, true);
mEventTarget->AddEventListener(NS_LITERAL_STRING("mouseout"), this, true);
mEventTarget->AddEventListener(NS_LITERAL_STRING("mouseover"), this, true);
mEventTarget->AddEventListener(NS_LITERAL_STRING("mouseup"), this, true);
mEventTarget->AddSystemEventListener(NS_LITERAL_STRING("keydown"),
this, true);
}
return NS_OK;
}
//-------------------------------------------------------
//
// RemoveListeners
//
// Unsubscribe from all the various events that we were listening to.
//
nsresult
nsPrintPreviewListener::RemoveListeners()
{
if (mEventTarget) {
mEventTarget->RemoveEventListener(NS_LITERAL_STRING("click"), this, true);
mEventTarget->RemoveEventListener(NS_LITERAL_STRING("contextmenu"), this, true);
mEventTarget->RemoveEventListener(NS_LITERAL_STRING("keydown"), this, true);
mEventTarget->RemoveEventListener(NS_LITERAL_STRING("keypress"), this, true);
mEventTarget->RemoveEventListener(NS_LITERAL_STRING("keyup"), this, true);
mEventTarget->RemoveEventListener(NS_LITERAL_STRING("mousedown"), this, true);
mEventTarget->RemoveEventListener(NS_LITERAL_STRING("mousemove"), this, true);
mEventTarget->RemoveEventListener(NS_LITERAL_STRING("mouseout"), this, true);
mEventTarget->RemoveEventListener(NS_LITERAL_STRING("mouseover"), this, true);
mEventTarget->RemoveEventListener(NS_LITERAL_STRING("mouseup"), this, true);
mEventTarget->RemoveSystemEventListener(NS_LITERAL_STRING("keydown"),
this, true);
}
return NS_OK;
}
//-------------------------------------------------------
//
// GetActionForEvent
//
// Helper function to let certain key events through
//
enum eEventAction {
eEventAction_Tab, eEventAction_ShiftTab,
eEventAction_Propagate, eEventAction_Suppress,
eEventAction_StopPropagation
};
static eEventAction
GetActionForEvent(nsIDOMEvent* aEvent)
{
WidgetKeyboardEvent* keyEvent =
aEvent->WidgetEventPtr()->AsKeyboardEvent();
if (!keyEvent) {
return eEventAction_Suppress;
}
if (keyEvent->mFlags.mInSystemGroup) {
NS_ASSERTION(keyEvent->mMessage == eKeyDown,
"Assuming we're listening only keydown event in system group");
return eEventAction_StopPropagation;
}
if (keyEvent->IsAlt() || keyEvent->IsControl() || keyEvent->IsMeta()) {
// Don't consume keydown event because following keypress event may be
// handled as access key or shortcut key.
return (keyEvent->mMessage == eKeyDown) ? eEventAction_StopPropagation :
eEventAction_Suppress;
}
static const uint32_t kOKKeyCodes[] = {
NS_VK_PAGE_UP, NS_VK_PAGE_DOWN,
NS_VK_UP, NS_VK_DOWN,
NS_VK_HOME, NS_VK_END
};
if (keyEvent->mKeyCode == NS_VK_TAB) {
return keyEvent->IsShift() ? eEventAction_ShiftTab : eEventAction_Tab;
}
if (keyEvent->mCharCode == ' ' || keyEvent->mKeyCode == NS_VK_SPACE) {
return eEventAction_Propagate;
}
if (keyEvent->IsShift()) {
return eEventAction_Suppress;
}
for (uint32_t i = 0; i < ArrayLength(kOKKeyCodes); ++i) {
if (keyEvent->mKeyCode == kOKKeyCodes[i]) {
return eEventAction_Propagate;
}
}
return eEventAction_Suppress;
}
NS_IMETHODIMP
nsPrintPreviewListener::HandleEvent(nsIDOMEvent* aEvent)
{
nsCOMPtr<nsIContent> content = do_QueryInterface(
aEvent ? aEvent->InternalDOMEvent()->GetOriginalTarget() : nullptr);
if (content && !content->IsXULElement()) {
eEventAction action = ::GetActionForEvent(aEvent);
switch (action) {
case eEventAction_Tab:
case eEventAction_ShiftTab:
{
nsAutoString eventString;
aEvent->GetType(eventString);
if (eventString.EqualsLiteral("keydown")) {
// Handle tabbing explicitly here since we don't want focus ending up
// inside the content document, bug 244128.
nsIDocument* doc = content->GetUncomposedDoc();
NS_ASSERTION(doc, "no document");
nsIDocument* parentDoc = doc->GetParentDocument();
NS_ASSERTION(parentDoc, "no parent document");
nsCOMPtr<nsPIDOMWindowOuter> win = parentDoc->GetWindow();
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
if (fm && win) {
dom::Element* fromElement = parentDoc->FindContentForSubDocument(doc);
nsCOMPtr<nsIDOMElement> from = do_QueryInterface(fromElement);
bool forward = (action == eEventAction_Tab);
nsCOMPtr<nsIDOMElement> result;
fm->MoveFocus(win, from,
forward ? nsIFocusManager::MOVEFOCUS_FORWARD :
nsIFocusManager::MOVEFOCUS_BACKWARD,
nsIFocusManager::FLAG_BYKEY, getter_AddRefs(result));
}
}
}
MOZ_FALLTHROUGH;
case eEventAction_Suppress:
aEvent->StopPropagation();
aEvent->PreventDefault();
break;
case eEventAction_StopPropagation:
aEvent->StopPropagation();
break;
case eEventAction_Propagate:
// intentionally empty
break;
}
}
return NS_OK;
}

View file

@ -0,0 +1,53 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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/. */
#ifndef nsPrintPreviewListener_h__
#define nsPrintPreviewListener_h__
// Interfaces needed to be included
#include "nsIDOMEventListener.h"
// Helper Classes
#include "nsCOMPtr.h"
#include "mozilla/Attributes.h"
namespace mozilla {
namespace dom {
class EventTarget;
} // namespace dom
} // namespace mozilla
//
// class nsPrintPreviewListener
//
// The class that listens to the chrome events and tells the embedding
// chrome to show context menus, as appropriate. Handles registering itself
// with the DOM with AddChromeListeners() and removing itself with
// RemoveChromeListeners().
//
class nsPrintPreviewListener final : public nsIDOMEventListener
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIDOMEVENTLISTENER
explicit nsPrintPreviewListener(mozilla::dom::EventTarget* aTarget);
// Add/remove the relevant listeners, based on what interfaces
// the embedding chrome implements.
nsresult AddListeners();
nsresult RemoveListeners();
private:
~nsPrintPreviewListener();
nsCOMPtr<mozilla::dom::EventTarget> mEventTarget;
}; // class nsPrintPreviewListener
#endif /* nsPrintPreviewListener_h__ */