1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072 |
- /* -*- 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 "nsPrintEngine.h"
- #include "nsIStringBundle.h"
- #include "nsReadableUtils.h"
- #include "nsCRT.h"
- #include "mozilla/AsyncEventDispatcher.h"
- #include "mozilla/dom/Selection.h"
- #include "mozilla/dom/CustomEvent.h"
- #include "nsIScriptGlobalObject.h"
- #include "nsPIDOMWindow.h"
- #include "nsIDocShell.h"
- #include "nsIURI.h"
- #include "nsIFile.h"
- #include "nsITextToSubURI.h"
- #include "nsError.h"
- #include "nsView.h"
- #include <algorithm>
- // Print Options
- #include "nsIPrintSettings.h"
- #include "nsIPrintSettingsService.h"
- #include "nsIPrintSession.h"
- #include "nsGfxCIID.h"
- #include "nsIServiceManager.h"
- #include "nsGkAtoms.h"
- #include "nsXPCOM.h"
- #include "nsISupportsPrimitives.h"
- static const char sPrintSettingsServiceContractID[] = "@mozilla.org/gfx/printsettings-service;1";
- // Printing Events
- #include "nsPrintPreviewListener.h"
- #include "nsThreadUtils.h"
- // Printing
- #include "nsIWebBrowserPrint.h"
- #include "nsIDOMHTMLFrameElement.h"
- #include "nsIDOMHTMLFrameSetElement.h"
- #include "nsIDOMHTMLIFrameElement.h"
- #include "nsIDOMHTMLObjectElement.h"
- #include "nsIDOMHTMLEmbedElement.h"
- // Print Preview
- #include "imgIContainer.h" // image animation mode constants
- #include "nsIWebBrowserPrint.h" // needed for PrintPreview Navigation constants
- // Print Progress
- #include "nsIPrintProgress.h"
- #include "nsIPrintProgressParams.h"
- #include "nsIObserver.h"
- // Print error dialog
- #include "nsIPrompt.h"
- #include "nsIWindowWatcher.h"
- // Printing Prompts
- #include "nsIPrintingPromptService.h"
- static const char kPrintingPromptService[] = "@mozilla.org/embedcomp/printingprompt-service;1";
- // Printing Timer
- #include "nsPagePrintTimer.h"
- // FrameSet
- #include "nsIDocument.h"
- // Focus
- #include "nsISelectionController.h"
- // Misc
- #include "mozilla/gfx/DrawEventRecorder.h"
- #include "mozilla/layout/RemotePrintJobChild.h"
- #include "nsISupportsUtils.h"
- #include "nsIScriptContext.h"
- #include "nsIDOMDocument.h"
- #include "nsISelectionListener.h"
- #include "nsISelectionPrivate.h"
- #include "nsIDOMRange.h"
- #include "nsContentCID.h"
- #include "nsLayoutCID.h"
- #include "nsContentUtils.h"
- #include "nsIPresShell.h"
- #include "nsLayoutUtils.h"
- #include "mozilla/Preferences.h"
- #include "nsWidgetsCID.h"
- #include "nsIDeviceContextSpec.h"
- #include "nsDeviceContextSpecProxy.h"
- #include "nsViewManager.h"
- #include "nsView.h"
- #include "nsRenderingContext.h"
- #include "nsIPageSequenceFrame.h"
- #include "nsIURL.h"
- #include "nsIContentViewerEdit.h"
- #include "nsIContentViewerFile.h"
- #include "nsIInterfaceRequestor.h"
- #include "nsIInterfaceRequestorUtils.h"
- #include "nsIDocShellTreeOwner.h"
- #include "nsIWebBrowserChrome.h"
- #include "nsIBaseWindow.h"
- #include "nsILayoutHistoryState.h"
- #include "nsFrameManager.h"
- #include "mozilla/ReflowInput.h"
- #include "nsIDOMHTMLAnchorElement.h"
- #include "nsIDOMHTMLAreaElement.h"
- #include "nsIDOMHTMLLinkElement.h"
- #include "nsIDOMHTMLImageElement.h"
- #include "nsIContentViewerContainer.h"
- #include "nsIContentViewer.h"
- #include "nsIDocumentViewerPrint.h"
- #include "nsFocusManager.h"
- #include "nsRange.h"
- #include "nsCDefaultURIFixup.h"
- #include "nsIURIFixup.h"
- #include "mozilla/dom/Element.h"
- #include "nsContentList.h"
- #include "nsIChannel.h"
- #include "xpcpublic.h"
- #include "nsVariant.h"
- #include "mozilla/StyleSetHandle.h"
- #include "mozilla/StyleSetHandleInlines.h"
- using namespace mozilla;
- using namespace mozilla::dom;
- //-----------------------------------------------------
- // PR LOGGING
- #include "mozilla/Logging.h"
- #ifdef DEBUG
- // PR_LOGGING is force to always be on (even in release builds)
- // but we only want some of it on,
- //#define EXTENDED_DEBUG_PRINTING
- #endif
- #define DUMP_LAYOUT_LEVEL 9 // this turns on the dumping of each doucment's layout info
- #ifndef PR_PL
- static mozilla::LazyLogModule gPrintingLog("printing");
- #define PR_PL(_p1) MOZ_LOG(gPrintingLog, mozilla::LogLevel::Debug, _p1);
- #endif
- #ifdef EXTENDED_DEBUG_PRINTING
- static uint32_t gDumpFileNameCnt = 0;
- static uint32_t gDumpLOFileNameCnt = 0;
- #endif
- #define PRT_YESNO(_p) ((_p)?"YES":"NO")
- static const char * gFrameTypesStr[] = {"eDoc", "eFrame", "eIFrame", "eFrameSet"};
- static const char * gPrintFrameTypeStr[] = {"kNoFrames", "kFramesAsIs", "kSelectedFrame", "kEachFrameSep"};
- static const char * gFrameHowToEnableStr[] = {"kFrameEnableNone", "kFrameEnableAll", "kFrameEnableAsIsAndEach"};
- static const char * gPrintRangeStr[] = {"kRangeAllPages", "kRangeSpecifiedPageRange", "kRangeSelection", "kRangeFocusFrame"};
- #ifdef EXTENDED_DEBUG_PRINTING
- // Forward Declarations
- static void DumpPrintObjectsListStart(const char * aStr, nsTArray<nsPrintObject*> * aDocList);
- static void DumpPrintObjectsTree(nsPrintObject * aPO, int aLevel= 0, FILE* aFD = nullptr);
- static void DumpPrintObjectsTreeLayout(nsPrintObject * aPO,nsDeviceContext * aDC, int aLevel= 0, FILE * aFD = nullptr);
- #define DUMP_DOC_LIST(_title) DumpPrintObjectsListStart((_title), mPrt->mPrintDocList);
- #define DUMP_DOC_TREE DumpPrintObjectsTree(mPrt->mPrintObject);
- #define DUMP_DOC_TREELAYOUT DumpPrintObjectsTreeLayout(mPrt->mPrintObject, mPrt->mPrintDC);
- #else
- #define DUMP_DOC_LIST(_title)
- #define DUMP_DOC_TREE
- #define DUMP_DOC_TREELAYOUT
- #endif
- class nsScriptSuppressor
- {
- public:
- explicit nsScriptSuppressor(nsPrintEngine* aPrintEngine)
- : mPrintEngine(aPrintEngine), mSuppressed(false) {}
- ~nsScriptSuppressor() { Unsuppress(); }
- void Suppress()
- {
- if (mPrintEngine) {
- mSuppressed = true;
- mPrintEngine->TurnScriptingOn(false);
- }
- }
- void Unsuppress()
- {
- if (mPrintEngine && mSuppressed) {
- mPrintEngine->TurnScriptingOn(true);
- }
- mSuppressed = false;
- }
- void Disconnect() { mPrintEngine = nullptr; }
- protected:
- RefPtr<nsPrintEngine> mPrintEngine;
- bool mSuppressed;
- };
- NS_IMPL_ISUPPORTS(nsPrintEngine, nsIWebProgressListener,
- nsISupportsWeakReference, nsIObserver)
- //---------------------------------------------------
- //-- nsPrintEngine Class Impl
- //---------------------------------------------------
- nsPrintEngine::nsPrintEngine()
- : mIsCreatingPrintPreview(false)
- , mIsDoingPrinting(false)
- , mIsDoingPrintPreview(false)
- , mProgressDialogIsShown(false)
- , mScreenDPI(115.0f)
- , mPagePrintTimer(nullptr)
- , mDebugFile(nullptr)
- , mLoadCounter(0)
- , mDidLoadDataForPrinting(false)
- , mIsDestroying(false)
- , mDisallowSelectionPrint(false)
- {
- }
- //-------------------------------------------------------
- nsPrintEngine::~nsPrintEngine()
- {
- Destroy(); // for insurance
- DisconnectPagePrintTimer();
- }
- //-------------------------------------------------------
- void nsPrintEngine::Destroy()
- {
- if (mIsDestroying) {
- return;
- }
- mIsDestroying = true;
- mPrt = nullptr;
- #ifdef NS_PRINT_PREVIEW
- mPrtPreview = nullptr;
- mOldPrtPreview = nullptr;
- #endif
- mDocViewerPrint = nullptr;
- }
- //-------------------------------------------------------
- void nsPrintEngine::DestroyPrintingData()
- {
- mPrt = nullptr;
- }
- //---------------------------------------------------------------------------------
- //-- Section: Methods needed by the DocViewer
- //---------------------------------------------------------------------------------
- //--------------------------------------------------------
- nsresult nsPrintEngine::Initialize(nsIDocumentViewerPrint* aDocViewerPrint,
- nsIDocShell* aContainer,
- nsIDocument* aDocument,
- float aScreenDPI,
- FILE* aDebugFile)
- {
- NS_ENSURE_ARG_POINTER(aDocViewerPrint);
- NS_ENSURE_ARG_POINTER(aContainer);
- NS_ENSURE_ARG_POINTER(aDocument);
- mDocViewerPrint = aDocViewerPrint;
- mContainer = do_GetWeakReference(aContainer);
- mDocument = aDocument;
- mScreenDPI = aScreenDPI;
- mDebugFile = aDebugFile; // ok to be nullptr
- return NS_OK;
- }
- //-------------------------------------------------------
- bool
- nsPrintEngine::CheckBeforeDestroy()
- {
- if (mPrt && mPrt->mPreparingForPrint) {
- mPrt->mDocWasToBeDestroyed = true;
- return true;
- }
- return false;
- }
- //-------------------------------------------------------
- nsresult
- nsPrintEngine::Cancelled()
- {
- if (mPrt && mPrt->mPrintSettings) {
- return mPrt->mPrintSettings->SetIsCancelled(true);
- }
- return NS_ERROR_FAILURE;
- }
- //-------------------------------------------------------
- // Install our event listeners on the document to prevent
- // some events from being processed while in PrintPreview
- //
- // No return code - if this fails, there isn't much we can do
- void
- nsPrintEngine::InstallPrintPreviewListener()
- {
- if (!mPrt->mPPEventListeners) {
- nsCOMPtr<nsIDocShell> docShell = do_QueryReferent(mContainer);
- if (!docShell) {
- return;
- }
- if (nsPIDOMWindowOuter* win = docShell->GetWindow()) {
- nsCOMPtr<EventTarget> target = win->GetFrameElementInternal();
- mPrt->mPPEventListeners = new nsPrintPreviewListener(target);
- mPrt->mPPEventListeners->AddListeners();
- }
- }
- }
- //----------------------------------------------------------------------
- nsresult
- nsPrintEngine::GetSeqFrameAndCountPagesInternal(nsPrintObject* aPO,
- nsIFrame*& aSeqFrame,
- int32_t& aCount)
- {
- NS_ENSURE_ARG_POINTER(aPO);
- // This is sometimes incorrectly called before the pres shell has been created
- // (bug 1141756). MOZ_DIAGNOSTIC_ASSERT so we'll still see the crash in
- // Nightly/Aurora in case the other patch fixes this.
- if (!aPO->mPresShell) {
- MOZ_DIAGNOSTIC_ASSERT(false,
- "GetSeqFrameAndCountPages needs a non-null pres shell");
- return NS_ERROR_FAILURE;
- }
- // Finds the SimplePageSequencer frame
- nsIPageSequenceFrame* seqFrame = aPO->mPresShell->GetPageSequenceFrame();
- aSeqFrame = do_QueryFrame(seqFrame);
- if (!aSeqFrame) {
- return NS_ERROR_FAILURE;
- }
- // count the total number of pages
- aCount = aSeqFrame->PrincipalChildList().GetLength();
- return NS_OK;
- }
- //-----------------------------------------------------------------
- nsresult nsPrintEngine::GetSeqFrameAndCountPages(nsIFrame*& aSeqFrame, int32_t& aCount)
- {
- MOZ_ASSERT(mPrtPreview);
- // Guarantee that mPrintPreview->mPrintObject won't be deleted during a call
- // of GetSeqFrameAndCountPagesInternal().
- RefPtr<nsPrintData> printDataForPrintPreview = mPrtPreview;
- return GetSeqFrameAndCountPagesInternal(
- printDataForPrintPreview->mPrintObject, aSeqFrame, aCount);
- }
- //---------------------------------------------------------------------------------
- //-- Done: Methods needed by the DocViewer
- //---------------------------------------------------------------------------------
- //---------------------------------------------------------------------------------
- //-- Section: nsIWebBrowserPrint
- //---------------------------------------------------------------------------------
- // Foward decl for Debug Helper Functions
- #ifdef EXTENDED_DEBUG_PRINTING
- static int RemoveFilesInDir(const char * aDir);
- static void GetDocTitleAndURL(nsPrintObject* aPO, char *& aDocStr, char *& aURLStr);
- static void DumpPrintObjectsTree(nsPrintObject * aPO, int aLevel, FILE* aFD);
- static void DumpPrintObjectsList(nsTArray<nsPrintObject*> * aDocList);
- static void RootFrameList(nsPresContext* aPresContext, FILE* out, int32_t aIndent);
- static void DumpViews(nsIDocShell* aDocShell, FILE* out);
- static void DumpLayoutData(char* aTitleStr, char* aURLStr,
- nsPresContext* aPresContext,
- nsDeviceContext * aDC, nsIFrame * aRootFrame,
- nsIDocShell * aDocShell, FILE* aFD);
- #endif
- //--------------------------------------------------------------------------------
- nsresult
- nsPrintEngine::CommonPrint(bool aIsPrintPreview,
- nsIPrintSettings* aPrintSettings,
- nsIWebProgressListener* aWebProgressListener,
- nsIDOMDocument* aDoc) {
- RefPtr<nsPrintEngine> kungfuDeathGrip = this;
- nsresult rv = DoCommonPrint(aIsPrintPreview, aPrintSettings,
- aWebProgressListener, aDoc);
- if (NS_FAILED(rv)) {
- if (aIsPrintPreview) {
- SetIsCreatingPrintPreview(false);
- SetIsPrintPreview(false);
- } else {
- SetIsPrinting(false);
- }
- if (mProgressDialogIsShown)
- CloseProgressDialog(aWebProgressListener);
- if (rv != NS_ERROR_ABORT && rv != NS_ERROR_OUT_OF_MEMORY) {
- FirePrintingErrorEvent(rv);
- }
- mPrt = nullptr;
- }
- return rv;
- }
- nsresult
- nsPrintEngine::DoCommonPrint(bool aIsPrintPreview,
- nsIPrintSettings* aPrintSettings,
- nsIWebProgressListener* aWebProgressListener,
- nsIDOMDocument* aDoc)
- {
- nsresult rv;
- if (aIsPrintPreview) {
- // The WebProgressListener can be QI'ed to nsIPrintingPromptService
- // then that means the progress dialog is already being shown.
- nsCOMPtr<nsIPrintingPromptService> pps(do_QueryInterface(aWebProgressListener));
- mProgressDialogIsShown = pps != nullptr;
- if (mIsDoingPrintPreview) {
- mOldPrtPreview = Move(mPrtPreview);
- }
- } else {
- mProgressDialogIsShown = false;
- }
- // Grab the new instance with local variable to guarantee that it won't be
- // deleted during this method.
- mPrt = new nsPrintData(aIsPrintPreview ? nsPrintData::eIsPrintPreview :
- nsPrintData::eIsPrinting);
- RefPtr<nsPrintData> printData = mPrt;
- // if they don't pass in a PrintSettings, then get the Global PS
- printData->mPrintSettings = aPrintSettings;
- if (!printData->mPrintSettings) {
- rv = GetGlobalPrintSettings(getter_AddRefs(printData->mPrintSettings));
- NS_ENSURE_SUCCESS(rv, rv);
- }
- rv = CheckForPrinters(printData->mPrintSettings);
- NS_ENSURE_SUCCESS(rv, rv);
- printData->mPrintSettings->SetIsCancelled(false);
- printData->mPrintSettings->GetShrinkToFit(&printData->mShrinkToFit);
- if (aIsPrintPreview) {
- SetIsCreatingPrintPreview(true);
- SetIsPrintPreview(true);
- nsCOMPtr<nsIContentViewer> viewer =
- do_QueryInterface(mDocViewerPrint);
- if (viewer) {
- viewer->SetTextZoom(1.0f);
- viewer->SetFullZoom(1.0f);
- viewer->SetMinFontSize(0);
- }
- }
- // Create a print session and let the print settings know about it.
- // Don't overwrite an existing print session.
- // The print settings hold an nsWeakPtr to the session so it does not
- // need to be cleared from the settings at the end of the job.
- // XXX What lifetime does the printSession need to have?
- nsCOMPtr<nsIPrintSession> printSession;
- bool remotePrintJobListening = false;
- if (!aIsPrintPreview) {
- rv = printData->mPrintSettings->GetPrintSession(
- getter_AddRefs(printSession));
- if (NS_FAILED(rv) || !printSession) {
- printSession = do_CreateInstance("@mozilla.org/gfx/printsession;1", &rv);
- NS_ENSURE_SUCCESS(rv, rv);
- printData->mPrintSettings->SetPrintSession(printSession);
- } else {
- RefPtr<mozilla::layout::RemotePrintJobChild> remotePrintJob;
- printSession->GetRemotePrintJob(getter_AddRefs(remotePrintJob));
- if (NS_SUCCEEDED(rv) && remotePrintJob) {
- // If we have a RemotePrintJob add it to the print progress listeners,
- // so it can forward to the parent.
- printData->mPrintProgressListeners.AppendElement(remotePrintJob);
- remotePrintJobListening = true;
- }
- }
- }
- if (aWebProgressListener != nullptr) {
- printData->mPrintProgressListeners.AppendObject(aWebProgressListener);
- }
- // Get the currently focused window and cache it
- // because the Print Dialog will "steal" focus and later when you try
- // to get the currently focused windows it will be nullptr
- printData->mCurrentFocusWin = FindFocusedDOMWindow();
- // Check to see if there is a "regular" selection
- bool isSelection = IsThereARangeSelection(printData->mCurrentFocusWin);
- // Get the docshell for this documentviewer
- nsCOMPtr<nsIDocShell> webContainer(do_QueryReferent(mContainer, &rv));
- NS_ENSURE_SUCCESS(rv, rv);
- {
- if (aIsPrintPreview) {
- nsCOMPtr<nsIContentViewer> viewer;
- webContainer->GetContentViewer(getter_AddRefs(viewer));
- if (viewer && viewer->GetDocument() && viewer->GetDocument()->IsShowing()) {
- viewer->GetDocument()->OnPageHide(false, nullptr);
- }
- }
- nsAutoScriptBlocker scriptBlocker;
- printData->mPrintObject = new nsPrintObject();
- NS_ENSURE_TRUE(printData->mPrintObject, NS_ERROR_OUT_OF_MEMORY);
- rv = printData->mPrintObject->Init(webContainer, aDoc, aIsPrintPreview);
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(printData->mPrintDocList.AppendElement(
- printData->mPrintObject),
- NS_ERROR_OUT_OF_MEMORY);
- printData->mIsParentAFrameSet = IsParentAFrameSet(webContainer);
- printData->mPrintObject->mFrameType =
- printData->mIsParentAFrameSet ? eFrameSet : eDoc;
- // Build the "tree" of PrintObjects
- BuildDocTree(printData->mPrintObject->mDocShell, &printData->mPrintDocList,
- printData->mPrintObject);
- }
- if (!aIsPrintPreview) {
- SetIsPrinting(true);
- }
- // XXX This isn't really correct...
- if (!printData->mPrintObject->mDocument ||
- !printData->mPrintObject->mDocument->GetRootElement())
- return NS_ERROR_GFX_PRINTER_STARTDOC;
- // Create the linkage from the sub-docs back to the content element
- // in the parent document
- MapContentToWebShells(printData->mPrintObject, printData->mPrintObject);
- printData->mIsIFrameSelected =
- IsThereAnIFrameSelected(webContainer, printData->mCurrentFocusWin,
- printData->mIsParentAFrameSet);
- // Setup print options for UI
- if (printData->mIsParentAFrameSet) {
- if (printData->mCurrentFocusWin) {
- printData->mPrintSettings->SetHowToEnableFrameUI(
- nsIPrintSettings::kFrameEnableAll);
- } else {
- printData->mPrintSettings->SetHowToEnableFrameUI(
- nsIPrintSettings::kFrameEnableAsIsAndEach);
- }
- } else {
- printData->mPrintSettings->SetHowToEnableFrameUI(
- nsIPrintSettings::kFrameEnableNone);
- }
- // Now determine how to set up the Frame print UI
- printData->mPrintSettings->SetPrintOptions(
- nsIPrintSettings::kEnableSelectionRB,
- isSelection || printData->mIsIFrameSelected);
- bool printingViaParent = XRE_IsContentProcess() &&
- Preferences::GetBool("print.print_via_parent");
- nsCOMPtr<nsIDeviceContextSpec> devspec;
- if (printingViaParent) {
- devspec = new nsDeviceContextSpecProxy();
- } else {
- devspec = do_CreateInstance("@mozilla.org/gfx/devicecontextspec;1", &rv);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- nsScriptSuppressor scriptSuppressor(this);
- // If printing via parent we still call ShowPrintDialog even for print preview
- // because we use that to retrieve the print settings from the printer.
- // The dialog is not shown, but this means we don't need to access the printer
- // driver from the child, which causes sandboxing issues.
- if (!aIsPrintPreview || printingViaParent) {
- #ifdef DEBUG
- printData->mDebugFilePtr = mDebugFile;
- #endif
- scriptSuppressor.Suppress();
- bool printSilently;
- printData->mPrintSettings->GetPrintSilent(&printSilently);
- // Check prefs for a default setting as to whether we should print silently
- printSilently =
- Preferences::GetBool("print.always_print_silent", printSilently);
- // Ask dialog to be Print Shown via the Plugable Printing Dialog Service
- // This service is for the Print Dialog and the Print Progress Dialog
- // If printing silently or you can't get the service continue on
- // If printing via the parent then we need to confirm that the pref is set
- // and get a remote print job, but the parent won't display a prompt.
- if (!printSilently || printingViaParent) {
- nsCOMPtr<nsIPrintingPromptService> printPromptService(do_GetService(kPrintingPromptService));
- if (printPromptService) {
- nsPIDOMWindowOuter* domWin = nullptr;
- // We leave domWin as nullptr to indicate a call for print preview.
- if (!aIsPrintPreview) {
- domWin = mDocument->GetWindow();
- NS_ENSURE_TRUE(domWin, NS_ERROR_FAILURE);
- }
- // Platforms not implementing a given dialog for the service may
- // return NS_ERROR_NOT_IMPLEMENTED or an error code.
- //
- // NS_ERROR_NOT_IMPLEMENTED indicates they want default behavior
- // Any other error code means we must bail out
- //
- nsCOMPtr<nsIWebBrowserPrint> wbp(do_QueryInterface(mDocViewerPrint));
- rv = printPromptService->ShowPrintDialog(domWin, wbp,
- printData->mPrintSettings);
- //
- // ShowPrintDialog triggers an event loop which means we can't assume
- // that the state of this->{anything} matches the state we've checked
- // above. Including that a given {thing} is non null.
- if (NS_WARN_IF(mPrt != printData)) {
- return NS_ERROR_FAILURE;
- }
- if (NS_SUCCEEDED(rv)) {
- // since we got the dialog and it worked then make sure we
- // are telling GFX we want to print silent
- printSilently = true;
- if (printData->mPrintSettings && !aIsPrintPreview) {
- // The user might have changed shrink-to-fit in the print dialog, so update our copy of its state
- printData->mPrintSettings->GetShrinkToFit(&printData->mShrinkToFit);
- // If we haven't already added the RemotePrintJob as a listener,
- // add it now if there is one.
- if (!remotePrintJobListening) {
- RefPtr<mozilla::layout::RemotePrintJobChild> remotePrintJob;
- printSession->GetRemotePrintJob(getter_AddRefs(remotePrintJob));
- if (NS_SUCCEEDED(rv) && remotePrintJob) {
- printData->mPrintProgressListeners.AppendElement(
- remotePrintJob);
- remotePrintJobListening = true;
- }
- }
- }
- } else if (rv == NS_ERROR_NOT_IMPLEMENTED) {
- // This means the Dialog service was there,
- // but they choose not to implement this dialog and
- // are looking for default behavior from the toolkit
- rv = NS_OK;
- }
- } else {
- // No dialog service available
- rv = NS_ERROR_NOT_IMPLEMENTED;
- }
- } else {
- // Call any code that requires a run of the event loop.
- rv = printData->mPrintSettings->SetupSilentPrinting();
- }
- // Check explicitly for abort because it's expected
- if (rv == NS_ERROR_ABORT)
- return rv;
- NS_ENSURE_SUCCESS(rv, rv);
- }
- rv = devspec->Init(nullptr, printData->mPrintSettings, aIsPrintPreview);
- NS_ENSURE_SUCCESS(rv, rv);
- printData->mPrintDC = new nsDeviceContext();
- rv = printData->mPrintDC->InitForPrinting(devspec);
- NS_ENSURE_SUCCESS(rv, rv);
- if (aIsPrintPreview) {
- printData->mPrintSettings->SetPrintFrameType(nsIPrintSettings::kFramesAsIs);
- // override any UI that wants to PrintPreview any selection or page range
- // we want to view every page in PrintPreview each time
- printData->mPrintSettings->SetPrintRange(nsIPrintSettings::kRangeAllPages);
- } else {
- // Always check and set the print settings first and then fall back
- // onto the PrintService if there isn't a PrintSettings
- //
- // Posiible Usage values:
- // nsIPrintSettings::kUseInternalDefault
- // nsIPrintSettings::kUseSettingWhenPossible
- //
- // NOTE: The consts are the same for PrintSettings and PrintSettings
- int16_t printFrameTypeUsage = nsIPrintSettings::kUseSettingWhenPossible;
- printData->mPrintSettings->GetPrintFrameTypeUsage(&printFrameTypeUsage);
- // Ok, see if we are going to use our value and override the default
- if (printFrameTypeUsage == nsIPrintSettings::kUseSettingWhenPossible) {
- // Get the Print Options/Settings PrintFrameType to see what is preferred
- int16_t printFrameType = nsIPrintSettings::kEachFrameSep;
- printData->mPrintSettings->GetPrintFrameType(&printFrameType);
- // Don't let anybody do something stupid like try to set it to
- // kNoFrames when we are printing a FrameSet
- if (printFrameType == nsIPrintSettings::kNoFrames) {
- printData->mPrintFrameType = nsIPrintSettings::kEachFrameSep;
- printData->mPrintSettings->SetPrintFrameType(
- printData->mPrintFrameType);
- } else {
- // First find out from the PrinService what options are available
- // to us for Printing FrameSets
- int16_t howToEnableFrameUI;
- printData->mPrintSettings->GetHowToEnableFrameUI(&howToEnableFrameUI);
- if (howToEnableFrameUI != nsIPrintSettings::kFrameEnableNone) {
- switch (howToEnableFrameUI) {
- case nsIPrintSettings::kFrameEnableAll:
- printData->mPrintFrameType = printFrameType;
- break;
- case nsIPrintSettings::kFrameEnableAsIsAndEach:
- if (printFrameType != nsIPrintSettings::kSelectedFrame) {
- printData->mPrintFrameType = printFrameType;
- } else { // revert back to a good value
- printData->mPrintFrameType = nsIPrintSettings::kEachFrameSep;
- }
- break;
- } // switch
- printData->mPrintSettings->SetPrintFrameType(
- printData->mPrintFrameType);
- }
- }
- } else {
- printData->mPrintSettings->GetPrintFrameType(&printData->mPrintFrameType);
- }
- }
- if (printData->mPrintFrameType == nsIPrintSettings::kEachFrameSep) {
- CheckForChildFrameSets(printData->mPrintObject);
- }
- if (NS_FAILED(EnablePOsForPrinting())) {
- return NS_ERROR_FAILURE;
- }
- // Attach progressListener to catch network requests.
- nsCOMPtr<nsIWebProgress> webProgress =
- do_QueryInterface(printData->mPrintObject->mDocShell);
- webProgress->AddProgressListener(
- static_cast<nsIWebProgressListener*>(this),
- nsIWebProgress::NOTIFY_STATE_REQUEST);
- mLoadCounter = 0;
- mDidLoadDataForPrinting = false;
- if (aIsPrintPreview) {
- bool notifyOnInit = false;
- ShowPrintProgress(false, notifyOnInit);
- // Very important! Turn Off scripting
- TurnScriptingOn(false);
- if (!notifyOnInit) {
- InstallPrintPreviewListener();
- rv = InitPrintDocConstruction(false);
- } else {
- rv = NS_OK;
- }
- } else {
- bool doNotify;
- ShowPrintProgress(true, doNotify);
- if (!doNotify) {
- // Print listener setup...
- printData->OnStartPrinting();
- rv = InitPrintDocConstruction(false);
- }
- }
- // We will enable scripting later after printing has finished.
- scriptSuppressor.Disconnect();
- return NS_OK;
- }
- //---------------------------------------------------------------------------------
- NS_IMETHODIMP
- nsPrintEngine::Print(nsIPrintSettings* aPrintSettings,
- nsIWebProgressListener* aWebProgressListener)
- {
- // If we have a print preview document, use that instead of the original
- // mDocument. That way animated images etc. get printed using the same state
- // as in print preview.
- nsCOMPtr<nsIDOMDocument> doc =
- do_QueryInterface(mPrtPreview && mPrtPreview->mPrintObject ?
- mPrtPreview->mPrintObject->mDocument : mDocument);
- return CommonPrint(false, aPrintSettings, aWebProgressListener, doc);
- }
- NS_IMETHODIMP
- nsPrintEngine::PrintPreview(nsIPrintSettings* aPrintSettings,
- mozIDOMWindowProxy* aChildDOMWin,
- nsIWebProgressListener* aWebProgressListener)
- {
- // Get the DocShell and see if it is busy
- // (We can't Print Preview this document if it is still busy)
- nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mContainer));
- NS_ENSURE_STATE(docShell);
- uint32_t busyFlags = nsIDocShell::BUSY_FLAGS_NONE;
- if (NS_FAILED(docShell->GetBusyFlags(&busyFlags)) ||
- busyFlags != nsIDocShell::BUSY_FLAGS_NONE) {
- CloseProgressDialog(aWebProgressListener);
- FirePrintingErrorEvent(NS_ERROR_GFX_PRINTER_DOC_IS_BUSY);
- return NS_ERROR_FAILURE;
- }
- auto* window = nsPIDOMWindowOuter::From(aChildDOMWin);
- NS_ENSURE_STATE(window);
- nsCOMPtr<nsIDocument> doc = window->GetDoc();
- NS_ENSURE_STATE(doc);
- nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(doc);
- MOZ_ASSERT(domDoc);
- // Document is not busy -- go ahead with the Print Preview
- return CommonPrint(true, aPrintSettings, aWebProgressListener, domDoc);
- }
- //----------------------------------------------------------------------------------
- NS_IMETHODIMP
- nsPrintEngine::GetIsFramesetDocument(bool *aIsFramesetDocument)
- {
- nsCOMPtr<nsIDocShell> webContainer(do_QueryReferent(mContainer));
- *aIsFramesetDocument = IsParentAFrameSet(webContainer);
- return NS_OK;
- }
- //----------------------------------------------------------------------------------
- NS_IMETHODIMP
- nsPrintEngine::GetIsIFrameSelected(bool *aIsIFrameSelected)
- {
- *aIsIFrameSelected = false;
- // Get the docshell for this documentviewer
- nsCOMPtr<nsIDocShell> webContainer(do_QueryReferent(mContainer));
- // Get the currently focused window
- nsCOMPtr<nsPIDOMWindowOuter> currentFocusWin = FindFocusedDOMWindow();
- if (currentFocusWin && webContainer) {
- // Get whether the doc contains a frameset
- // Also, check to see if the currently focus docshell
- // is a child of this docshell
- bool isParentFrameSet;
- *aIsIFrameSelected = IsThereAnIFrameSelected(webContainer, currentFocusWin, isParentFrameSet);
- }
- return NS_OK;
- }
- //----------------------------------------------------------------------------------
- NS_IMETHODIMP
- nsPrintEngine::GetIsRangeSelection(bool *aIsRangeSelection)
- {
- // Get the currently focused window
- nsCOMPtr<nsPIDOMWindowOuter> currentFocusWin = FindFocusedDOMWindow();
- *aIsRangeSelection = IsThereARangeSelection(currentFocusWin);
- return NS_OK;
- }
- //----------------------------------------------------------------------------------
- NS_IMETHODIMP
- nsPrintEngine::GetIsFramesetFrameSelected(bool *aIsFramesetFrameSelected)
- {
- // Get the currently focused window
- nsCOMPtr<nsPIDOMWindowOuter> currentFocusWin = FindFocusedDOMWindow();
- *aIsFramesetFrameSelected = currentFocusWin != nullptr;
- return NS_OK;
- }
- //----------------------------------------------------------------------------------
- NS_IMETHODIMP
- nsPrintEngine::GetPrintPreviewNumPages(int32_t *aPrintPreviewNumPages)
- {
- NS_ENSURE_ARG_POINTER(aPrintPreviewNumPages);
- nsIFrame* seqFrame = nullptr;
- *aPrintPreviewNumPages = 0;
- // When calling this function, the FinishPrintPreview() function might not
- // been called as there are still some
- RefPtr<nsPrintData> printData = mPrtPreview ? mPrtPreview : mPrt;
- if (NS_WARN_IF(!printData)) {
- return NS_ERROR_FAILURE;
- }
- nsresult rv =
- GetSeqFrameAndCountPagesInternal(printData->mPrintObject, seqFrame,
- *aPrintPreviewNumPages);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return NS_ERROR_FAILURE;
- }
- return NS_OK;
- }
- //----------------------------------------------------------------------------------
- // Enumerate all the documents for their titles
- NS_IMETHODIMP
- nsPrintEngine::EnumerateDocumentNames(uint32_t* aCount,
- char16_t*** aResult)
- {
- NS_ENSURE_ARG(aCount);
- NS_ENSURE_ARG_POINTER(aResult);
- *aCount = 0;
- *aResult = nullptr;
- int32_t numDocs = mPrt->mPrintDocList.Length();
- char16_t** array = (char16_t**) moz_xmalloc(numDocs * sizeof(char16_t*));
- if (!array)
- return NS_ERROR_OUT_OF_MEMORY;
- for (int32_t i=0;i<numDocs;i++) {
- nsPrintObject* po = mPrt->mPrintDocList.ElementAt(i);
- NS_ASSERTION(po, "nsPrintObject can't be null!");
- nsAutoString docTitleStr;
- nsAutoString docURLStr;
- GetDocumentTitleAndURL(po->mDocument, docTitleStr, docURLStr);
- // Use the URL if the doc is empty
- if (docTitleStr.IsEmpty() && !docURLStr.IsEmpty()) {
- docTitleStr = docURLStr;
- }
- array[i] = ToNewUnicode(docTitleStr);
- }
- *aCount = numDocs;
- *aResult = array;
- return NS_OK;
- }
- //----------------------------------------------------------------------------------
- nsresult
- nsPrintEngine::GetGlobalPrintSettings(nsIPrintSettings **aGlobalPrintSettings)
- {
- NS_ENSURE_ARG_POINTER(aGlobalPrintSettings);
- nsresult rv = NS_ERROR_FAILURE;
- nsCOMPtr<nsIPrintSettingsService> printSettingsService =
- do_GetService(sPrintSettingsServiceContractID, &rv);
- if (NS_SUCCEEDED(rv)) {
- rv = printSettingsService->GetGlobalPrintSettings(aGlobalPrintSettings);
- }
- return rv;
- }
- //----------------------------------------------------------------------------------
- NS_IMETHODIMP
- nsPrintEngine::GetDoingPrint(bool *aDoingPrint)
- {
- NS_ENSURE_ARG_POINTER(aDoingPrint);
- *aDoingPrint = mIsDoingPrinting;
- return NS_OK;
- }
- //----------------------------------------------------------------------------------
- NS_IMETHODIMP
- nsPrintEngine::GetDoingPrintPreview(bool *aDoingPrintPreview)
- {
- NS_ENSURE_ARG_POINTER(aDoingPrintPreview);
- *aDoingPrintPreview = mIsDoingPrintPreview;
- return NS_OK;
- }
- //----------------------------------------------------------------------------------
- NS_IMETHODIMP
- nsPrintEngine::GetCurrentPrintSettings(nsIPrintSettings * *aCurrentPrintSettings)
- {
- NS_ENSURE_ARG_POINTER(aCurrentPrintSettings);
- if (mPrt) {
- *aCurrentPrintSettings = mPrt->mPrintSettings;
- } else if (mPrtPreview) {
- *aCurrentPrintSettings = mPrtPreview->mPrintSettings;
- } else {
- *aCurrentPrintSettings = nullptr;
- }
- NS_IF_ADDREF(*aCurrentPrintSettings);
- return NS_OK;
- }
- //-----------------------------------------------------------------
- //-- Section: Pre-Reflow Methods
- //-----------------------------------------------------------------
- //---------------------------------------------------------------------
- // This method checks to see if there is at least one printer defined
- // and if so, it sets the first printer in the list as the default name
- // in the PrintSettings which is then used for Printer Preview
- nsresult
- nsPrintEngine::CheckForPrinters(nsIPrintSettings* aPrintSettings)
- {
- NS_ENSURE_ARG_POINTER(aPrintSettings);
- // See if aPrintSettings already has a printer
- nsXPIDLString printerName;
- nsresult rv = aPrintSettings->GetPrinterName(getter_Copies(printerName));
- if (NS_SUCCEEDED(rv) && !printerName.IsEmpty()) {
- return NS_OK;
- }
- // aPrintSettings doesn't have a printer set. Try to fetch the default.
- nsCOMPtr<nsIPrintSettingsService> printSettingsService =
- do_GetService(sPrintSettingsServiceContractID, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = printSettingsService->GetDefaultPrinterName(getter_Copies(printerName));
- if (NS_SUCCEEDED(rv) && !printerName.IsEmpty()) {
- rv = aPrintSettings->SetPrinterName(printerName.get());
- }
- return rv;
- }
- //----------------------------------------------------------------------
- // Set up to use the "pluggable" Print Progress Dialog
- void
- nsPrintEngine::ShowPrintProgress(bool aIsForPrinting, bool& aDoNotify)
- {
- // default to not notifying, that if something here goes wrong
- // or we aren't going to show the progress dialog we can straight into
- // reflowing the doc for printing.
- aDoNotify = false;
- // Assume we can't do progress and then see if we can
- bool showProgresssDialog = false;
- // if it is already being shown then don't bother to find out if it should be
- // so skip this and leave mShowProgressDialog set to FALSE
- if (!mProgressDialogIsShown) {
- showProgresssDialog = Preferences::GetBool("print.show_print_progress");
- }
- // Guarantee that mPrt and the objects it owns won't be deleted. If this
- // method shows a progress dialog and spins the event loop. So, mPrt may be
- // cleared or recreated.
- RefPtr<nsPrintData> printData = mPrt;
- // Turning off the showing of Print Progress in Prefs overrides
- // whether the calling PS desire to have it on or off, so only check PS if
- // prefs says it's ok to be on.
- if (showProgresssDialog) {
- printData->mPrintSettings->GetShowPrintProgress(&showProgresssDialog);
- }
- // Now open the service to get the progress dialog
- // If we don't get a service, that's ok, then just don't show progress
- if (showProgresssDialog) {
- nsCOMPtr<nsIPrintingPromptService> printPromptService(do_GetService(kPrintingPromptService));
- if (printPromptService) {
- nsPIDOMWindowOuter* domWin = mDocument->GetWindow();
- if (!domWin) return;
- nsCOMPtr<nsIDocShell> docShell = domWin->GetDocShell();
- if (!docShell) return;
- nsCOMPtr<nsIDocShellTreeOwner> owner;
- docShell->GetTreeOwner(getter_AddRefs(owner));
- nsCOMPtr<nsIWebBrowserChrome> browserChrome = do_GetInterface(owner);
- if (!browserChrome) return;
- bool isModal = true;
- browserChrome->IsWindowModal(&isModal);
- if (isModal) {
- // Showing a print progress dialog when printing a modal window
- // isn't supported. See bug 301560.
- return;
- }
- nsCOMPtr<nsIWebProgressListener> printProgressListener;
- nsCOMPtr<nsIWebBrowserPrint> wbp(do_QueryInterface(mDocViewerPrint));
- nsresult rv =
- printPromptService->ShowProgress(
- domWin, wbp, printData->mPrintSettings, this,
- aIsForPrinting,
- getter_AddRefs(printProgressListener),
- getter_AddRefs(printData->mPrintProgressParams),
- &aDoNotify);
- if (NS_SUCCEEDED(rv)) {
- if (printProgressListener) {
- printData->mPrintProgressListeners.AppendObject(
- printProgressListener);
- }
- if (printData->mPrintProgressParams) {
- SetDocAndURLIntoProgress(printData->mPrintObject,
- printData->mPrintProgressParams);
- }
- }
- }
- }
- }
- //---------------------------------------------------------------------
- bool
- nsPrintEngine::IsThereARangeSelection(nsPIDOMWindowOuter* aDOMWin)
- {
- if (mDisallowSelectionPrint)
- return false;
- nsCOMPtr<nsIPresShell> presShell;
- if (aDOMWin) {
- presShell = aDOMWin->GetDocShell()->GetPresShell();
- }
- if (!presShell)
- return false;
- // check here to see if there is a range selection
- // so we know whether to turn on the "Selection" radio button
- Selection* selection = presShell->GetCurrentSelection(SelectionType::eNormal);
- if (!selection) {
- return false;
- }
- int32_t rangeCount = selection->RangeCount();
- if (!rangeCount) {
- return false;
- }
- if (rangeCount > 1) {
- return true;
- }
- // check to make sure it isn't an insertion selection
- return selection->GetRangeAt(0) && !selection->IsCollapsed();
- }
- //---------------------------------------------------------------------
- bool
- nsPrintEngine::IsParentAFrameSet(nsIDocShell * aParent)
- {
- // See if the incoming doc is the root document
- if (!aParent) return false;
- // When it is the top level document we need to check
- // to see if it contains a frameset. If it does, then
- // we only want to print the doc's children and not the document itself
- // For anything else we always print all the children and the document
- // for example, if the doc contains an IFRAME we eant to print the child
- // document (the IFRAME) and then the rest of the document.
- //
- // XXX we really need to search the frame tree, and not the content
- // but there is no way to distinguish between IFRAMEs and FRAMEs
- // with the GetFrameType call.
- // Bug 53459 has been files so we can eventually distinguish
- // between IFRAME frames and FRAME frames
- bool isFrameSet = false;
- // only check to see if there is a frameset if there is
- // NO parent doc for this doc. meaning this parent is the root doc
- nsCOMPtr<nsIDocument> doc = aParent->GetDocument();
- if (doc) {
- nsIContent *rootElement = doc->GetRootElement();
- if (rootElement) {
- isFrameSet = HasFramesetChild(rootElement);
- }
- }
- return isFrameSet;
- }
- //---------------------------------------------------------------------
- // Recursively build a list of sub documents to be printed
- // that mirrors the document tree
- void
- nsPrintEngine::BuildDocTree(nsIDocShell * aParentNode,
- nsTArray<nsPrintObject*> * aDocList,
- nsPrintObject * aPO)
- {
- NS_ASSERTION(aParentNode, "Pointer is null!");
- NS_ASSERTION(aDocList, "Pointer is null!");
- NS_ASSERTION(aPO, "Pointer is null!");
- int32_t childWebshellCount;
- aParentNode->GetChildCount(&childWebshellCount);
- if (childWebshellCount > 0) {
- for (int32_t i=0;i<childWebshellCount;i++) {
- nsCOMPtr<nsIDocShellTreeItem> child;
- aParentNode->GetChildAt(i, getter_AddRefs(child));
- nsCOMPtr<nsIDocShell> childAsShell(do_QueryInterface(child));
- nsCOMPtr<nsIContentViewer> viewer;
- childAsShell->GetContentViewer(getter_AddRefs(viewer));
- if (viewer) {
- nsCOMPtr<nsIContentViewerFile> viewerFile(do_QueryInterface(viewer));
- if (viewerFile) {
- nsCOMPtr<nsIDOMDocument> doc = do_GetInterface(childAsShell);
- nsPrintObject * po = new nsPrintObject();
- po->mParent = aPO;
- nsresult rv = po->Init(childAsShell, doc, aPO->mPrintPreview);
- if (NS_FAILED(rv))
- NS_NOTREACHED("Init failed?");
- aPO->mKids.AppendElement(po);
- aDocList->AppendElement(po);
- BuildDocTree(childAsShell, aDocList, po);
- }
- }
- }
- }
- }
- //---------------------------------------------------------------------
- void
- nsPrintEngine::GetDocumentTitleAndURL(nsIDocument* aDoc,
- nsAString& aTitle,
- nsAString& aURLStr)
- {
- NS_ASSERTION(aDoc, "Pointer is null!");
- aTitle.Truncate();
- aURLStr.Truncate();
- nsCOMPtr<nsIDOMDocument> doc = do_QueryInterface(aDoc);
- doc->GetTitle(aTitle);
- nsIURI* url = aDoc->GetDocumentURI();
- if (!url) return;
- nsCOMPtr<nsIURIFixup> urifixup(do_GetService(NS_URIFIXUP_CONTRACTID));
- if (!urifixup) return;
- nsCOMPtr<nsIURI> exposableURI;
- urifixup->CreateExposableURI(url, getter_AddRefs(exposableURI));
- if (!exposableURI) return;
- nsAutoCString urlCStr;
- nsresult rv = exposableURI->GetSpec(urlCStr);
- if (NS_FAILED(rv)) return;
- nsCOMPtr<nsITextToSubURI> textToSubURI =
- do_GetService(NS_ITEXTTOSUBURI_CONTRACTID, &rv);
- if (NS_FAILED(rv)) return;
- textToSubURI->UnEscapeURIForUI(NS_LITERAL_CSTRING("UTF-8"),
- urlCStr, aURLStr);
- }
- //---------------------------------------------------------------------
- // The walks the PO tree and for each document it walks the content
- // tree looking for any content that are sub-shells
- //
- // It then sets the mContent pointer in the "found" PO object back to the
- // the document that contained it.
- void
- nsPrintEngine::MapContentToWebShells(nsPrintObject* aRootPO,
- nsPrintObject* aPO)
- {
- NS_ASSERTION(aRootPO, "Pointer is null!");
- NS_ASSERTION(aPO, "Pointer is null!");
- // Recursively walk the content from the root item
- // XXX Would be faster to enumerate the subdocuments, although right now
- // nsIDocument doesn't expose quite what would be needed.
- nsCOMPtr<nsIContentViewer> viewer;
- aPO->mDocShell->GetContentViewer(getter_AddRefs(viewer));
- if (!viewer) return;
- nsCOMPtr<nsIDOMDocument> domDoc;
- viewer->GetDOMDocument(getter_AddRefs(domDoc));
- nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
- if (!doc) return;
- Element* rootElement = doc->GetRootElement();
- if (rootElement) {
- MapContentForPO(aPO, rootElement);
- } else {
- NS_WARNING("Null root content on (sub)document.");
- }
- // Continue recursively walking the chilren of this PO
- for (uint32_t i=0;i<aPO->mKids.Length();i++) {
- MapContentToWebShells(aRootPO, aPO->mKids[i]);
- }
- }
- //-------------------------------------------------------
- // A Frame's sub-doc may contain content or a FrameSet
- // When it contains a FrameSet the mFrameType for the PrintObject
- // is always set to an eFrame. Which is fine when printing "AsIs"
- // but is incorrect when when printing "Each Frame Separately".
- // When printing "Each Frame Separately" the Frame really acts like
- // a frameset.
- //
- // This method walks the PO tree and checks to see if the PrintObject is
- // an eFrame and has children that are eFrames (meaning it's a Frame containing a FrameSet)
- // If so, then the mFrameType need to be changed to eFrameSet
- //
- // Also note: We only want to call this we are printing "Each Frame Separately"
- // when printing "As Is" leave it as an eFrame
- void
- nsPrintEngine::CheckForChildFrameSets(nsPrintObject* aPO)
- {
- NS_ASSERTION(aPO, "Pointer is null!");
- // Continue recursively walking the chilren of this PO
- bool hasChildFrames = false;
- for (uint32_t i=0;i<aPO->mKids.Length();i++) {
- nsPrintObject* po = aPO->mKids[i];
- if (po->mFrameType == eFrame) {
- hasChildFrames = true;
- CheckForChildFrameSets(po);
- }
- }
- if (hasChildFrames && aPO->mFrameType == eFrame) {
- aPO->mFrameType = eFrameSet;
- }
- }
- //---------------------------------------------------------------------
- // This method is key to the entire print mechanism.
- //
- // This "maps" or figures out which sub-doc represents a
- // given Frame or IFrame in its parent sub-doc.
- //
- // So the Mcontent pointer in the child sub-doc points to the
- // content in the its parent document, that caused it to be printed.
- // This is used later to (after reflow) to find the absolute location
- // of the sub-doc on its parent's page frame so it can be
- // printed in the correct location.
- //
- // This method recursvely "walks" the content for a document finding
- // all the Frames and IFrames, then sets the "mFrameType" data member
- // which tells us what type of PO we have
- void
- nsPrintEngine::MapContentForPO(nsPrintObject* aPO,
- nsIContent* aContent)
- {
- NS_PRECONDITION(aPO && aContent, "Null argument");
- nsIDocument* doc = aContent->GetComposedDoc();
- NS_ASSERTION(doc, "Content without a document from a document tree?");
- nsIDocument* subDoc = doc->GetSubDocumentFor(aContent);
- if (subDoc) {
- nsCOMPtr<nsIDocShell> docShell(subDoc->GetDocShell());
- if (docShell) {
- nsPrintObject * po = nullptr;
- int32_t cnt = aPO->mKids.Length();
- for (int32_t i=0;i<cnt;i++) {
- nsPrintObject* kid = aPO->mKids.ElementAt(i);
- if (kid->mDocument == subDoc) {
- po = kid;
- break;
- }
- }
- // XXX If a subdocument has no onscreen presentation, there will be no PO
- // This is even if there should be a print presentation
- if (po) {
- nsCOMPtr<nsIDOMHTMLFrameElement> frame(do_QueryInterface(aContent));
- // "frame" elements not in a frameset context should be treated
- // as iframes
- if (frame && po->mParent->mFrameType == eFrameSet) {
- po->mFrameType = eFrame;
- } else {
- // Assume something iframe-like, i.e. iframe, object, or embed
- po->mFrameType = eIFrame;
- SetPrintAsIs(po, true);
- NS_ASSERTION(po->mParent, "The root must be a parent");
- po->mParent->mPrintAsIs = true;
- }
- }
- }
- }
- // walk children content
- for (nsIContent* child = aContent->GetFirstChild();
- child;
- child = child->GetNextSibling()) {
- MapContentForPO(aPO, child);
- }
- }
- //---------------------------------------------------------------------
- bool
- nsPrintEngine::IsThereAnIFrameSelected(nsIDocShell* aDocShell,
- nsPIDOMWindowOuter* aDOMWin,
- bool& aIsParentFrameSet)
- {
- aIsParentFrameSet = IsParentAFrameSet(aDocShell);
- bool iFrameIsSelected = false;
- if (mPrt && mPrt->mPrintObject) {
- nsPrintObject* po = FindPrintObjectByDOMWin(mPrt->mPrintObject, aDOMWin);
- iFrameIsSelected = po && po->mFrameType == eIFrame;
- } else {
- // First, check to see if we are a frameset
- if (!aIsParentFrameSet) {
- // Check to see if there is a currenlt focused frame
- // if so, it means the selected frame is either the main docshell
- // or an IFRAME
- if (aDOMWin) {
- // Get the main docshell's DOMWin to see if it matches
- // the frame that is selected
- nsPIDOMWindowOuter* domWin = aDocShell ? aDocShell->GetWindow() : nullptr;
- if (domWin != aDOMWin) {
- iFrameIsSelected = true; // we have a selected IFRAME
- }
- }
- }
- }
- return iFrameIsSelected;
- }
- //---------------------------------------------------------------------
- // Recursively sets all the PO items to be printed
- // from the given item down into the tree
- void
- nsPrintEngine::SetPrintPO(nsPrintObject* aPO, bool aPrint)
- {
- NS_ASSERTION(aPO, "Pointer is null!");
- // Set whether to print flag
- aPO->mDontPrint = !aPrint;
- for (uint32_t i=0;i<aPO->mKids.Length();i++) {
- SetPrintPO(aPO->mKids[i], aPrint);
- }
- }
- //---------------------------------------------------------------------
- // This will first use a Title and/or URL from the PrintSettings
- // if one isn't set then it uses the one from the document
- // then if not title is there we will make sure we send something back
- // depending on the situation.
- void
- nsPrintEngine::GetDisplayTitleAndURL(nsPrintObject* aPO,
- nsAString& aTitle,
- nsAString& aURLStr,
- eDocTitleDefault aDefType)
- {
- NS_ASSERTION(aPO, "Pointer is null!");
- if (!mPrt)
- return;
- aTitle.Truncate();
- aURLStr.Truncate();
- // First check to see if the PrintSettings has defined an alternate title
- // and use that if it did
- if (mPrt->mPrintSettings) {
- char16_t * docTitleStrPS = nullptr;
- char16_t * docURLStrPS = nullptr;
- mPrt->mPrintSettings->GetTitle(&docTitleStrPS);
- mPrt->mPrintSettings->GetDocURL(&docURLStrPS);
- if (docTitleStrPS) {
- aTitle = docTitleStrPS;
- }
- if (docURLStrPS) {
- aURLStr = docURLStrPS;
- }
- free(docTitleStrPS);
- free(docURLStrPS);
- }
- nsAutoString docTitle;
- nsAutoString docUrl;
- GetDocumentTitleAndURL(aPO->mDocument, docTitle, docUrl);
- if (aURLStr.IsEmpty() && !docUrl.IsEmpty()) {
- aURLStr = docUrl;
- }
- if (aTitle.IsEmpty()) {
- if (!docTitle.IsEmpty()) {
- aTitle = docTitle;
- } else {
- if (aDefType == eDocTitleDefURLDoc) {
- if (!aURLStr.IsEmpty()) {
- aTitle = aURLStr;
- } else if (mPrt->mBrandName) {
- aTitle = mPrt->mBrandName;
- }
- }
- }
- }
- }
- //---------------------------------------------------------------------
- nsresult nsPrintEngine::DocumentReadyForPrinting()
- {
- if (mPrt->mPrintFrameType == nsIPrintSettings::kEachFrameSep) {
- // Guarantee that mPrt->mPrintObject won't be deleted during a call of
- // CheckForChildFrameSets().
- RefPtr<nsPrintData> printData = mPrt;
- CheckForChildFrameSets(printData->mPrintObject);
- }
- //
- // Send the document to the printer...
- //
- nsresult rv = SetupToPrintContent();
- if (NS_FAILED(rv)) {
- // The print job was canceled or there was a problem
- // So remove all other documents from the print list
- DonePrintingPages(nullptr, rv);
- }
- return rv;
- }
- /** ---------------------------------------------------
- * Cleans up when an error occurred
- */
- nsresult nsPrintEngine::CleanupOnFailure(nsresult aResult, bool aIsPrinting)
- {
- PR_PL(("**** Failed %s - rv 0x%X", aIsPrinting?"Printing":"Print Preview", aResult));
- /* cleanup... */
- if (mPagePrintTimer) {
- mPagePrintTimer->Stop();
- DisconnectPagePrintTimer();
- }
- if (aIsPrinting) {
- SetIsPrinting(false);
- } else {
- SetIsPrintPreview(false);
- SetIsCreatingPrintPreview(false);
- }
- /* cleanup done, let's fire-up an error dialog to notify the user
- * what went wrong...
- *
- * When rv == NS_ERROR_ABORT, it means we want out of the
- * print job without displaying any error messages
- */
- if (aResult != NS_ERROR_ABORT) {
- FirePrintingErrorEvent(aResult);
- }
- FirePrintCompletionEvent();
- return aResult;
- }
- //---------------------------------------------------------------------
- void
- nsPrintEngine::FirePrintingErrorEvent(nsresult aPrintError)
- {
- nsCOMPtr<nsIContentViewer> cv = do_QueryInterface(mDocViewerPrint);
- if (NS_WARN_IF(!cv)) {
- return;
- }
- nsCOMPtr<nsIDocument> doc = cv->GetDocument();
- RefPtr<CustomEvent> event =
- NS_NewDOMCustomEvent(doc, nullptr, nullptr);
- MOZ_ASSERT(event);
- nsCOMPtr<nsIWritableVariant> resultVariant = new nsVariant();
- // nsresults are Uint32_t's, but XPConnect will interpret it as a double
- // when any JS attempts to access it, and will therefore interpret it
- // incorrectly. We preempt this by casting and setting as a double.
- resultVariant->SetAsDouble(static_cast<double>(aPrintError));
- event->InitCustomEvent(NS_LITERAL_STRING("PrintingError"), false, false,
- resultVariant);
- event->SetTrusted(true);
- RefPtr<AsyncEventDispatcher> asyncDispatcher =
- new AsyncEventDispatcher(doc, event);
- asyncDispatcher->mOnlyChromeDispatch = true;
- asyncDispatcher->RunDOMEventWhenSafe();
- // Inform any progress listeners of the Error.
- if (mPrt) {
- // Note that nsPrintData::DoOnStatusChange() will call some listeners.
- // So, mPrt can be cleared or recreated.
- RefPtr<nsPrintData> printData = mPrt;
- printData->DoOnStatusChange(aPrintError);
- }
- }
- //-----------------------------------------------------------------
- //-- Section: Reflow Methods
- //-----------------------------------------------------------------
- nsresult
- nsPrintEngine::ReconstructAndReflow(bool doSetPixelScale)
- {
- if (NS_WARN_IF(!mPrt)) {
- return NS_ERROR_FAILURE;
- }
- #if defined(XP_WIN) && defined(EXTENDED_DEBUG_PRINTING)
- // We need to clear all the output files here
- // because they will be re-created with second reflow of the docs
- if (kPrintingLogMod && kPrintingLogMod->level == DUMP_LAYOUT_LEVEL) {
- RemoveFilesInDir(".\\");
- gDumpFileNameCnt = 0;
- gDumpLOFileNameCnt = 0;
- }
- #endif
- // In this loop, it's conceivable that one of our helpers might clear mPrt,
- // while we're using it & its members! So we capture it in an owning local
- // reference & use that instead of using mPrt directly.
- RefPtr<nsPrintData> printData = mPrt;
- for (uint32_t i = 0; i < printData->mPrintDocList.Length(); ++i) {
- nsPrintObject* po = printData->mPrintDocList.ElementAt(i);
- NS_ASSERTION(po, "nsPrintObject can't be null!");
- if (po->mDontPrint || po->mInvisible) {
- continue;
- }
- UpdateZoomRatio(po, doSetPixelScale);
- po->mPresContext->SetPageScale(po->mZoomRatio);
- // Calculate scale factor from printer to screen
- float printDPI = float(printData->mPrintDC->AppUnitsPerCSSInch()) /
- float(printData->mPrintDC->AppUnitsPerDevPixel());
- po->mPresContext->SetPrintPreviewScale(mScreenDPI / printDPI);
- po->mPresShell->ReconstructFrames();
- // If the printing was canceled or restarted with different data,
- // let's stop doing this printing.
- if (NS_WARN_IF(mPrt != printData)) {
- return NS_ERROR_FAILURE;
- }
- // For all views except the first one, setup the root view.
- // ??? Can there be multiple po for the top-level-document?
- bool documentIsTopLevel = true;
- if (i != 0) {
- nsSize adjSize;
- bool doReturn;
- nsresult rv = SetRootView(po, doReturn, documentIsTopLevel, adjSize);
- MOZ_ASSERT(!documentIsTopLevel, "How could this happen?");
- if (NS_FAILED(rv) || doReturn) {
- return rv;
- }
- }
- po->mPresShell->FlushPendingNotifications(Flush_Layout);
- // If the printing was canceled or restarted with different data,
- // let's stop doing this printing.
- if (NS_WARN_IF(mPrt != printData)) {
- return NS_ERROR_FAILURE;
- }
- nsresult rv = UpdateSelectionAndShrinkPrintObject(po, documentIsTopLevel);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- return NS_OK;
- }
- //-------------------------------------------------------
- nsresult
- nsPrintEngine::SetupToPrintContent()
- {
- if (NS_WARN_IF(!mPrt)) {
- return NS_ERROR_FAILURE;
- }
- bool didReconstruction = false;
- // This method works with mPrt->mPrintObject. So, we need to guarantee that
- // it won't be deleted in this method. We achieve this by holding a strong
- // local reference to mPrt, which in turn keeps mPrintObject alive.
- RefPtr<nsPrintData> printData = mPrt;
- // If some new content got loaded since the initial reflow rebuild
- // everything.
- if (mDidLoadDataForPrinting) {
- nsresult rv = ReconstructAndReflow(DoSetPixelScale());
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- // If the printing was canceled or restarted with different data,
- // let's stop doing this printing.
- if (NS_WARN_IF(mPrt != printData)) {
- return NS_ERROR_FAILURE;
- }
- didReconstruction = true;
- }
- // Here is where we figure out if extra reflow for shrinking the content
- // is required.
- // But skip this step if we are in PrintPreview
- bool ppIsShrinkToFit = mPrtPreview && mPrtPreview->mShrinkToFit;
- if (printData->mShrinkToFit && !ppIsShrinkToFit) {
- // Now look for the PO that has the smallest percent for shrink to fit
- if (printData->mPrintDocList.Length() > 1 &&
- printData->mPrintObject->mFrameType == eFrameSet) {
- nsPrintObject* smallestPO = FindSmallestSTF();
- NS_ASSERTION(smallestPO, "There must always be an XMost PO!");
- if (smallestPO) {
- // Calc the shrinkage based on the entire content area
- printData->mShrinkRatio = smallestPO->mShrinkRatio;
- }
- } else {
- // Single document so use the Shrink as calculated for the PO
- printData->mShrinkRatio = printData->mPrintObject->mShrinkRatio;
- }
- if (printData->mShrinkRatio < 0.998f) {
- nsresult rv = ReconstructAndReflow(true);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- // If the printing was canceled or restarted with different data,
- // let's stop doing this printing.
- if (NS_WARN_IF(mPrt != printData)) {
- return NS_ERROR_FAILURE;
- }
- didReconstruction = true;
- }
- if (MOZ_LOG_TEST(gPrintingLog, LogLevel::Debug)) {
- float calcRatio = 0.0f;
- if (printData->mPrintDocList.Length() > 1 &&
- printData->mPrintObject->mFrameType == eFrameSet) {
- nsPrintObject* smallestPO = FindSmallestSTF();
- NS_ASSERTION(smallestPO, "There must always be an XMost PO!");
- if (smallestPO) {
- // Calc the shrinkage based on the entire content area
- calcRatio = smallestPO->mShrinkRatio;
- }
- } else {
- // Single document so use the Shrink as calculated for the PO
- calcRatio = printData->mPrintObject->mShrinkRatio;
- }
- PR_PL(("**************************************************************************\n"));
- PR_PL(("STF Ratio is: %8.5f Effective Ratio: %8.5f Diff: %8.5f\n",
- printData->mShrinkRatio, calcRatio,
- printData->mShrinkRatio-calcRatio));
- PR_PL(("**************************************************************************\n"));
- }
- }
- // If the frames got reconstructed and reflowed the number of pages might
- // has changed.
- if (didReconstruction) {
- FirePrintPreviewUpdateEvent();
- // If the printing was canceled or restarted with different data,
- // let's stop doing this printing.
- if (NS_WARN_IF(mPrt != printData)) {
- return NS_ERROR_FAILURE;
- }
- }
- DUMP_DOC_LIST(("\nAfter Reflow------------------------------------------"));
- PR_PL(("\n"));
- PR_PL(("-------------------------------------------------------\n"));
- PR_PL(("\n"));
- CalcNumPrintablePages(printData->mNumPrintablePages);
- PR_PL(("--- Printing %d pages\n", printData->mNumPrintablePages));
- DUMP_DOC_TREELAYOUT;
- // Print listener setup...
- printData->OnStartPrinting();
- // If the printing was canceled or restarted with different data,
- // let's stop doing this printing.
- if (NS_WARN_IF(mPrt != printData)) {
- return NS_ERROR_FAILURE;
- }
- nsAutoString fileNameStr;
- // check to see if we are printing to a file
- bool isPrintToFile = false;
- printData->mPrintSettings->GetPrintToFile(&isPrintToFile);
- if (isPrintToFile) {
- // On some platforms The BeginDocument needs to know the name of the file.
- char16_t* fileName = nullptr;
- printData->mPrintSettings->GetToFileName(&fileName);
- fileNameStr = fileName;
- }
- nsAutoString docTitleStr;
- nsAutoString docURLStr;
- GetDisplayTitleAndURL(printData->mPrintObject, docTitleStr, docURLStr,
- eDocTitleDefURLDoc);
- int32_t startPage = 1;
- int32_t endPage = printData->mNumPrintablePages;
- int16_t printRangeType = nsIPrintSettings::kRangeAllPages;
- printData->mPrintSettings->GetPrintRange(&printRangeType);
- if (printRangeType == nsIPrintSettings::kRangeSpecifiedPageRange) {
- printData->mPrintSettings->GetStartPageRange(&startPage);
- printData->mPrintSettings->GetEndPageRange(&endPage);
- if (endPage > printData->mNumPrintablePages) {
- endPage = printData->mNumPrintablePages;
- }
- }
- nsresult rv = NS_OK;
- // BeginDocument may pass back a FAILURE code
- // i.e. On Windows, if you are printing to a file and hit "Cancel"
- // to the "File Name" dialog, this comes back as an error
- // Don't start printing when regression test are executed
- if (!printData->mDebugFilePtr && mIsDoingPrinting) {
- rv = printData->mPrintDC->BeginDocument(docTitleStr, fileNameStr, startPage,
- endPage);
- }
- if (mIsCreatingPrintPreview) {
- // Copy docTitleStr and docURLStr to the pageSequenceFrame, to be displayed
- // in the header
- nsIPageSequenceFrame* seqFrame =
- printData->mPrintObject->mPresShell->GetPageSequenceFrame();
- if (seqFrame) {
- seqFrame->StartPrint(printData->mPrintObject->mPresContext,
- printData->mPrintSettings, docTitleStr, docURLStr);
- }
- }
- PR_PL(("****************** Begin Document ************************\n"));
- NS_ENSURE_SUCCESS(rv, rv);
- // This will print the docshell document
- // when it completes asynchronously in the DonePrintingPages method
- // it will check to see if there are more docshells to be printed and
- // then PrintDocContent will be called again.
- if (mIsDoingPrinting) {
- PrintDocContent(printData->mPrintObject, rv); // ignore return value
- }
- return rv;
- }
- //-------------------------------------------------------
- // Recursively reflow each sub-doc and then calc
- // all the frame locations of the sub-docs
- nsresult
- nsPrintEngine::ReflowDocList(nsPrintObject* aPO, bool aSetPixelScale)
- {
- NS_ENSURE_ARG_POINTER(aPO);
- // Check to see if the subdocument's element has been hidden by the parent document
- if (aPO->mParent && aPO->mParent->mPresShell) {
- nsIFrame* frame = aPO->mContent ? aPO->mContent->GetPrimaryFrame() : nullptr;
- if (!frame || !frame->StyleVisibility()->IsVisible()) {
- SetPrintPO(aPO, false);
- aPO->mInvisible = true;
- return NS_OK;
- }
- }
- UpdateZoomRatio(aPO, aSetPixelScale);
- nsresult rv;
- // Reflow the PO
- rv = ReflowPrintObject(aPO);
- NS_ENSURE_SUCCESS(rv, rv);
- int32_t cnt = aPO->mKids.Length();
- for (int32_t i=0;i<cnt;i++) {
- rv = ReflowDocList(aPO->mKids[i], aSetPixelScale);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- return NS_OK;
- }
- void
- nsPrintEngine::FirePrintPreviewUpdateEvent()
- {
- // Dispatch the event only while in PrintPreview. When printing, there is no
- // listener bound to this event and therefore no need to dispatch it.
- if (mIsDoingPrintPreview && !mIsDoingPrinting) {
- nsCOMPtr<nsIContentViewer> cv = do_QueryInterface(mDocViewerPrint);
- (new AsyncEventDispatcher(
- cv->GetDocument(), NS_LITERAL_STRING("printPreviewUpdate"), true, true)
- )->RunDOMEventWhenSafe();
- }
- }
- nsresult
- nsPrintEngine::InitPrintDocConstruction(bool aHandleError)
- {
- nsresult rv;
- // Guarantee that mPrt->mPrintObject won't be deleted. It's owned by mPrt.
- // So, we should grab it with local variable.
- RefPtr<nsPrintData> printData = mPrt;
- rv = ReflowDocList(printData->mPrintObject, DoSetPixelScale());
- NS_ENSURE_SUCCESS(rv, rv);
- FirePrintPreviewUpdateEvent();
- if (mLoadCounter == 0) {
- AfterNetworkPrint(aHandleError);
- }
- return rv;
- }
- nsresult
- nsPrintEngine::AfterNetworkPrint(bool aHandleError)
- {
- nsCOMPtr<nsIWebProgress> webProgress = do_QueryInterface(mPrt->mPrintObject->mDocShell);
- webProgress->RemoveProgressListener(
- static_cast<nsIWebProgressListener*>(this));
- nsresult rv;
- if (mIsDoingPrinting) {
- rv = DocumentReadyForPrinting();
- } else {
- rv = FinishPrintPreview();
- }
- /* cleaup on failure + notify user */
- if (aHandleError && NS_FAILED(rv)) {
- NS_WARNING("nsPrintEngine::AfterNetworkPrint failed");
- CleanupOnFailure(rv, !mIsDoingPrinting);
- }
- return rv;
- }
- ////////////////////////////////////////////////////////////////////////////////
- // nsIWebProgressListener
- NS_IMETHODIMP
- nsPrintEngine::OnStateChange(nsIWebProgress* aWebProgress,
- nsIRequest* aRequest,
- uint32_t aStateFlags,
- nsresult aStatus)
- {
- nsAutoCString name;
- aRequest->GetName(name);
- if (name.EqualsLiteral("about:document-onload-blocker")) {
- return NS_OK;
- }
- if (aStateFlags & STATE_START) {
- ++mLoadCounter;
- } else if (aStateFlags & STATE_STOP) {
- mDidLoadDataForPrinting = true;
- --mLoadCounter;
- // If all resources are loaded, then do a small timeout and if there
- // are still no new requests, then another reflow.
- if (mLoadCounter == 0) {
- AfterNetworkPrint(true);
- }
- }
- return NS_OK;
- }
- NS_IMETHODIMP
- nsPrintEngine::OnProgressChange(nsIWebProgress* aWebProgress,
- nsIRequest* aRequest,
- int32_t aCurSelfProgress,
- int32_t aMaxSelfProgress,
- int32_t aCurTotalProgress,
- int32_t aMaxTotalProgress)
- {
- NS_NOTREACHED("notification excluded in AddProgressListener(...)");
- return NS_OK;
- }
- NS_IMETHODIMP
- nsPrintEngine::OnLocationChange(nsIWebProgress* aWebProgress,
- nsIRequest* aRequest,
- nsIURI* aLocation,
- uint32_t aFlags)
- {
- NS_NOTREACHED("notification excluded in AddProgressListener(...)");
- return NS_OK;
- }
- NS_IMETHODIMP
- nsPrintEngine::OnStatusChange(nsIWebProgress *aWebProgress,
- nsIRequest *aRequest,
- nsresult aStatus,
- const char16_t *aMessage)
- {
- NS_NOTREACHED("notification excluded in AddProgressListener(...)");
- return NS_OK;
- }
- NS_IMETHODIMP
- nsPrintEngine::OnSecurityChange(nsIWebProgress *aWebProgress,
- nsIRequest *aRequest,
- uint32_t aState)
- {
- NS_NOTREACHED("notification excluded in AddProgressListener(...)");
- return NS_OK;
- }
- //-------------------------------------------------------
- void
- nsPrintEngine::UpdateZoomRatio(nsPrintObject* aPO, bool aSetPixelScale)
- {
- // Here is where we set the shrinkage value into the DC
- // and this is what actually makes it shrink
- if (aSetPixelScale && aPO->mFrameType != eIFrame) {
- float ratio;
- if (mPrt->mPrintFrameType == nsIPrintSettings::kFramesAsIs || mPrt->mPrintFrameType == nsIPrintSettings::kNoFrames) {
- ratio = mPrt->mShrinkRatio - 0.005f; // round down
- } else {
- ratio = aPO->mShrinkRatio - 0.005f; // round down
- }
- aPO->mZoomRatio = ratio;
- } else if (!mPrt->mShrinkToFit) {
- double scaling;
- mPrt->mPrintSettings->GetScaling(&scaling);
- aPO->mZoomRatio = float(scaling);
- }
- }
- nsresult
- nsPrintEngine::UpdateSelectionAndShrinkPrintObject(nsPrintObject* aPO,
- bool aDocumentIsTopLevel)
- {
- nsCOMPtr<nsIPresShell> displayShell = aPO->mDocShell->GetPresShell();
- // Transfer Selection Ranges to the new Print PresShell
- RefPtr<Selection> selection, selectionPS;
- // It's okay if there is no display shell, just skip copying the selection
- if (displayShell) {
- selection = displayShell->GetCurrentSelection(SelectionType::eNormal);
- }
- selectionPS = aPO->mPresShell->GetCurrentSelection(SelectionType::eNormal);
- // Reset all existing selection ranges that might have been added by calling
- // this function before.
- if (selectionPS) {
- selectionPS->RemoveAllRanges();
- }
- if (selection && selectionPS) {
- int32_t cnt = selection->RangeCount();
- int32_t inx;
- for (inx = 0; inx < cnt; ++inx) {
- selectionPS->AddRange(selection->GetRangeAt(inx));
- }
- }
- // If we are trying to shrink the contents to fit on the page
- // we must first locate the "pageContent" frame
- // Then we walk the frame tree and look for the "xmost" frame
- // this is the frame where the right-hand side of the frame extends
- // the furthest
- if (mPrt->mShrinkToFit && aDocumentIsTopLevel) {
- nsIPageSequenceFrame* pageSequence = aPO->mPresShell->GetPageSequenceFrame();
- NS_ENSURE_STATE(pageSequence);
- pageSequence->GetSTFPercent(aPO->mShrinkRatio);
- // Limit the shrink-to-fit scaling for some text-ish type of documents.
- nsAutoString contentType;
- aPO->mPresShell->GetDocument()->GetContentType(contentType);
- if (contentType.EqualsLiteral("application/xhtml+xml") ||
- StringBeginsWith(contentType, NS_LITERAL_STRING("text/"))) {
- int32_t limitPercent =
- Preferences::GetInt("print.shrink-to-fit.scale-limit-percent", 20);
- limitPercent = std::max(0, limitPercent);
- limitPercent = std::min(100, limitPercent);
- float minShrinkRatio = float(limitPercent) / 100;
- aPO->mShrinkRatio = std::max(aPO->mShrinkRatio, minShrinkRatio);
- }
- }
- return NS_OK;
- }
- bool
- nsPrintEngine::DoSetPixelScale()
- {
- // This is an Optimization
- // If we are in PP then we already know all the shrinkage information
- // so just transfer it to the PrintData and we will skip the extra shrinkage reflow
- //
- // doSetPixelScale tells Reflow whether to set the shrinkage value into the DC
- // The first time we do not want to do this, the second time through we do
- bool doSetPixelScale = false;
- bool ppIsShrinkToFit = mPrtPreview && mPrtPreview->mShrinkToFit;
- if (ppIsShrinkToFit) {
- mPrt->mShrinkRatio = mPrtPreview->mShrinkRatio;
- doSetPixelScale = true;
- }
- return doSetPixelScale;
- }
- nsView*
- nsPrintEngine::GetParentViewForRoot()
- {
- if (mIsCreatingPrintPreview) {
- nsCOMPtr<nsIContentViewer> cv = do_QueryInterface(mDocViewerPrint);
- if (cv) {
- return cv->FindContainerView();
- }
- }
- return nullptr;
- }
- nsresult
- nsPrintEngine::SetRootView(
- nsPrintObject* aPO,
- bool& doReturn,
- bool& documentIsTopLevel,
- nsSize& adjSize
- )
- {
- bool canCreateScrollbars = true;
- nsView* rootView;
- nsView* parentView = nullptr;
- doReturn = false;
- if (aPO->mParent && aPO->mParent->IsPrintable()) {
- nsIFrame* frame = aPO->mContent ? aPO->mContent->GetPrimaryFrame() : nullptr;
- // Without a frame, this document can't be displayed; therefore, there is no
- // point to reflowing it
- if (!frame) {
- SetPrintPO(aPO, false);
- doReturn = true;
- return NS_OK;
- }
- //XXX If printing supported printing document hierarchies with non-constant
- // zoom this would be wrong as we use the same mPrt->mPrintDC for all
- // subdocuments.
- adjSize = frame->GetContentRect().Size();
- documentIsTopLevel = false;
- // presshell exists because parent is printable
- // the top nsPrintObject's widget will always have scrollbars
- if (frame && frame->GetType() == nsGkAtoms::subDocumentFrame) {
- nsView* view = frame->GetView();
- NS_ENSURE_TRUE(view, NS_ERROR_FAILURE);
- view = view->GetFirstChild();
- NS_ENSURE_TRUE(view, NS_ERROR_FAILURE);
- parentView = view;
- canCreateScrollbars = false;
- }
- } else {
- nscoord pageWidth, pageHeight;
- mPrt->mPrintDC->GetDeviceSurfaceDimensions(pageWidth, pageHeight);
- adjSize = nsSize(pageWidth, pageHeight);
- documentIsTopLevel = true;
- parentView = GetParentViewForRoot();
- }
- if (aPO->mViewManager->GetRootView()) {
- // Reuse the root view that is already on the root frame.
- rootView = aPO->mViewManager->GetRootView();
- // Remove it from its existing parent if necessary
- aPO->mViewManager->RemoveChild(rootView);
- rootView->SetParent(parentView);
- } else {
- // Create a child window of the parent that is our "root view/window"
- nsRect tbounds = nsRect(nsPoint(0, 0), adjSize);
- rootView = aPO->mViewManager->CreateView(tbounds, parentView);
- NS_ENSURE_TRUE(rootView, NS_ERROR_OUT_OF_MEMORY);
- }
- if (mIsCreatingPrintPreview && documentIsTopLevel) {
- aPO->mPresContext->SetPaginatedScrolling(canCreateScrollbars);
- }
- // Setup hierarchical relationship in view manager
- aPO->mViewManager->SetRootView(rootView);
- return NS_OK;
- }
- // Reflow a nsPrintObject
- nsresult
- nsPrintEngine::ReflowPrintObject(nsPrintObject * aPO)
- {
- NS_ENSURE_STATE(aPO);
- if (!aPO->IsPrintable()) {
- return NS_OK;
- }
- NS_ASSERTION(!aPO->mPresContext, "Recreating prescontext");
- // Guarantee that mPrt and the objects it owns won't be deleted in this method
- // because it might be cleared if other modules called from here may fire
- // events, notifying observers and/or listeners.
- RefPtr<nsPrintData> printData = mPrt;
- // create the PresContext
- nsPresContext::nsPresContextType type =
- mIsCreatingPrintPreview ? nsPresContext::eContext_PrintPreview:
- nsPresContext::eContext_Print;
- nsView* parentView =
- aPO->mParent && aPO->mParent->IsPrintable() ? nullptr : GetParentViewForRoot();
- aPO->mPresContext = parentView ?
- new nsPresContext(aPO->mDocument, type) :
- new nsRootPresContext(aPO->mDocument, type);
- NS_ENSURE_TRUE(aPO->mPresContext, NS_ERROR_OUT_OF_MEMORY);
- aPO->mPresContext->SetPrintSettings(printData->mPrintSettings);
- // set the presentation context to the value in the print settings
- bool printBGColors;
- printData->mPrintSettings->GetPrintBGColors(&printBGColors);
- aPO->mPresContext->SetBackgroundColorDraw(printBGColors);
- printData->mPrintSettings->GetPrintBGImages(&printBGColors);
- aPO->mPresContext->SetBackgroundImageDraw(printBGColors);
- // init it with the DC
- nsresult rv = aPO->mPresContext->Init(printData->mPrintDC);
- NS_ENSURE_SUCCESS(rv, rv);
- aPO->mViewManager = new nsViewManager();
- rv = aPO->mViewManager->Init(printData->mPrintDC);
- NS_ENSURE_SUCCESS(rv,rv);
- StyleSetHandle styleSet = mDocViewerPrint->CreateStyleSet(aPO->mDocument);
- aPO->mPresShell = aPO->mDocument->CreateShell(aPO->mPresContext,
- aPO->mViewManager, styleSet);
- if (!aPO->mPresShell) {
- styleSet->Delete();
- return NS_ERROR_FAILURE;
- }
- styleSet->EndUpdate();
- // The pres shell now owns the style set object.
- bool doReturn = false;;
- bool documentIsTopLevel = false;
- nsSize adjSize;
- rv = SetRootView(aPO, doReturn, documentIsTopLevel, adjSize);
- if (NS_FAILED(rv) || doReturn) {
- return rv;
- }
- PR_PL(("In DV::ReflowPrintObject PO: %p pS: %p (%9s) Setting w,h to %d,%d\n", aPO, aPO->mPresShell.get(),
- gFrameTypesStr[aPO->mFrameType], adjSize.width, adjSize.height));
- // This docshell stuff is weird; will go away when we stop having multiple
- // presentations per document
- aPO->mPresContext->SetContainer(aPO->mDocShell);
- aPO->mPresShell->BeginObservingDocument();
- aPO->mPresContext->SetPageSize(adjSize);
- aPO->mPresContext->SetIsRootPaginatedDocument(documentIsTopLevel);
- aPO->mPresContext->SetPageScale(aPO->mZoomRatio);
- // Calculate scale factor from printer to screen
- float printDPI = float(printData->mPrintDC->AppUnitsPerCSSInch()) /
- float(printData->mPrintDC->AppUnitsPerDevPixel());
- aPO->mPresContext->SetPrintPreviewScale(mScreenDPI / printDPI);
- if (mIsCreatingPrintPreview && documentIsTopLevel) {
- mDocViewerPrint->SetPrintPreviewPresentation(aPO->mViewManager,
- aPO->mPresContext,
- aPO->mPresShell);
- }
- rv = aPO->mPresShell->Initialize(adjSize.width, adjSize.height);
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ASSERTION(aPO->mPresShell, "Presshell should still be here");
- // Process the reflow event Initialize posted
- aPO->mPresShell->FlushPendingNotifications(Flush_Layout);
- rv = UpdateSelectionAndShrinkPrintObject(aPO, documentIsTopLevel);
- NS_ENSURE_SUCCESS(rv, rv);
- #ifdef EXTENDED_DEBUG_PRINTING
- if (kPrintingLogMod && kPrintingLogMod->level == DUMP_LAYOUT_LEVEL) {
- nsAutoCString docStr;
- nsAutoCString urlStr;
- GetDocTitleAndURL(aPO, docStr, urlStr);
- char filename[256];
- sprintf(filename, "print_dump_%d.txt", gDumpFileNameCnt++);
- // Dump all the frames and view to a a file
- FILE * fd = fopen(filename, "w");
- if (fd) {
- nsIFrame *theRootFrame =
- aPO->mPresShell->FrameManager()->GetRootFrame();
- fprintf(fd, "Title: %s\n", docStr.get());
- fprintf(fd, "URL: %s\n", urlStr.get());
- fprintf(fd, "--------------- Frames ----------------\n");
- //RefPtr<gfxContext> renderingContext =
- // printData->mPrintDocDC->CreateRenderingContext();
- RootFrameList(aPO->mPresContext, fd, 0);
- //DumpFrames(fd, aPO->mPresContext, renderingContext, theRootFrame, 0);
- fprintf(fd, "---------------------------------------\n\n");
- fprintf(fd, "--------------- Views From Root Frame----------------\n");
- nsView* v = theRootFrame->GetView();
- if (v) {
- v->List(fd);
- } else {
- printf("View is null!\n");
- }
- if (docShell) {
- fprintf(fd, "--------------- All Views ----------------\n");
- DumpViews(docShell, fd);
- fprintf(fd, "---------------------------------------\n\n");
- }
- fclose(fd);
- }
- }
- #endif
- return NS_OK;
- }
- //-------------------------------------------------------
- // Figure out how many documents and how many total pages we are printing
- void
- nsPrintEngine::CalcNumPrintablePages(int32_t& aNumPages)
- {
- aNumPages = 0;
- // Count the number of printable documents
- // and printable pages
- for (uint32_t i=0; i<mPrt->mPrintDocList.Length(); i++) {
- nsPrintObject* po = mPrt->mPrintDocList.ElementAt(i);
- NS_ASSERTION(po, "nsPrintObject can't be null!");
- if (po->mPresContext && po->mPresContext->IsRootPaginatedDocument()) {
- nsIPageSequenceFrame* pageSequence = po->mPresShell->GetPageSequenceFrame();
- nsIFrame * seqFrame = do_QueryFrame(pageSequence);
- if (seqFrame) {
- aNumPages += seqFrame->PrincipalChildList().GetLength();
- }
- }
- }
- }
- //-----------------------------------------------------------------
- //-- Done: Reflow Methods
- //-----------------------------------------------------------------
- //-----------------------------------------------------------------
- //-- Section: Printing Methods
- //-----------------------------------------------------------------
- //-------------------------------------------------------
- // Called for each DocShell that needs to be printed
- bool
- nsPrintEngine::PrintDocContent(nsPrintObject* aPO, nsresult& aStatus)
- {
- NS_ASSERTION(aPO, "Pointer is null!");
- aStatus = NS_OK;
- if (!aPO->mHasBeenPrinted && aPO->IsPrintable()) {
- aStatus = DoPrint(aPO);
- return true;
- }
- // If |aPO->mPrintAsIs| and |aPO->mHasBeenPrinted| are true,
- // the kids frames are already processed in |PrintPage|.
- if (!aPO->mInvisible && !(aPO->mPrintAsIs && aPO->mHasBeenPrinted)) {
- for (uint32_t i=0;i<aPO->mKids.Length();i++) {
- nsPrintObject* po = aPO->mKids[i];
- bool printed = PrintDocContent(po, aStatus);
- if (printed || NS_FAILED(aStatus)) {
- return true;
- }
- }
- }
- return false;
- }
- static already_AddRefed<nsIDOMNode>
- GetEqualNodeInCloneTree(nsIDOMNode* aNode, nsIDocument* aDoc)
- {
- nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
- // Selections in anonymous subtrees aren't supported.
- if (content && content->IsInAnonymousSubtree()) {
- return nullptr;
- }
- nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
- NS_ENSURE_TRUE(node, nullptr);
- nsTArray<int32_t> indexArray;
- nsINode* current = node;
- NS_ENSURE_TRUE(current, nullptr);
- while (current) {
- nsINode* parent = current->GetParentNode();
- if (!parent) {
- break;
- }
- int32_t index = parent->IndexOf(current);
- NS_ENSURE_TRUE(index >= 0, nullptr);
- indexArray.AppendElement(index);
- current = parent;
- }
- NS_ENSURE_TRUE(current->IsNodeOfType(nsINode::eDOCUMENT), nullptr);
- current = aDoc;
- for (int32_t i = indexArray.Length() - 1; i >= 0; --i) {
- current = current->GetChildAt(indexArray[i]);
- NS_ENSURE_TRUE(current, nullptr);
- }
- nsCOMPtr<nsIDOMNode> result = do_QueryInterface(current);
- return result.forget();
- }
- static void
- CloneRangeToSelection(nsRange* aRange, nsIDocument* aDoc,
- Selection* aSelection)
- {
- if (aRange->Collapsed()) {
- return;
- }
- nsCOMPtr<nsIDOMNode> startContainer, endContainer;
- aRange->GetStartContainer(getter_AddRefs(startContainer));
- int32_t startOffset = aRange->StartOffset();
- aRange->GetEndContainer(getter_AddRefs(endContainer));
- int32_t endOffset = aRange->EndOffset();
- NS_ENSURE_TRUE_VOID(startContainer && endContainer);
- nsCOMPtr<nsIDOMNode> newStart = GetEqualNodeInCloneTree(startContainer, aDoc);
- nsCOMPtr<nsIDOMNode> newEnd = GetEqualNodeInCloneTree(endContainer, aDoc);
- NS_ENSURE_TRUE_VOID(newStart && newEnd);
- nsCOMPtr<nsINode> newStartNode = do_QueryInterface(newStart);
- nsCOMPtr<nsINode> newEndNode = do_QueryInterface(newEnd);
- if (NS_WARN_IF(!newStartNode) || NS_WARN_IF(!newEndNode)) {
- return;
- }
- RefPtr<nsRange> range = new nsRange(newStartNode);
- nsresult rv =
- range->SetStartAndEnd(newStartNode, startOffset, newEndNode, endOffset);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return;
- }
- aSelection->AddRange(range);
- }
- static nsresult CloneSelection(nsIDocument* aOrigDoc, nsIDocument* aDoc)
- {
- nsIPresShell* origShell = aOrigDoc->GetShell();
- nsIPresShell* shell = aDoc->GetShell();
- NS_ENSURE_STATE(origShell && shell);
- RefPtr<Selection> origSelection =
- origShell->GetCurrentSelection(SelectionType::eNormal);
- RefPtr<Selection> selection =
- shell->GetCurrentSelection(SelectionType::eNormal);
- NS_ENSURE_STATE(origSelection && selection);
- int32_t rangeCount = origSelection->RangeCount();
- for (int32_t i = 0; i < rangeCount; ++i) {
- CloneRangeToSelection(origSelection->GetRangeAt(i), aDoc, selection);
- }
- return NS_OK;
- }
- //-------------------------------------------------------
- nsresult
- nsPrintEngine::DoPrint(nsPrintObject * aPO)
- {
- PR_PL(("\n"));
- PR_PL(("**************************** %s ****************************\n", gFrameTypesStr[aPO->mFrameType]));
- PR_PL(("****** In DV::DoPrint PO: %p \n", aPO));
- nsIPresShell* poPresShell = aPO->mPresShell;
- nsPresContext* poPresContext = aPO->mPresContext;
- NS_ASSERTION(poPresContext, "PrintObject has not been reflowed");
- NS_ASSERTION(poPresContext->Type() != nsPresContext::eContext_PrintPreview,
- "How did this context end up here?");
- // Guarantee that mPrt and its owning objects won't be deleted in this method
- // because it might be cleared if other modules called from here may fire
- // events, notifying observers and/or listeners.
- RefPtr<nsPrintData> printData = mPrt;
- if (printData->mPrintProgressParams) {
- SetDocAndURLIntoProgress(aPO, printData->mPrintProgressParams);
- }
- {
- int16_t printRangeType = nsIPrintSettings::kRangeAllPages;
- nsresult rv;
- if (printData->mPrintSettings) {
- printData->mPrintSettings->GetPrintRange(&printRangeType);
- }
- // Ask the page sequence frame to print all the pages
- nsIPageSequenceFrame* pageSequence = poPresShell->GetPageSequenceFrame();
- NS_ASSERTION(nullptr != pageSequence, "no page sequence frame");
- // We are done preparing for printing, so we can turn this off
- printData->mPreparingForPrint = false;
- // printData->mDebugFilePtr this is onlu non-null when compiled for
- // debugging
- if (printData->mDebugFilePtr) {
- #ifdef DEBUG
- // output the regression test
- nsIFrame* root = poPresShell->FrameManager()->GetRootFrame();
- root->DumpRegressionData(poPresContext, printData->mDebugFilePtr, 0);
- fclose(printData->mDebugFilePtr);
- SetIsPrinting(false);
- #endif
- } else {
- #ifdef EXTENDED_DEBUG_PRINTING
- nsIFrame* rootFrame = poPresShell->FrameManager()->GetRootFrame();
- if (aPO->IsPrintable()) {
- nsAutoCString docStr;
- nsAutoCString urlStr;
- GetDocTitleAndURL(aPO, docStr, urlStr);
- DumpLayoutData(docStr.get(), urlStr.get(), poPresContext,
- printData->mPrintDocDC, rootFrame, docShell, nullptr);
- }
- #endif
- if (!printData->mPrintSettings) {
- // not sure what to do here!
- SetIsPrinting(false);
- return NS_ERROR_FAILURE;
- }
- nsAutoString docTitleStr;
- nsAutoString docURLStr;
- GetDisplayTitleAndURL(aPO, docTitleStr, docURLStr, eDocTitleDefBlank);
- if (nsIPrintSettings::kRangeSelection == printRangeType) {
- CloneSelection(aPO->mDocument->GetOriginalDocument(), aPO->mDocument);
- poPresContext->SetIsRenderingOnlySelection(true);
- // temporarily creating rendering context
- // which is needed to find the selection frames
- // mPrintDC must have positive width and height for this call
- // find the starting and ending page numbers
- // via the selection
- nsIFrame* startFrame;
- nsIFrame* endFrame;
- int32_t startPageNum;
- int32_t endPageNum;
- nsRect startRect;
- nsRect endRect;
- rv = GetPageRangeForSelection(pageSequence,
- &startFrame, startPageNum, startRect,
- &endFrame, endPageNum, endRect);
- if (NS_SUCCEEDED(rv)) {
- printData->mPrintSettings->SetStartPageRange(startPageNum);
- printData->mPrintSettings->SetEndPageRange(endPageNum);
- nsIntMargin marginTwips(0,0,0,0);
- nsIntMargin unwrtMarginTwips(0,0,0,0);
- printData->mPrintSettings->GetMarginInTwips(marginTwips);
- printData->mPrintSettings->GetUnwriteableMarginInTwips(
- unwrtMarginTwips);
- nsMargin totalMargin = poPresContext->CSSTwipsToAppUnits(marginTwips +
- unwrtMarginTwips);
- if (startPageNum == endPageNum) {
- startRect.y -= totalMargin.top;
- endRect.y -= totalMargin.top;
- // Clip out selection regions above the top of the first page
- if (startRect.y < 0) {
- // Reduce height to be the height of the positive-territory
- // region of original rect
- startRect.height = std::max(0, startRect.YMost());
- startRect.y = 0;
- }
- if (endRect.y < 0) {
- // Reduce height to be the height of the positive-territory
- // region of original rect
- endRect.height = std::max(0, endRect.YMost());
- endRect.y = 0;
- }
- NS_ASSERTION(endRect.y >= startRect.y,
- "Selection end point should be after start point");
- NS_ASSERTION(startRect.height >= 0,
- "rect should have non-negative height.");
- NS_ASSERTION(endRect.height >= 0,
- "rect should have non-negative height.");
- nscoord selectionHgt = endRect.y + endRect.height - startRect.y;
- // XXX This is temporary fix for printing more than one page of a selection
- pageSequence->SetSelectionHeight(startRect.y * aPO->mZoomRatio,
- selectionHgt * aPO->mZoomRatio);
- // calc total pages by getting calculating the selection's height
- // and then dividing it by how page content frames will fit.
- nscoord pageWidth, pageHeight;
- printData->mPrintDC->GetDeviceSurfaceDimensions(pageWidth,
- pageHeight);
- pageHeight -= totalMargin.top + totalMargin.bottom;
- int32_t totalPages = NSToIntCeil(float(selectionHgt) * aPO->mZoomRatio / float(pageHeight));
- pageSequence->SetTotalNumPages(totalPages);
- }
- }
- }
- nsIFrame * seqFrame = do_QueryFrame(pageSequence);
- if (!seqFrame) {
- SetIsPrinting(false);
- return NS_ERROR_FAILURE;
- }
- mPageSeqFrame = seqFrame;
- pageSequence->StartPrint(poPresContext, printData->mPrintSettings,
- docTitleStr, docURLStr);
- // Schedule Page to Print
- PR_PL(("Scheduling Print of PO: %p (%s) \n", aPO, gFrameTypesStr[aPO->mFrameType]));
- StartPagePrintTimer(aPO);
- }
- }
- return NS_OK;
- }
- //---------------------------------------------------------------------
- void
- nsPrintEngine::SetDocAndURLIntoProgress(nsPrintObject* aPO,
- nsIPrintProgressParams* aParams)
- {
- NS_ASSERTION(aPO, "Must have valid nsPrintObject");
- NS_ASSERTION(aParams, "Must have valid nsIPrintProgressParams");
- if (!aPO || !aPO->mDocShell || !aParams) {
- return;
- }
- const uint32_t kTitleLength = 64;
- nsAutoString docTitleStr;
- nsAutoString docURLStr;
- GetDisplayTitleAndURL(aPO, docTitleStr, docURLStr, eDocTitleDefURLDoc);
- // Make sure the Titles & URLS don't get too long for the progress dialog
- EllipseLongString(docTitleStr, kTitleLength, false);
- EllipseLongString(docURLStr, kTitleLength, true);
- aParams->SetDocTitle(docTitleStr.get());
- aParams->SetDocURL(docURLStr.get());
- }
- //---------------------------------------------------------------------
- void
- nsPrintEngine::EllipseLongString(nsAString& aStr, const uint32_t aLen, bool aDoFront)
- {
- // Make sure the URLS don't get too long for the progress dialog
- if (aLen >= 3 && aStr.Length() > aLen) {
- if (aDoFront) {
- nsAutoString newStr;
- newStr.AppendLiteral("...");
- newStr += Substring(aStr, aStr.Length() - (aLen - 3), aLen - 3);
- aStr = newStr;
- } else {
- aStr.SetLength(aLen - 3);
- aStr.AppendLiteral("...");
- }
- }
- }
- static bool
- DocHasPrintCallbackCanvas(nsIDocument* aDoc, void* aData)
- {
- if (!aDoc) {
- return true;
- }
- Element* root = aDoc->GetRootElement();
- if (!root) {
- return true;
- }
- RefPtr<nsContentList> canvases = NS_GetContentList(root,
- kNameSpaceID_XHTML,
- NS_LITERAL_STRING("canvas"));
- uint32_t canvasCount = canvases->Length(true);
- for (uint32_t i = 0; i < canvasCount; ++i) {
- HTMLCanvasElement* canvas = HTMLCanvasElement::FromContentOrNull(canvases->Item(i, false));
- if (canvas && canvas->GetMozPrintCallback()) {
- // This subdocument has a print callback. Set result and return false to
- // stop iteration.
- *static_cast<bool*>(aData) = true;
- return false;
- }
- }
- return true;
- }
- static bool
- DocHasPrintCallbackCanvas(nsIDocument* aDoc)
- {
- bool result = false;
- aDoc->EnumerateSubDocuments(&DocHasPrintCallbackCanvas, static_cast<void*>(&result));
- return result;
- }
- /**
- * Checks to see if the document this print engine is associated with has any
- * canvases that have a mozPrintCallback.
- * https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement#Properties
- */
- bool
- nsPrintEngine::HasPrintCallbackCanvas()
- {
- if (!mDocument) {
- return false;
- }
- // First check this mDocument.
- bool result = false;
- DocHasPrintCallbackCanvas(mDocument, static_cast<void*>(&result));
- // Also check the sub documents.
- return result || DocHasPrintCallbackCanvas(mDocument);
- }
- //-------------------------------------------------------
- bool
- nsPrintEngine::PrePrintPage()
- {
- NS_ASSERTION(mPageSeqFrame.IsAlive(), "mPageSeqFrame is not alive!");
- NS_ASSERTION(mPrt, "mPrt is null!");
- // Although these should NEVER be nullptr
- // This is added insurance, to make sure we don't crash in optimized builds
- if (!mPrt || !mPageSeqFrame.IsAlive()) {
- return true; // means we are done preparing the page.
- }
- // Guarantee that mPrt won't be deleted during a call of
- // FirePrintingErrorEvent().
- RefPtr<nsPrintData> printData = mPrt;
- // Check setting to see if someone request it be cancelled
- bool isCancelled = false;
- printData->mPrintSettings->GetIsCancelled(&isCancelled);
- if (isCancelled)
- return true;
- // Ask mPageSeqFrame if the page is ready to be printed.
- // If the page doesn't get printed at all, the |done| will be |true|.
- bool done = false;
- nsIPageSequenceFrame* pageSeqFrame = do_QueryFrame(mPageSeqFrame.GetFrame());
- nsresult rv = pageSeqFrame->PrePrintNextPage(mPagePrintTimer, &done);
- if (NS_FAILED(rv)) {
- // ??? ::PrintPage doesn't set |printData->mIsAborted = true| if
- // rv != NS_ERROR_ABORT, but I don't really understand why this should be
- // the right thing to do? Shouldn't |printData->mIsAborted| set to true
- // all the time if something went wrong?
- if (rv != NS_ERROR_ABORT) {
- FirePrintingErrorEvent(rv);
- printData->mIsAborted = true;
- }
- done = true;
- }
- return done;
- }
- bool
- nsPrintEngine::PrintPage(nsPrintObject* aPO,
- bool& aInRange)
- {
- NS_ASSERTION(aPO, "aPO is null!");
- NS_ASSERTION(mPageSeqFrame.IsAlive(), "mPageSeqFrame is not alive!");
- NS_ASSERTION(mPrt, "mPrt is null!");
- // Although these should NEVER be nullptr
- // This is added insurance, to make sure we don't crash in optimized builds
- if (!mPrt || !aPO || !mPageSeqFrame.IsAlive()) {
- FirePrintingErrorEvent(NS_ERROR_FAILURE);
- return true; // means we are done printing
- }
- // Guarantee that mPrt won't be deleted during a call of
- // nsPrintData::DoOnProgressChange() which runs some listeners,
- // which may clear (& might otherwise destroy).
- RefPtr<nsPrintData> printData = mPrt;
- PR_PL(("-----------------------------------\n"));
- PR_PL(("------ In DV::PrintPage PO: %p (%s)\n", aPO, gFrameTypesStr[aPO->mFrameType]));
- // Check setting to see if someone request it be cancelled
- bool isCancelled = false;
- printData->mPrintSettings->GetIsCancelled(&isCancelled);
- if (isCancelled || printData->mIsAborted) {
- return true;
- }
- int32_t pageNum, numPages, endPage;
- nsIPageSequenceFrame* pageSeqFrame = do_QueryFrame(mPageSeqFrame.GetFrame());
- pageSeqFrame->GetCurrentPageNum(&pageNum);
- pageSeqFrame->GetNumPages(&numPages);
- bool donePrinting;
- bool isDoingPrintRange;
- pageSeqFrame->IsDoingPrintRange(&isDoingPrintRange);
- if (isDoingPrintRange) {
- int32_t fromPage;
- int32_t toPage;
- pageSeqFrame->GetPrintRange(&fromPage, &toPage);
- if (fromPage > numPages) {
- return true;
- }
- if (toPage > numPages) {
- toPage = numPages;
- }
- PR_PL(("****** Printing Page %d printing from %d to page %d\n", pageNum, fromPage, toPage));
- donePrinting = pageNum >= toPage;
- aInRange = pageNum >= fromPage && pageNum <= toPage;
- endPage = (toPage - fromPage)+1;
- } else {
- PR_PL(("****** Printing Page %d of %d page(s)\n", pageNum, numPages));
- donePrinting = pageNum >= numPages;
- endPage = numPages;
- aInRange = true;
- }
- // XXX This is wrong, but the actual behavior in the presence of a print
- // range sucks.
- if (printData->mPrintFrameType == nsIPrintSettings::kEachFrameSep) {
- endPage = printData->mNumPrintablePages;
- }
- printData->DoOnProgressChange(++printData->mNumPagesPrinted,
- endPage, false, 0);
- if (NS_WARN_IF(mPrt != printData)) {
- // If current printing is canceled or new print is started, let's return
- // true to notify the caller of current printing is done.
- return true;
- }
- // Print the Page
- // if a print job was cancelled externally, an EndPage or BeginPage may
- // fail and the failure is passed back here.
- // Returning true means we are done printing.
- //
- // When rv == NS_ERROR_ABORT, it means we want out of the
- // print job without displaying any error messages
- nsresult rv = pageSeqFrame->PrintNextPage();
- if (NS_FAILED(rv)) {
- if (rv != NS_ERROR_ABORT) {
- FirePrintingErrorEvent(rv);
- printData->mIsAborted = true;
- }
- return true;
- }
- pageSeqFrame->DoPageEnd();
- return donePrinting;
- }
- /** ---------------------------------------------------
- * Find by checking frames type
- */
- nsresult
- nsPrintEngine::FindSelectionBoundsWithList(nsFrameList::Enumerator& aChildFrames,
- nsIFrame * aParentFrame,
- nsRect& aRect,
- nsIFrame *& aStartFrame,
- nsRect& aStartRect,
- nsIFrame *& aEndFrame,
- nsRect& aEndRect)
- {
- NS_ASSERTION(aParentFrame, "Pointer is null!");
- aRect += aParentFrame->GetPosition();
- for (; !aChildFrames.AtEnd(); aChildFrames.Next()) {
- nsIFrame* child = aChildFrames.get();
- if (child->IsSelected() && child->IsVisibleForPainting()) {
- nsRect r = child->GetRect();
- if (aStartFrame == nullptr) {
- aStartFrame = child;
- aStartRect.SetRect(aRect.x + r.x, aRect.y + r.y, r.width, r.height);
- } else {
- aEndFrame = child;
- aEndRect.SetRect(aRect.x + r.x, aRect.y + r.y, r.width, r.height);
- }
- }
- FindSelectionBounds(child, aRect, aStartFrame, aStartRect, aEndFrame, aEndRect);
- child = child->GetNextSibling();
- }
- aRect -= aParentFrame->GetPosition();
- return NS_OK;
- }
- //-------------------------------------------------------
- // Find the Frame that is XMost
- nsresult
- nsPrintEngine::FindSelectionBounds(nsIFrame * aParentFrame,
- nsRect& aRect,
- nsIFrame *& aStartFrame,
- nsRect& aStartRect,
- nsIFrame *& aEndFrame,
- nsRect& aEndRect)
- {
- NS_ASSERTION(aParentFrame, "Pointer is null!");
- // loop through named child lists
- nsIFrame::ChildListIterator lists(aParentFrame);
- for (; !lists.IsDone(); lists.Next()) {
- nsFrameList::Enumerator childFrames(lists.CurrentList());
- nsresult rv = FindSelectionBoundsWithList(childFrames, aParentFrame, aRect,
- aStartFrame, aStartRect, aEndFrame, aEndRect);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- return NS_OK;
- }
- /** ---------------------------------------------------
- * This method finds the starting and ending page numbers
- * of the selection and also returns rect for each where
- * the x,y of the rect is relative to the very top of the
- * frame tree (absolutely positioned)
- */
- nsresult
- nsPrintEngine::GetPageRangeForSelection(nsIPageSequenceFrame* aPageSeqFrame,
- nsIFrame** aStartFrame,
- int32_t& aStartPageNum,
- nsRect& aStartRect,
- nsIFrame** aEndFrame,
- int32_t& aEndPageNum,
- nsRect& aEndRect)
- {
- NS_ASSERTION(aPageSeqFrame, "Pointer is null!");
- NS_ASSERTION(aStartFrame, "Pointer is null!");
- NS_ASSERTION(aEndFrame, "Pointer is null!");
- nsIFrame * seqFrame = do_QueryFrame(aPageSeqFrame);
- if (!seqFrame) {
- return NS_ERROR_FAILURE;
- }
- nsIFrame * startFrame = nullptr;
- nsIFrame * endFrame = nullptr;
- // start out with the sequence frame and search the entire frame tree
- // capturing the starting and ending child frames of the selection
- // and their rects
- nsRect r = seqFrame->GetRect();
- FindSelectionBounds(seqFrame, r, startFrame, aStartRect, endFrame, aEndRect);
- #ifdef DEBUG_rodsX
- printf("Start Frame: %p\n", startFrame);
- printf("End Frame: %p\n", endFrame);
- #endif
- // initial the page numbers here
- // in case we don't find and frames
- aStartPageNum = -1;
- aEndPageNum = -1;
- nsIFrame * startPageFrame;
- nsIFrame * endPageFrame;
- // check to make sure we found a starting frame
- if (startFrame != nullptr) {
- // Now search up the tree to find what page the
- // start/ending selections frames are on
- //
- // Check to see if start should be same as end if
- // the end frame comes back null
- if (endFrame == nullptr) {
- // XXX the "GetPageFrame" step could be integrated into
- // the FindSelectionBounds step, but walking up to find
- // the parent of a child frame isn't expensive and it makes
- // FindSelectionBounds a little easier to understand
- startPageFrame = nsLayoutUtils::GetPageFrame(startFrame);
- endPageFrame = startPageFrame;
- aEndRect = aStartRect;
- } else {
- startPageFrame = nsLayoutUtils::GetPageFrame(startFrame);
- endPageFrame = nsLayoutUtils::GetPageFrame(endFrame);
- }
- } else {
- return NS_ERROR_FAILURE;
- }
- #ifdef DEBUG_rodsX
- printf("Start Page: %p\n", startPageFrame);
- printf("End Page: %p\n", endPageFrame);
- // dump all the pages and their pointers
- {
- int32_t pageNum = 1;
- nsIFrame* child = seqFrame->PrincipalChildList().FirstChild();
- while (child != nullptr) {
- printf("Page: %d - %p\n", pageNum, child);
- pageNum++;
- child = child->GetNextSibling();
- }
- }
- #endif
- // Now that we have the page frames
- // find out what the page numbers are for each frame
- int32_t pageNum = 1;
- for (nsIFrame* page : seqFrame->PrincipalChildList()) {
- if (page == startPageFrame) {
- aStartPageNum = pageNum;
- }
- if (page == endPageFrame) {
- aEndPageNum = pageNum;
- }
- pageNum++;
- }
- #ifdef DEBUG_rodsX
- printf("Start Page No: %d\n", aStartPageNum);
- printf("End Page No: %d\n", aEndPageNum);
- #endif
- *aStartFrame = startPageFrame;
- *aEndFrame = endPageFrame;
- return NS_OK;
- }
- //-----------------------------------------------------------------
- //-- Done: Printing Methods
- //-----------------------------------------------------------------
- //-----------------------------------------------------------------
- //-- Section: Misc Support Methods
- //-----------------------------------------------------------------
- //---------------------------------------------------------------------
- void nsPrintEngine::SetIsPrinting(bool aIsPrinting)
- {
- mIsDoingPrinting = aIsPrinting;
- // Calling SetIsPrinting while in print preview confuses the document viewer
- // This is safe because we prevent exiting print preview while printing
- if (!mIsDoingPrintPreview && mDocViewerPrint) {
- mDocViewerPrint->SetIsPrinting(aIsPrinting);
- }
- if (mPrt && aIsPrinting) {
- mPrt->mPreparingForPrint = true;
- }
- }
- //---------------------------------------------------------------------
- void nsPrintEngine::SetIsPrintPreview(bool aIsPrintPreview)
- {
- mIsDoingPrintPreview = aIsPrintPreview;
- if (mDocViewerPrint) {
- mDocViewerPrint->SetIsPrintPreview(aIsPrintPreview);
- }
- }
- //---------------------------------------------------------------------
- void
- nsPrintEngine::CleanupDocTitleArray(char16_t**& aArray, int32_t& aCount)
- {
- for (int32_t i = aCount - 1; i >= 0; i--) {
- free(aArray[i]);
- }
- free(aArray);
- aArray = nullptr;
- aCount = 0;
- }
- //---------------------------------------------------------------------
- // static
- bool nsPrintEngine::HasFramesetChild(nsIContent* aContent)
- {
- if (!aContent) {
- return false;
- }
- // do a breadth search across all siblings
- for (nsIContent* child = aContent->GetFirstChild();
- child;
- child = child->GetNextSibling()) {
- if (child->IsHTMLElement(nsGkAtoms::frameset)) {
- return true;
- }
- }
- return false;
- }
- /** ---------------------------------------------------
- * Get the Focused Frame for a documentviewer
- */
- already_AddRefed<nsPIDOMWindowOuter>
- nsPrintEngine::FindFocusedDOMWindow()
- {
- nsIFocusManager* fm = nsFocusManager::GetFocusManager();
- NS_ENSURE_TRUE(fm, nullptr);
- nsPIDOMWindowOuter* window = mDocument->GetWindow();
- NS_ENSURE_TRUE(window, nullptr);
- nsCOMPtr<nsPIDOMWindowOuter> rootWindow = window->GetPrivateRoot();
- NS_ENSURE_TRUE(rootWindow, nullptr);
- nsCOMPtr<nsPIDOMWindowOuter> focusedWindow;
- nsFocusManager::GetFocusedDescendant(rootWindow, true,
- getter_AddRefs(focusedWindow));
- NS_ENSURE_TRUE(focusedWindow, nullptr);
- if (IsWindowsInOurSubTree(focusedWindow)) {
- return focusedWindow.forget();
- }
- return nullptr;
- }
- //---------------------------------------------------------------------
- bool
- nsPrintEngine::IsWindowsInOurSubTree(nsPIDOMWindowOuter* window)
- {
- bool found = false;
- // now check to make sure it is in "our" tree of docshells
- if (window) {
- nsCOMPtr<nsIDocShell> docShell = window->GetDocShell();
- if (docShell) {
- // get this DocViewer docshell
- nsCOMPtr<nsIDocShell> thisDVDocShell(do_QueryReferent(mContainer));
- while (!found) {
- if (docShell) {
- if (docShell == thisDVDocShell) {
- found = true;
- break;
- }
- } else {
- break; // at top of tree
- }
- nsCOMPtr<nsIDocShellTreeItem> docShellItemParent;
- docShell->GetSameTypeParent(getter_AddRefs(docShellItemParent));
- docShell = do_QueryInterface(docShellItemParent);
- } // while
- }
- } // scriptobj
- return found;
- }
- //-------------------------------------------------------
- bool
- nsPrintEngine::DonePrintingPages(nsPrintObject* aPO, nsresult aResult)
- {
- //NS_ASSERTION(aPO, "Pointer is null!");
- PR_PL(("****** In DV::DonePrintingPages PO: %p (%s)\n", aPO, aPO?gFrameTypesStr[aPO->mFrameType]:""));
- // If there is a pageSeqFrame, make sure there are no more printCanvas active
- // that might call |Notify| on the pagePrintTimer after things are cleaned up
- // and printing was marked as being done.
- if (mPageSeqFrame.IsAlive()) {
- nsIPageSequenceFrame* pageSeqFrame = do_QueryFrame(mPageSeqFrame.GetFrame());
- pageSeqFrame->ResetPrintCanvasList();
- }
- // Guarantee that mPrt and mPrt->mPrintObject won't be deleted during a
- // call of PrintDocContent() and FirePrintCompletionEvent().
- RefPtr<nsPrintData> printData = mPrt;
- if (aPO && !printData->mIsAborted) {
- aPO->mHasBeenPrinted = true;
- nsresult rv;
- bool didPrint = PrintDocContent(printData->mPrintObject, rv);
- if (NS_SUCCEEDED(rv) && didPrint) {
- PR_PL(("****** In DV::DonePrintingPages PO: %p (%s) didPrint:%s (Not Done Printing)\n", aPO, gFrameTypesStr[aPO->mFrameType], PRT_YESNO(didPrint)));
- return false;
- }
- }
- if (NS_SUCCEEDED(aResult)) {
- FirePrintCompletionEvent();
- // XXX mPrt may be cleared or replaced with new instance here.
- // However, the following methods will clean up with new mPrt or will
- // do nothing due to no proper nsPrintData instance.
- }
- TurnScriptingOn(true);
- SetIsPrinting(false);
- // Release reference to mPagePrintTimer; the timer object destroys itself
- // after this returns true
- DisconnectPagePrintTimer();
- return true;
- }
- //-------------------------------------------------------
- // Recursively sets the PO items to be printed "As Is"
- // from the given item down into the tree
- void
- nsPrintEngine::SetPrintAsIs(nsPrintObject* aPO, bool aAsIs)
- {
- NS_ASSERTION(aPO, "Pointer is null!");
- aPO->mPrintAsIs = aAsIs;
- for (uint32_t i=0;i<aPO->mKids.Length();i++) {
- SetPrintAsIs(aPO->mKids[i], aAsIs);
- }
- }
- //-------------------------------------------------------
- // Given a DOMWindow it recursively finds the PO object that matches
- nsPrintObject*
- nsPrintEngine::FindPrintObjectByDOMWin(nsPrintObject* aPO,
- nsPIDOMWindowOuter* aDOMWin)
- {
- NS_ASSERTION(aPO, "Pointer is null!");
- // Often the CurFocused DOMWindow is passed in
- // andit is valid for it to be null, so short circut
- if (!aDOMWin) {
- return nullptr;
- }
- nsCOMPtr<nsIDocument> doc = aDOMWin->GetDoc();
- if (aPO->mDocument && aPO->mDocument->GetOriginalDocument() == doc) {
- return aPO;
- }
- int32_t cnt = aPO->mKids.Length();
- for (int32_t i = 0; i < cnt; ++i) {
- nsPrintObject* po = FindPrintObjectByDOMWin(aPO->mKids[i], aDOMWin);
- if (po) {
- return po;
- }
- }
- return nullptr;
- }
- //-------------------------------------------------------
- nsresult
- nsPrintEngine::EnablePOsForPrinting()
- {
- // Guarantee that mPrt and the objects it owns won't be deleted.
- RefPtr<nsPrintData> printData = mPrt;
- // NOTE: All POs have been "turned off" for printing
- // this is where we decided which POs get printed.
- printData->mSelectedPO = nullptr;
- if (printData->mPrintSettings == nullptr) {
- return NS_ERROR_FAILURE;
- }
- printData->mPrintFrameType = nsIPrintSettings::kNoFrames;
- printData->mPrintSettings->GetPrintFrameType(&printData->mPrintFrameType);
- int16_t printHowEnable = nsIPrintSettings::kFrameEnableNone;
- printData->mPrintSettings->GetHowToEnableFrameUI(&printHowEnable);
- int16_t printRangeType = nsIPrintSettings::kRangeAllPages;
- printData->mPrintSettings->GetPrintRange(&printRangeType);
- PR_PL(("\n"));
- PR_PL(("********* nsPrintEngine::EnablePOsForPrinting *********\n"));
- PR_PL(("PrintFrameType: %s \n",
- gPrintFrameTypeStr[printData->mPrintFrameType]));
- PR_PL(("HowToEnableFrameUI: %s \n", gFrameHowToEnableStr[printHowEnable]));
- PR_PL(("PrintRange: %s \n", gPrintRangeStr[printRangeType]));
- PR_PL(("----\n"));
- // ***** This is the ultimate override *****
- // if we are printing the selection (either an IFrame or selection range)
- // then set the mPrintFrameType as if it were the selected frame
- if (printRangeType == nsIPrintSettings::kRangeSelection) {
- printData->mPrintFrameType = nsIPrintSettings::kSelectedFrame;
- printHowEnable = nsIPrintSettings::kFrameEnableNone;
- }
- // This tells us that the "Frame" UI has turned off,
- // so therefore there are no FrameSets/Frames/IFrames to be printed
- //
- // This means there are not FrameSets,
- // but the document could contain an IFrame
- if (printHowEnable == nsIPrintSettings::kFrameEnableNone) {
- // Print all the pages or a sub range of pages
- if (printRangeType == nsIPrintSettings::kRangeAllPages ||
- printRangeType == nsIPrintSettings::kRangeSpecifiedPageRange) {
- SetPrintPO(printData->mPrintObject, true);
- // Set the children so they are PrinAsIs
- // In this case, the children are probably IFrames
- if (printData->mPrintObject->mKids.Length() > 0) {
- for (uint32_t i = 0; i < printData->mPrintObject->mKids.Length(); i++) {
- nsPrintObject* po = printData->mPrintObject->mKids[i];
- NS_ASSERTION(po, "nsPrintObject can't be null!");
- SetPrintAsIs(po);
- }
- // ***** Another override *****
- printData->mPrintFrameType = nsIPrintSettings::kFramesAsIs;
- }
- PR_PL(("PrintFrameType: %s \n",
- gPrintFrameTypeStr[printData->mPrintFrameType]));
- PR_PL(("HowToEnableFrameUI: %s \n",
- gFrameHowToEnableStr[printHowEnable]));
- PR_PL(("PrintRange: %s \n", gPrintRangeStr[printRangeType]));
- return NS_OK;
- }
- // This means we are either printed a selected IFrame or
- // we are printing the current selection
- if (printRangeType == nsIPrintSettings::kRangeSelection) {
- // If the currentFocusDOMWin can'r be null if something is selected
- if (printData->mCurrentFocusWin) {
- // Find the selected IFrame
- nsPrintObject* po =
- FindPrintObjectByDOMWin(printData->mPrintObject,
- printData->mCurrentFocusWin);
- if (po) {
- printData->mSelectedPO = po;
- // Makes sure all of its children are be printed "AsIs"
- SetPrintAsIs(po);
- // Now, only enable this POs (the selected PO) and all of its children
- SetPrintPO(po, true);
- // check to see if we have a range selection,
- // as oppose to a insert selection
- // this means if the user just clicked on the IFrame then
- // there will not be a selection so we want the entire page to print
- //
- // XXX this is sort of a hack right here to make the page
- // not try to reposition itself when printing selection
- nsPIDOMWindowOuter* domWin =
- po->mDocument->GetOriginalDocument()->GetWindow();
- if (!IsThereARangeSelection(domWin)) {
- printRangeType = nsIPrintSettings::kRangeAllPages;
- printData->mPrintSettings->SetPrintRange(printRangeType);
- }
- PR_PL(("PrintFrameType: %s \n",
- gPrintFrameTypeStr[printData->mPrintFrameType]));
- PR_PL(("HowToEnableFrameUI: %s \n",
- gFrameHowToEnableStr[printHowEnable]));
- PR_PL(("PrintRange: %s \n", gPrintRangeStr[printRangeType]));
- return NS_OK;
- }
- } else {
- for (uint32_t i = 0; i < printData->mPrintDocList.Length(); i++) {
- nsPrintObject* po = printData->mPrintDocList.ElementAt(i);
- NS_ASSERTION(po, "nsPrintObject can't be null!");
- nsCOMPtr<nsPIDOMWindowOuter> domWin = po->mDocShell->GetWindow();
- if (IsThereARangeSelection(domWin)) {
- printData->mCurrentFocusWin = domWin.forget();
- SetPrintPO(po, true);
- break;
- }
- }
- return NS_OK;
- }
- }
- }
- // check to see if there is a selection when a FrameSet is present
- if (printRangeType == nsIPrintSettings::kRangeSelection) {
- // If the currentFocusDOMWin can'r be null if something is selected
- if (printData->mCurrentFocusWin) {
- // Find the selected IFrame
- nsPrintObject* po =
- FindPrintObjectByDOMWin(printData->mPrintObject,
- printData->mCurrentFocusWin);
- if (po) {
- printData->mSelectedPO = po;
- // Makes sure all of its children are be printed "AsIs"
- SetPrintAsIs(po);
- // Now, only enable this POs (the selected PO) and all of its children
- SetPrintPO(po, true);
- // check to see if we have a range selection,
- // as oppose to a insert selection
- // this means if the user just clicked on the IFrame then
- // there will not be a selection so we want the entire page to print
- //
- // XXX this is sort of a hack right here to make the page
- // not try to reposition itself when printing selection
- nsCOMPtr<nsPIDOMWindowOuter> domWin = po->mDocument->GetOriginalDocument()->GetWindow();
- if (!IsThereARangeSelection(domWin)) {
- printRangeType = nsIPrintSettings::kRangeAllPages;
- printData->mPrintSettings->SetPrintRange(printRangeType);
- }
- PR_PL(("PrintFrameType: %s \n",
- gPrintFrameTypeStr[printData->mPrintFrameType]));
- PR_PL(("HowToEnableFrameUI: %s \n",
- gFrameHowToEnableStr[printHowEnable]));
- PR_PL(("PrintRange: %s \n", gPrintRangeStr[printRangeType]));
- return NS_OK;
- }
- }
- }
- // If we are printing "AsIs" then sets all the POs to be printed as is
- if (printData->mPrintFrameType == nsIPrintSettings::kFramesAsIs) {
- SetPrintAsIs(printData->mPrintObject);
- SetPrintPO(printData->mPrintObject, true);
- return NS_OK;
- }
- // If we are printing the selected Frame then
- // find that PO for that selected DOMWin and set it all of its
- // children to be printed
- if (printData->mPrintFrameType == nsIPrintSettings::kSelectedFrame) {
- if ((printData->mIsParentAFrameSet && printData->mCurrentFocusWin) ||
- printData->mIsIFrameSelected) {
- nsPrintObject* po =
- FindPrintObjectByDOMWin(printData->mPrintObject,
- printData->mCurrentFocusWin);
- if (po) {
- printData->mSelectedPO = po;
- // NOTE: Calling this sets the "po" and
- // we don't want to do this for documents that have no children,
- // because then the "DoEndPage" gets called and it shouldn't
- if (po->mKids.Length() > 0) {
- // Makes sure that itself, and all of its children are printed "AsIs"
- SetPrintAsIs(po);
- }
- // Now, only enable this POs (the selected PO) and all of its children
- SetPrintPO(po, true);
- }
- }
- return NS_OK;
- }
- // If we are print each subdoc separately,
- // then don't print any of the FraneSet Docs
- if (printData->mPrintFrameType == nsIPrintSettings::kEachFrameSep) {
- SetPrintPO(printData->mPrintObject, true);
- int32_t cnt = printData->mPrintDocList.Length();
- for (int32_t i=0;i<cnt;i++) {
- nsPrintObject* po = printData->mPrintDocList.ElementAt(i);
- NS_ASSERTION(po, "nsPrintObject can't be null!");
- if (po->mFrameType == eFrameSet) {
- po->mDontPrint = true;
- }
- }
- }
- return NS_OK;
- }
- //-------------------------------------------------------
- // Return the nsPrintObject with that is XMost (The widest frameset frame) AND
- // contains the XMost (widest) layout frame
- nsPrintObject*
- nsPrintEngine::FindSmallestSTF()
- {
- float smallestRatio = 1.0f;
- nsPrintObject* smallestPO = nullptr;
- for (uint32_t i=0;i<mPrt->mPrintDocList.Length();i++) {
- nsPrintObject* po = mPrt->mPrintDocList.ElementAt(i);
- NS_ASSERTION(po, "nsPrintObject can't be null!");
- if (po->mFrameType != eFrameSet && po->mFrameType != eIFrame) {
- if (po->mShrinkRatio < smallestRatio) {
- smallestRatio = po->mShrinkRatio;
- smallestPO = po;
- }
- }
- }
- #ifdef EXTENDED_DEBUG_PRINTING
- if (smallestPO) printf("*PO: %p Type: %d %10.3f\n", smallestPO, smallestPO->mFrameType, smallestPO->mShrinkRatio);
- #endif
- return smallestPO;
- }
- //-------------------------------------------------------
- void
- nsPrintEngine::TurnScriptingOn(bool aDoTurnOn)
- {
- if (mIsDoingPrinting && aDoTurnOn && mDocViewerPrint &&
- mDocViewerPrint->GetIsPrintPreview()) {
- // We don't want to turn scripting on if print preview is shown still after
- // printing.
- return;
- }
- // The following for loop uses nsPrintObject instances that are owned by
- // mPrt or mPrtPreview. Therefore, this method needs to guarantee that
- // they won't be deleted in this method.
- RefPtr<nsPrintData> printData = mPrt ? mPrt : mPrtPreview;
- if (!printData) {
- return;
- }
- NS_ASSERTION(mDocument, "We MUST have a document.");
- // First, get the script global object from the document...
- for (uint32_t i = 0; i < printData->mPrintDocList.Length(); i++) {
- nsPrintObject* po = printData->mPrintDocList.ElementAt(i);
- MOZ_ASSERT(po);
- nsIDocument* doc = po->mDocument;
- if (!doc) {
- continue;
- }
- if (nsCOMPtr<nsPIDOMWindowInner> window = doc->GetInnerWindow()) {
- nsCOMPtr<nsIGlobalObject> go = do_QueryInterface(window);
- NS_WARNING_ASSERTION(go && go->GetGlobalJSObject(), "Can't get global");
- nsresult propThere = NS_PROPTABLE_PROP_NOT_THERE;
- doc->GetProperty(nsGkAtoms::scriptEnabledBeforePrintOrPreview,
- &propThere);
- if (aDoTurnOn) {
- if (propThere != NS_PROPTABLE_PROP_NOT_THERE) {
- doc->DeleteProperty(nsGkAtoms::scriptEnabledBeforePrintOrPreview);
- if (go && go->GetGlobalJSObject()) {
- xpc::Scriptability::Get(go->GetGlobalJSObject()).Unblock();
- }
- window->Resume();
- }
- } else {
- // Have to be careful, because people call us over and over again with
- // aDoTurnOn == false. So don't set the property if it's already
- // set, since in that case we'd set it to the wrong value.
- if (propThere == NS_PROPTABLE_PROP_NOT_THERE) {
- // Stash the current value of IsScriptEnabled on the document, so
- // that layout code running in print preview doesn't get confused.
- doc->SetProperty(nsGkAtoms::scriptEnabledBeforePrintOrPreview,
- NS_INT32_TO_PTR(doc->IsScriptEnabled()));
- if (go && go->GetGlobalJSObject()) {
- xpc::Scriptability::Get(go->GetGlobalJSObject()).Block();
- }
- window->Suspend();
- }
- }
- }
- }
- }
- //-----------------------------------------------------------------
- //-- Done: Misc Support Methods
- //-----------------------------------------------------------------
- //-----------------------------------------------------------------
- //-- Section: Finishing up or Cleaning up
- //-----------------------------------------------------------------
- //-----------------------------------------------------------------
- void
- nsPrintEngine::CloseProgressDialog(nsIWebProgressListener* aWebProgressListener)
- {
- if (aWebProgressListener) {
- aWebProgressListener->OnStateChange(nullptr, nullptr, nsIWebProgressListener::STATE_STOP|nsIWebProgressListener::STATE_IS_DOCUMENT, NS_OK);
- }
- }
- //-----------------------------------------------------------------
- nsresult
- nsPrintEngine::FinishPrintPreview()
- {
- nsresult rv = NS_OK;
- #ifdef NS_PRINT_PREVIEW
- if (!mPrt) {
- /* we're already finished with print preview */
- return rv;
- }
- rv = DocumentReadyForPrinting();
- SetIsCreatingPrintPreview(false);
- // mPrt may be cleared during a call of nsPrintData::OnEndPrinting()
- // because that method invokes some arbitrary listeners.
- RefPtr<nsPrintData> printData = mPrt;
- if (NS_FAILED(rv)) {
- /* cleanup done, let's fire-up an error dialog to notify the user
- * what went wrong...
- */
- printData->OnEndPrinting();
- // XXX mPrt may be nullptr here. So, Shouldn't TurnScriptingOn() take
- // nsPrintData as an argument?
- TurnScriptingOn(true);
- return rv;
- }
- // At this point we are done preparing everything
- // before it is to be created
- if (mIsDoingPrintPreview && mOldPrtPreview) {
- mOldPrtPreview = nullptr;
- }
- printData->OnEndPrinting();
- // XXX If mPrt becomes nullptr or different instance here, what should we
- // do?
- // PrintPreview was built using the mPrt (code reuse)
- // then we assign it over
- mPrtPreview = Move(mPrt);
- #endif // NS_PRINT_PREVIEW
- return NS_OK;
- }
- //-----------------------------------------------------------------
- //-- Done: Finishing up or Cleaning up
- //-----------------------------------------------------------------
- /*=============== Timer Related Code ======================*/
- nsresult
- nsPrintEngine::StartPagePrintTimer(nsPrintObject* aPO)
- {
- if (!mPagePrintTimer) {
- // Get the delay time in between the printing of each page
- // this gives the user more time to press cancel
- int32_t printPageDelay = 50;
- mPrt->mPrintSettings->GetPrintPageDelay(&printPageDelay);
- RefPtr<nsPagePrintTimer> timer =
- new nsPagePrintTimer(this, mDocViewerPrint, printPageDelay);
- timer.forget(&mPagePrintTimer);
- nsCOMPtr<nsIPrintSession> printSession;
- nsresult rv = mPrt->mPrintSettings->GetPrintSession(getter_AddRefs(printSession));
- if (NS_SUCCEEDED(rv) && printSession) {
- RefPtr<mozilla::layout::RemotePrintJobChild> remotePrintJob;
- printSession->GetRemotePrintJob(getter_AddRefs(remotePrintJob));
- if (NS_SUCCEEDED(rv) && remotePrintJob) {
- remotePrintJob->SetPagePrintTimer(mPagePrintTimer);
- remotePrintJob->SetPrintEngine(this);
- }
- }
- }
- return mPagePrintTimer->Start(aPO);
- }
- /*=============== nsIObserver Interface ======================*/
- NS_IMETHODIMP
- nsPrintEngine::Observe(nsISupports *aSubject, const char *aTopic, const char16_t *aData)
- {
- nsresult rv = NS_ERROR_FAILURE;
- rv = InitPrintDocConstruction(true);
- if (!mIsDoingPrinting && mPrtPreview) {
- RefPtr<nsPrintData> printDataOfPrintPreview = mPrtPreview;
- printDataOfPrintPreview->OnEndPrinting();
- }
- return rv;
- }
- //---------------------------------------------------------------
- //-- PLEvent Notification
- //---------------------------------------------------------------
- class nsPrintCompletionEvent : public Runnable {
- public:
- explicit nsPrintCompletionEvent(nsIDocumentViewerPrint *docViewerPrint)
- : mDocViewerPrint(docViewerPrint) {
- NS_ASSERTION(mDocViewerPrint, "mDocViewerPrint is null.");
- }
- NS_IMETHOD Run() override {
- if (mDocViewerPrint)
- mDocViewerPrint->OnDonePrinting();
- return NS_OK;
- }
- private:
- nsCOMPtr<nsIDocumentViewerPrint> mDocViewerPrint;
- };
- //-----------------------------------------------------------
- void
- nsPrintEngine::FirePrintCompletionEvent()
- {
- nsCOMPtr<nsIRunnable> event = new nsPrintCompletionEvent(mDocViewerPrint);
- if (NS_FAILED(NS_DispatchToCurrentThread(event)))
- NS_WARNING("failed to dispatch print completion event");
- }
- void
- nsPrintEngine::DisconnectPagePrintTimer()
- {
- if (mPagePrintTimer) {
- mPagePrintTimer->Disconnect();
- NS_RELEASE(mPagePrintTimer);
- }
- }
- //---------------------------------------------------------------
- //---------------------------------------------------------------
- //-- Debug helper routines
- //---------------------------------------------------------------
- //---------------------------------------------------------------
- #if defined(XP_WIN) && defined(EXTENDED_DEBUG_PRINTING)
- #include "windows.h"
- #include "process.h"
- #include "direct.h"
- #define MY_FINDFIRST(a,b) FindFirstFile(a,b)
- #define MY_FINDNEXT(a,b) FindNextFile(a,b)
- #define ISDIR(a) (a.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
- #define MY_FINDCLOSE(a) FindClose(a)
- #define MY_FILENAME(a) a.cFileName
- #define MY_FILESIZE(a) (a.nFileSizeHigh * MAXDWORD) + a.nFileSizeLow
- int RemoveFilesInDir(const char * aDir)
- {
- WIN32_FIND_DATA data_ptr;
- HANDLE find_handle;
- char path[MAX_PATH];
- strcpy(path, aDir);
- // Append slash to the end of the directory names if not there
- if (path[strlen(path)-1] != '\\')
- strcat(path, "\\");
- char findPath[MAX_PATH];
- strcpy(findPath, path);
- strcat(findPath, "*.*");
- find_handle = MY_FINDFIRST(findPath, &data_ptr);
- if (find_handle != INVALID_HANDLE_VALUE) {
- do {
- if (ISDIR(data_ptr)
- && (stricmp(MY_FILENAME(data_ptr),"."))
- && (stricmp(MY_FILENAME(data_ptr),".."))) {
- // skip
- }
- else if (!ISDIR(data_ptr)) {
- if (!strncmp(MY_FILENAME(data_ptr), "print_dump", 10)) {
- char fileName[MAX_PATH];
- strcpy(fileName, aDir);
- strcat(fileName, "\\");
- strcat(fileName, MY_FILENAME(data_ptr));
- printf("Removing %s\n", fileName);
- remove(fileName);
- }
- }
- } while(MY_FINDNEXT(find_handle,&data_ptr));
- MY_FINDCLOSE(find_handle);
- }
- return TRUE;
- }
- #endif
- #ifdef EXTENDED_DEBUG_PRINTING
- /** ---------------------------------------------------
- * Dumps Frames for Printing
- */
- static void RootFrameList(nsPresContext* aPresContext, FILE* out, int32_t aIndent)
- {
- if (!aPresContext || !out)
- return;
- nsIPresShell *shell = aPresContext->GetPresShell();
- if (shell) {
- nsIFrame* frame = shell->FrameManager()->GetRootFrame();
- if (frame) {
- frame->List(aPresContext, out, aIndent);
- }
- }
- }
- /** ---------------------------------------------------
- * Dumps Frames for Printing
- */
- static void DumpFrames(FILE* out,
- nsPresContext* aPresContext,
- nsRenderingContext * aRendContext,
- nsIFrame * aFrame,
- int32_t aLevel)
- {
- NS_ASSERTION(out, "Pointer is null!");
- NS_ASSERTION(aPresContext, "Pointer is null!");
- NS_ASSERTION(aRendContext, "Pointer is null!");
- NS_ASSERTION(aFrame, "Pointer is null!");
- nsIFrame* child = aFrame->PrincipalChildList().FirstChild();
- while (child != nullptr) {
- for (int32_t i=0;i<aLevel;i++) {
- fprintf(out, " ");
- }
- nsAutoString tmp;
- child->GetFrameName(tmp);
- fputs(NS_LossyConvertUTF16toASCII(tmp).get(), out);
- bool isSelected;
- if (NS_SUCCEEDED(child->IsVisibleForPainting(aPresContext, *aRendContext, true, &isSelected))) {
- fprintf(out, " %p %s", child, isSelected?"VIS":"UVS");
- nsRect rect = child->GetRect();
- fprintf(out, "[%d,%d,%d,%d] ", rect.x, rect.y, rect.width, rect.height);
- fprintf(out, "v: %p ", (void*)child->GetView());
- fprintf(out, "\n");
- DumpFrames(out, aPresContext, aRendContext, child, aLevel+1);
- child = child->GetNextSibling();
- }
- }
- }
- /** ---------------------------------------------------
- * Dumps the Views from the DocShell
- */
- static void
- DumpViews(nsIDocShell* aDocShell, FILE* out)
- {
- NS_ASSERTION(aDocShell, "Pointer is null!");
- NS_ASSERTION(out, "Pointer is null!");
- if (nullptr != aDocShell) {
- fprintf(out, "docshell=%p \n", aDocShell);
- nsIPresShell* shell = nsPrintEngine::GetPresShellFor(aDocShell);
- if (shell) {
- nsViewManager* vm = shell->GetViewManager();
- if (vm) {
- nsView* root = vm->GetRootView();
- if (root) {
- root->List(out);
- }
- }
- }
- else {
- fputs("null pres shell\n", out);
- }
- // dump the views of the sub documents
- int32_t i, n;
- aDocShell->GetChildCount(&n);
- for (i = 0; i < n; i++) {
- nsCOMPtr<nsIDocShellTreeItem> child;
- aDocShell->GetChildAt(i, getter_AddRefs(child));
- nsCOMPtr<nsIDocShell> childAsShell(do_QueryInterface(child));
- if (childAsShell) {
- DumpViews(childAsShell, out);
- }
- }
- }
- }
- /** ---------------------------------------------------
- * Dumps the Views and Frames
- */
- void DumpLayoutData(char* aTitleStr,
- char* aURLStr,
- nsPresContext* aPresContext,
- nsDeviceContext * aDC,
- nsIFrame * aRootFrame,
- nsIDocShekk * aDocShell,
- FILE* aFD = nullptr)
- {
- if (!kPrintingLogMod || kPrintingLogMod->level != DUMP_LAYOUT_LEVEL) return;
- if (aPresContext == nullptr || aDC == nullptr) {
- return;
- }
- #ifdef NS_PRINT_PREVIEW
- if (aPresContext->Type() == nsPresContext::eContext_PrintPreview) {
- return;
- }
- #endif
- NS_ASSERTION(aRootFrame, "Pointer is null!");
- NS_ASSERTION(aDocShell, "Pointer is null!");
- // Dump all the frames and view to a a file
- char filename[256];
- sprintf(filename, "print_dump_layout_%d.txt", gDumpLOFileNameCnt++);
- FILE * fd = aFD?aFD:fopen(filename, "w");
- if (fd) {
- fprintf(fd, "Title: %s\n", aTitleStr?aTitleStr:"");
- fprintf(fd, "URL: %s\n", aURLStr?aURLStr:"");
- fprintf(fd, "--------------- Frames ----------------\n");
- fprintf(fd, "--------------- Frames ----------------\n");
- //RefPtr<gfxContext> renderingContext =
- // aDC->CreateRenderingContext();
- RootFrameList(aPresContext, fd, 0);
- //DumpFrames(fd, aPresContext, renderingContext, aRootFrame, 0);
- fprintf(fd, "---------------------------------------\n\n");
- fprintf(fd, "--------------- Views From Root Frame----------------\n");
- nsView* v = aRootFrame->GetView();
- if (v) {
- v->List(fd);
- } else {
- printf("View is null!\n");
- }
- if (aDocShell) {
- fprintf(fd, "--------------- All Views ----------------\n");
- DumpViews(aDocShell, fd);
- fprintf(fd, "---------------------------------------\n\n");
- }
- if (aFD == nullptr) {
- fclose(fd);
- }
- }
- }
- //-------------------------------------------------------------
- static void DumpPrintObjectsList(nsTArray<nsPrintObject*> * aDocList)
- {
- if (!kPrintingLogMod || kPrintingLogMod->level != DUMP_LAYOUT_LEVEL) return;
- NS_ASSERTION(aDocList, "Pointer is null!");
- const char types[][3] = {"DC", "FR", "IF", "FS"};
- PR_PL(("Doc List\n***************************************************\n"));
- PR_PL(("T P A H PO DocShell Seq Page Root Page# Rect\n"));
- int32_t cnt = aDocList->Length();
- for (int32_t i=0;i<cnt;i++) {
- nsPrintObject* po = aDocList->ElementAt(i);
- NS_ASSERTION(po, "nsPrintObject can't be null!");
- nsIFrame* rootFrame = nullptr;
- if (po->mPresShell) {
- rootFrame = po->mPresShell->FrameManager()->GetRootFrame();
- while (rootFrame != nullptr) {
- nsIPageSequenceFrame * sqf = do_QueryFrame(rootFrame);
- if (sqf) {
- break;
- }
- rootFrame = rootFrame->PrincipalChildList().FirstChild();
- }
- }
- PR_PL(("%s %d %d %d %p %p %p %p %p %d %d,%d,%d,%d\n", types[po->mFrameType],
- po->IsPrintable(), po->mPrintAsIs, po->mHasBeenPrinted, po, po->mDocShell.get(), po->mSeqFrame,
- po->mPageFrame, rootFrame, po->mPageNum, po->mRect.x, po->mRect.y, po->mRect.width, po->mRect.height));
- }
- }
- //-------------------------------------------------------------
- static void DumpPrintObjectsTree(nsPrintObject * aPO, int aLevel, FILE* aFD)
- {
- if (!kPrintingLogMod || kPrintingLogMod->level != DUMP_LAYOUT_LEVEL) return;
- NS_ASSERTION(aPO, "Pointer is null!");
- FILE * fd = aFD?aFD:stdout;
- const char types[][3] = {"DC", "FR", "IF", "FS"};
- if (aLevel == 0) {
- fprintf(fd, "DocTree\n***************************************************\n");
- fprintf(fd, "T PO DocShell Seq Page Page# Rect\n");
- }
- int32_t cnt = aPO->mKids.Length();
- for (int32_t i=0;i<cnt;i++) {
- nsPrintObject* po = aPO->mKids.ElementAt(i);
- NS_ASSERTION(po, "nsPrintObject can't be null!");
- for (int32_t k=0;k<aLevel;k++) fprintf(fd, " ");
- fprintf(fd, "%s %p %p %p %p %d %d,%d,%d,%d\n", types[po->mFrameType], po, po->mDocShell.get(), po->mSeqFrame,
- po->mPageFrame, po->mPageNum, po->mRect.x, po->mRect.y, po->mRect.width, po->mRect.height);
- }
- }
- //-------------------------------------------------------------
- static void GetDocTitleAndURL(nsPrintObject* aPO, nsACString& aDocStr, nsACString& aURLStr)
- {
- nsAutoString docTitleStr;
- nsAutoString docURLStr;
- nsPrintEngine::GetDisplayTitleAndURL(aPO,
- docTitleStr, docURLStr,
- nsPrintEngine::eDocTitleDefURLDoc);
- aDocStr = NS_ConvertUTF16toUTF8(docTitleStr);
- aURLStr = NS_ConvertUTF16toUTF8(docURLStr);
- }
- //-------------------------------------------------------------
- static void DumpPrintObjectsTreeLayout(nsPrintObject * aPO,
- nsDeviceContext * aDC,
- int aLevel, FILE * aFD)
- {
- if (!kPrintingLogMod || kPrintingLogMod->level != DUMP_LAYOUT_LEVEL) return;
- NS_ASSERTION(aPO, "Pointer is null!");
- NS_ASSERTION(aDC, "Pointer is null!");
- const char types[][3] = {"DC", "FR", "IF", "FS"};
- FILE * fd = nullptr;
- if (aLevel == 0) {
- fd = fopen("tree_layout.txt", "w");
- fprintf(fd, "DocTree\n***************************************************\n");
- fprintf(fd, "***************************************************\n");
- fprintf(fd, "T PO DocShell Seq Page Page# Rect\n");
- } else {
- fd = aFD;
- }
- if (fd) {
- nsIFrame* rootFrame = nullptr;
- if (aPO->mPresShell) {
- rootFrame = aPO->mPresShell->FrameManager()->GetRootFrame();
- }
- for (int32_t k=0;k<aLevel;k++) fprintf(fd, " ");
- fprintf(fd, "%s %p %p %p %p %d %d,%d,%d,%d\n", types[aPO->mFrameType], aPO, aPO->mDocShell.get(), aPO->mSeqFrame,
- aPO->mPageFrame, aPO->mPageNum, aPO->mRect.x, aPO->mRect.y, aPO->mRect.width, aPO->mRect.height);
- if (aPO->IsPrintable()) {
- nsAutoCString docStr;
- nsAutoCString urlStr;
- GetDocTitleAndURL(aPO, docStr, urlStr);
- DumpLayoutData(docStr.get(), urlStr.get(), aPO->mPresContext, aDC, rootFrame, aPO->mDocShell, fd);
- }
- fprintf(fd, "<***************************************************>\n");
- int32_t cnt = aPO->mKids.Length();
- for (int32_t i=0;i<cnt;i++) {
- nsPrintObject* po = aPO->mKids.ElementAt(i);
- NS_ASSERTION(po, "nsPrintObject can't be null!");
- DumpPrintObjectsTreeLayout(po, aDC, aLevel+1, fd);
- }
- }
- if (aLevel == 0 && fd) {
- fclose(fd);
- }
- }
- //-------------------------------------------------------------
- static void DumpPrintObjectsListStart(const char * aStr, nsTArray<nsPrintObject*> * aDocList)
- {
- if (!kPrintingLogMod || kPrintingLogMod->level != DUMP_LAYOUT_LEVEL) return;
- NS_ASSERTION(aStr, "Pointer is null!");
- NS_ASSERTION(aDocList, "Pointer is null!");
- PR_PL(("%s\n", aStr));
- DumpPrintObjectsList(aDocList);
- }
- #define DUMP_DOC_LIST(_title) DumpPrintObjectsListStart((_title), mPrt->mPrintDocList);
- #define DUMP_DOC_TREE DumpPrintObjectsTree(mPrt->mPrintObject);
- #define DUMP_DOC_TREELAYOUT DumpPrintObjectsTreeLayout(mPrt->mPrintObject, mPrt->mPrintDC);
- #else
- #define DUMP_DOC_LIST(_title)
- #define DUMP_DOC_TREE
- #define DUMP_DOC_TREELAYOUT
- #endif
- //---------------------------------------------------------------
- //---------------------------------------------------------------
- //-- End of debug helper routines
- //---------------------------------------------------------------
|