Back to index

lightning-sunbird  0.9+nobinonly
nsMsgPrintEngine.cpp
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is mozilla.org Code.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 2001
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *
00023  * Alternatively, the contents of this file may be used under the terms of
00024  * either of the GNU General Public License Version 2 or later (the "GPL"),
00025  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00026  * in which case the provisions of the GPL or the LGPL are applicable instead
00027  * of those above. If you wish to allow use of your version of this file only
00028  * under the terms of either the GPL or the LGPL, and not to allow others to
00029  * use your version of this file under the terms of the MPL, indicate your
00030  * decision by deleting the provisions above and replace them with the notice
00031  * and other provisions required by the GPL or the LGPL. If you do not delete
00032  * the provisions above, a recipient may use your version of this file under
00033  * the terms of any one of the MPL, the GPL or the LGPL.
00034  *
00035  * ***** END LICENSE BLOCK ***** */
00036 
00037 // nsMsgPrintEngine.cpp: provides a DocShell container for use
00038 // in printing
00039 
00040 #include "nscore.h"
00041 #include "nsCOMPtr.h"
00042 
00043 #include "nsIComponentManager.h"
00044 
00045 #include "nsISupports.h"
00046 
00047 #include "nsIURI.h"
00048 #include "nsEscape.h"
00049 #include "nsXPIDLString.h"
00050 #include "nsReadableUtils.h"
00051 #include "nsIDocShell.h"
00052 #include "nsIDOMDocument.h"
00053 #include "nsIDOMWindowInternal.h"
00054 #include "nsIDocumentViewer.h"
00055 #include "nsPresContext.h"
00056 #include "nsIPresShell.h"
00057 #include "nsIDocument.h"
00058 #include "nsIMsgMessageService.h"
00059 #include "nsMsgUtils.h"
00060 #include "nsIWebProgress.h"
00061 #include "nsIInterfaceRequestor.h"
00062 #include "nsIInterfaceRequestorUtils.h"
00063 #include "nsIMarkupDocumentViewer.h"
00064 #include "nsIMsgMailSession.h"
00065 #include "nsMsgPrintEngine.h"
00066 #include "nsMsgBaseCID.h"
00067 #include "nsIDocumentLoader.h"
00068 #include "nsIWidget.h"
00069 #include "nsIXULWindow.h"
00070 #include "nsIPrefService.h"
00071 #include "nsIPrefBranch.h"
00072 
00073 // For PLEvents
00074 #include "plevent.h"
00075 #include "nsIEventQueue.h"
00076 #include "nsIEventQueueService.h"
00077 #include "nsIServiceManager.h"
00078 
00079 // Interfaces Needed
00080 #include "nsIBaseWindow.h"
00081 #include "nsIDocShellTreeOwner.h"
00082 #include "nsIDocShellTreeItem.h"
00083 #include "nsIDocShellTreeNode.h"
00084 #include "nsIWebNavigation.h"
00085 #include "nsIChannel.h"
00086 #include "nsIContentViewerFile.h"
00087 #include "nsIPrintingPromptService.h"
00088 
00089 static const char* kPrintingPromptService = "@mozilla.org/embedcomp/printingprompt-service;1";
00090 
00092 // nsMsgPrintEngine implementation
00094 
00095 nsMsgPrintEngine::nsMsgPrintEngine() :
00096   mIsDoingPrintPreview(PR_FALSE),
00097   mMsgInx(nsIMsgPrintEngine::MNAB_START)
00098 {
00099   mCurrentlyPrintingURI = -1;
00100 }
00101 
00102 
00103 nsMsgPrintEngine::~nsMsgPrintEngine()
00104 {
00105 }
00106 
00107 // Implement AddRef and Release
00108 NS_IMPL_ISUPPORTS4(nsMsgPrintEngine,
00109                          nsIMsgPrintEngine,
00110                          nsIWebProgressListener,
00111                          nsIObserver,
00112                          nsISupportsWeakReference)
00113 
00114 // nsIWebProgressListener implementation
00115 NS_IMETHODIMP
00116 nsMsgPrintEngine::OnStateChange(nsIWebProgress* aWebProgress,
00117                    nsIRequest *aRequest,
00118                    PRUint32 progressStateFlags,
00119                    nsresult aStatus)
00120 {
00121   nsresult rv = NS_OK;
00122 
00123   // top-level document load data
00124   if (progressStateFlags & nsIWebProgressListener::STATE_IS_DOCUMENT) {
00125     if (progressStateFlags & nsIWebProgressListener::STATE_START) {
00126       // Tell the user we are loading...
00127       PRUnichar *msg = GetString(NS_LITERAL_STRING("LoadingMessageToPrint").get());
00128       SetStatusMessage( msg );
00129       CRTFREEIF(msg)
00130     }
00131 
00132     if (progressStateFlags & nsIWebProgressListener::STATE_STOP) {
00133       nsCOMPtr<nsIDocumentLoader> docLoader(do_QueryInterface(aWebProgress));
00134       if (docLoader)
00135       {
00136         // Check to see if the document DOMWin that is finished loading is the same
00137         // one as the mail msg that we started to load.
00138         // We only want to print when the entire msg and all of its attachments
00139         // have finished loading.
00140         // The mail msg doc is the last one to receive the STATE_STOP notification
00141         nsCOMPtr<nsISupports> container;
00142         docLoader->GetContainer(getter_AddRefs(container));
00143         nsCOMPtr<nsIDOMWindow> domWindow(do_GetInterface(container));
00144         if (domWindow.get() != mMsgDOMWin.get()) {
00145           return NS_OK;
00146         }
00147       }
00148       nsCOMPtr<nsIWebProgressListener> wpl(do_QueryInterface(mPrintPromptService));
00149       if (wpl) {
00150         wpl->OnStateChange(nsnull, nsnull, nsIWebProgressListener::STATE_STOP|nsIWebProgressListener::STATE_IS_DOCUMENT, nsnull);
00151         mPrintProgressListener = nsnull;
00152         mPrintProgress         = nsnull;
00153         mPrintProgressParams   = nsnull;
00154       }
00155 
00156       PRBool isPrintingCancelled = PR_FALSE;
00157       if (mPrintSettings)
00158       {
00159         mPrintSettings->GetIsCancelled(&isPrintingCancelled);
00160       }
00161       if (!isPrintingCancelled) {
00162         // if aWebProgress is a documentloader than the notification from
00163         // loading the documents. If it is NULL (or not a DocLoader) then it
00164         // it coming from Printing
00165         if (docLoader) {
00166           // Now, fire off the print operation!
00167           rv = NS_ERROR_FAILURE;
00168 
00169           // Tell the user the message is loaded...
00170           PRUnichar *msg = GetString(NS_LITERAL_STRING("MessageLoaded").get());
00171           SetStatusMessage( msg );
00172           if (msg) nsCRT::free(msg);
00173 
00174           NS_ASSERTION(mDocShell,"can't print, there is no docshell");
00175           if ( (!mDocShell) || (!aRequest) )
00176           {
00177             return StartNextPrintOperation();
00178           }
00179           nsCOMPtr<nsIChannel> aChannel = do_QueryInterface(aRequest);
00180           if (!aChannel) return NS_ERROR_FAILURE;
00181 
00182           // Make sure this isn't just "about:blank" finishing....
00183           nsCOMPtr<nsIURI> originalURI = nsnull;
00184           if (NS_SUCCEEDED(aChannel->GetOriginalURI(getter_AddRefs(originalURI))) && originalURI)
00185           {
00186             nsCAutoString spec;
00187 
00188             if (NS_SUCCEEDED(originalURI->GetSpec(spec)))
00189             {
00190               if (spec.Equals("about:blank"))
00191               {
00192                 return StartNextPrintOperation();
00193               }
00194             }
00195           }
00196 
00197           // If something bad happens here (menaing we can fire the PLEvent, highly unlikely)
00198           // we will still ask the msg to print, but if the user "cancels" out of the
00199           // print dialog the hidden print window will not be "closed"
00200           if (!FirePrintEvent())
00201           {
00202             PrintMsgWindow();
00203           }
00204         } else {
00205           FireStartNextEvent();
00206           rv = NS_OK;
00207         }
00208       }
00209       else
00210       {
00211         mWindow->Close();
00212       }
00213     }
00214   }
00215 
00216   return rv;
00217 }
00218 
00219 NS_IMETHODIMP
00220 nsMsgPrintEngine::OnProgressChange(nsIWebProgress *aWebProgress,
00221                                      nsIRequest *aRequest,
00222                                      PRInt32 aCurSelfProgress,
00223                                      PRInt32 aMaxSelfProgress,
00224                                      PRInt32 aCurTotalProgress,
00225                                      PRInt32 aMaxTotalProgress)
00226 {
00227     return NS_OK;
00228 }
00229 
00230 NS_IMETHODIMP
00231 nsMsgPrintEngine::OnLocationChange(nsIWebProgress* aWebProgress,
00232                       nsIRequest* aRequest,
00233                       nsIURI *location)
00234 {
00235     NS_NOTREACHED("notification excluded in AddProgressListener(...)");
00236     return NS_OK;
00237 }
00238 
00239 
00240 NS_IMETHODIMP
00241 nsMsgPrintEngine::OnStatusChange(nsIWebProgress* aWebProgress,
00242                     nsIRequest* aRequest,
00243                     nsresult aStatus,
00244                     const PRUnichar* aMessage)
00245 {
00246     return NS_OK;
00247 }
00248 
00249 
00250 NS_IMETHODIMP
00251 nsMsgPrintEngine::OnSecurityChange(nsIWebProgress *aWebProgress,
00252                       nsIRequest *aRequest,
00253                       PRUint32 state)
00254 {
00255     NS_NOTREACHED("notification excluded in AddProgressListener(...)");
00256     return NS_OK;
00257 }
00258 
00259 NS_IMETHODIMP
00260 nsMsgPrintEngine::SetWindow(nsIDOMWindowInternal *aWin)
00261 {
00262        if (!aWin)
00263   {
00264     // It isn't an error to pass in null for aWin, in fact it means we are shutting
00265     // down and we should start cleaning things up...
00266               return NS_OK;
00267   }
00268 
00269   mWindow = aWin;
00270 
00271   nsCOMPtr<nsIScriptGlobalObject> globalObj( do_QueryInterface(aWin) );
00272   NS_ENSURE_TRUE(globalObj, NS_ERROR_FAILURE);
00273 
00274   globalObj->GetDocShell()->SetAppType(nsIDocShell::APP_TYPE_MAIL);
00275 
00276   nsCOMPtr<nsIDocShellTreeItem> docShellAsItem =
00277     do_QueryInterface(globalObj->GetDocShell());
00278   NS_ENSURE_TRUE(docShellAsItem, NS_ERROR_FAILURE);
00279 
00280   nsCOMPtr<nsIDocShellTreeItem> rootAsItem;
00281   docShellAsItem->GetSameTypeRootTreeItem(getter_AddRefs(rootAsItem));
00282 
00283   nsCOMPtr<nsIDocShellTreeNode> rootAsNode(do_QueryInterface(rootAsItem));
00284   NS_ENSURE_TRUE(rootAsNode, NS_ERROR_FAILURE);
00285 
00286   nsCOMPtr<nsIDocShellTreeItem> childItem;
00287   rootAsNode->FindChildWithName(NS_LITERAL_STRING("content").get(), PR_TRUE,
00288                             PR_FALSE, nsnull, nsnull,
00289                             getter_AddRefs(childItem));
00290 
00291   mDocShell = do_QueryInterface(childItem);
00292 
00293   if(mDocShell)
00294     SetupObserver();
00295 
00296   return NS_OK;
00297 }
00298 
00299 /* void setParentWindow (in nsIDOMWindowInternal ptr); */
00300 NS_IMETHODIMP nsMsgPrintEngine::SetParentWindow(nsIDOMWindowInternal *ptr)
00301 {
00302   mParentWindow = ptr;
00303   return NS_OK;
00304 }
00305 
00306 
00307 NS_IMETHODIMP
00308 nsMsgPrintEngine::ShowWindow(PRBool aShow)
00309 {
00310   nsresult rv;
00311 
00312   NS_ENSURE_TRUE(mWindow, NS_ERROR_NOT_INITIALIZED);
00313 
00314   nsCOMPtr <nsIScriptGlobalObject> globalScript = do_QueryInterface(mWindow, &rv);
00315 
00316   NS_ENSURE_SUCCESS(rv,rv);
00317 
00318   nsCOMPtr <nsIDocShellTreeItem> treeItem =
00319     do_QueryInterface(globalScript->GetDocShell(), &rv);
00320   NS_ENSURE_SUCCESS(rv,rv);
00321 
00322   nsCOMPtr <nsIDocShellTreeOwner> treeOwner;
00323   rv = treeItem->GetTreeOwner(getter_AddRefs(treeOwner));
00324   NS_ENSURE_SUCCESS(rv,rv);
00325 
00326   if (treeOwner) {
00327     // disable (enable) the window
00328     nsCOMPtr<nsIBaseWindow> baseWindow;
00329     baseWindow = do_QueryInterface(treeOwner, &rv);
00330     NS_ENSURE_SUCCESS(rv,rv);
00331 
00332     rv = baseWindow->SetEnabled(aShow);
00333     NS_ENSURE_SUCCESS(rv,rv);
00334 
00335     // hide or show the window
00336     baseWindow->SetVisibility(aShow);
00337   }
00338   return rv;
00339 }
00340 
00341 NS_IMETHODIMP
00342 nsMsgPrintEngine::AddPrintURI(const PRUnichar *aMsgURI)
00343 {
00344   mURIArray.AppendString(nsDependentString(aMsgURI));
00345   return NS_OK;
00346 }
00347 
00348 NS_IMETHODIMP
00349 nsMsgPrintEngine::SetPrintURICount(PRInt32 aCount)
00350 {
00351   mURICount = aCount;
00352   return NS_OK;
00353 }
00354 
00355 NS_IMETHODIMP
00356 nsMsgPrintEngine::StartPrintOperation(nsIPrintSettings* aPS)
00357 {
00358   NS_ENSURE_ARG_POINTER(aPS);
00359   mPrintSettings = aPS;
00360 
00361   // Load the about:blank on the tail end...
00362   nsresult rv = AddPrintURI(NS_LITERAL_STRING("about:blank").get());
00363   if (NS_FAILED(rv)) return rv;
00364   return StartNextPrintOperation();
00365 }
00366 
00367 //----------------------------------------------------------------------
00368 // Set up to use the "pluggable" Print Progress Dialog
00369 nsresult
00370 nsMsgPrintEngine::ShowProgressDialog(PRBool aIsForPrinting, PRBool& aDoNotify)
00371 {
00372   nsresult rv;
00373 
00374   // default to not notifying, that if something here goes wrong
00375   // or we aren't going to show the progress dialog we can straight into
00376   // reflowing the doc for printing.
00377   aDoNotify = PR_FALSE;
00378 
00379   // Assume we can't do progress and then see if we can
00380   PRBool showProgressDialog = PR_FALSE;
00381 
00382   // if it is already being shown then don't bother to find out if it should be
00383   // so skip this and leave mShowProgressDialog set to FALSE
00384   nsCOMPtr<nsIPrefBranch> prefBranch = do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
00385   if (NS_SUCCEEDED(rv))
00386   {
00387     prefBranch->GetBoolPref("print.show_print_progress", &showProgressDialog);
00388   }
00389 
00390   // Turning off the showing of Print Progress in Prefs overrides
00391   // whether the calling PS desire to have it on or off, so only check PS if
00392   // prefs says it's ok to be on.
00393   if (showProgressDialog)
00394   {
00395     mPrintSettings->GetShowPrintProgress(&showProgressDialog);
00396   }
00397 
00398   // Now open the service to get the progress dialog
00399   // If we don't get a service, that's ok, then just don't show progress
00400   if (showProgressDialog) {
00401     if (!mPrintPromptService)
00402     {
00403       mPrintPromptService = do_GetService(kPrintingPromptService);
00404     }
00405     if (mPrintPromptService)
00406     {
00407       nsCOMPtr<nsIDOMWindow> domWin(do_QueryInterface(mParentWindow));
00408       if (!domWin)
00409       {
00410         domWin = mWindow;
00411       }
00412 
00413       rv = mPrintPromptService->ShowProgress(domWin, mWebBrowserPrint, mPrintSettings, this, aIsForPrinting,
00414                                             getter_AddRefs(mPrintProgressListener),
00415                                             getter_AddRefs(mPrintProgressParams),
00416                                             &aDoNotify);
00417       if (NS_SUCCEEDED(rv)) {
00418 
00419         showProgressDialog = mPrintProgressListener != nsnull && mPrintProgressParams != nsnull;
00420 
00421         if (showProgressDialog)
00422         {
00423           nsIWebProgressListener* wpl = NS_STATIC_CAST(nsIWebProgressListener*, mPrintProgressListener.get());
00424           NS_ASSERTION(wpl, "nsIWebProgressListener is NULL!");
00425           NS_ADDREF(wpl);
00426           PRUnichar *msg = nsnull;
00427           if (mIsDoingPrintPreview) {
00428             GetString(NS_LITERAL_STRING("LoadingMailMsgForPrintPreview").get());
00429           } else {
00430             GetString(NS_LITERAL_STRING("LoadingMailMsgForPrint").get());
00431           }
00432           if (msg)
00433           {
00434             mPrintProgressParams->SetDocTitle(msg);
00435             nsCRT::free(msg);
00436           }
00437         }
00438       }
00439     }
00440   }
00441   return rv;
00442 }
00443 
00444 
00445 NS_IMETHODIMP
00446 nsMsgPrintEngine::StartNextPrintOperation()
00447 {
00448   nsresult      rv;
00449 
00450   // Only do this the first time through...
00451   if (mCurrentlyPrintingURI == -1)
00452     InitializeDisplayCharset();
00453 
00454   mCurrentlyPrintingURI++;
00455 
00456   // First, check if we are at the end of this stuff!
00457   if ( mCurrentlyPrintingURI >= mURIArray.Count() )
00458   {
00459     // This is the end...dum, dum, dum....my only friend...the end
00460     mWindow->Close();
00461 
00462     // Tell the user we are done...
00463     PRUnichar *msg = GetString(NS_LITERAL_STRING("PrintingComplete").get());
00464     SetStatusMessage( msg );
00465     CRTFREEIF(msg)
00466 
00467     return NS_OK;
00468   }
00469 
00470   if (!mDocShell)
00471     return StartNextPrintOperation();
00472 
00473   nsString *uri = mURIArray.StringAt(mCurrentlyPrintingURI);
00474   rv = FireThatLoadOperationStartup(uri);
00475   if (NS_FAILED(rv))
00476     return StartNextPrintOperation();
00477   else
00478     return rv;
00479 }
00480 
00481 NS_IMETHODIMP
00482 nsMsgPrintEngine::SetStatusFeedback(nsIMsgStatusFeedback *aFeedback)
00483 {
00484        mFeedback = aFeedback;
00485        return NS_OK;
00486 }
00487 
00488 #define DATA_URL_PREFIX     "data:"
00489 #define DATA_URL_PREFIX_LEN 5
00490 
00491 #define ADDBOOK_URL_PREFIX     "addbook:"
00492 #define ADDBOOK_URL_PREFIX_LEN 8
00493 
00494 NS_IMETHODIMP
00495 nsMsgPrintEngine::FireThatLoadOperationStartup(nsString *uri)
00496 {
00497   if (uri)
00498   {
00499     mLoadURI = *uri;
00500   }
00501   else
00502   {
00503     mLoadURI.SetLength(0);
00504   }
00505 
00506   PRBool   notify = PR_FALSE;
00507   nsresult rv     = NS_ERROR_FAILURE;
00508   // Don't show dialog if we are out of URLs
00509   //if ( mCurrentlyPrintingURI < mURIArray.Count() && !mIsDoingPrintPreview)
00510   if ( mCurrentlyPrintingURI < mURIArray.Count())
00511   {
00512     rv = ShowProgressDialog(!mIsDoingPrintPreview, notify);
00513   }
00514   if (NS_FAILED(rv) || !notify)
00515   {
00516     return FireThatLoadOperation(uri);
00517   }
00518   return NS_OK;
00519 }
00520 
00521 NS_IMETHODIMP
00522 nsMsgPrintEngine::FireThatLoadOperation(nsString *uri)
00523 {
00524   nsresult rv = NS_OK;
00525 
00526   char  *tString = ToNewCString(*uri);
00527   if (!tString)
00528     return NS_ERROR_OUT_OF_MEMORY;
00529 
00530   nsCOMPtr <nsIMsgMessageService> messageService;
00531 
00532   // if this is a data: url, skip it, because
00533   // we've already got something we can print
00534   // and we know it is not a message.
00535   //
00536   // if this an about:blank url, skip it, because
00537   // ...
00538   //
00539   // if this is an addbook: url, skip it, because
00540   // we know that isn't a message.
00541   //
00542   // if this is a message part (or .eml file on disk)
00543   // skip it, because we don't want to print the parent message
00544   // we want to print the part.
00545   // example:  imap://sspitzer@nsmail-1:143/fetch%3EUID%3E/INBOX%3E180958?part=1.1.2&type=application/x-message-display&filename=test"
00546   if (strncmp(tString, DATA_URL_PREFIX, DATA_URL_PREFIX_LEN) &&
00547       strncmp(tString, ADDBOOK_URL_PREFIX, ADDBOOK_URL_PREFIX_LEN) &&
00548       strcmp(tString, "about:blank") &&
00549       !strstr(tString, "type=application/x-message-display")) {
00550     rv = GetMessageServiceFromURI(tString, getter_AddRefs(messageService));
00551   }
00552 
00553   if (NS_SUCCEEDED(rv) && messageService)
00554   {
00555     rv = messageService->DisplayMessageForPrinting(tString, mDocShell, nsnull, nsnull, nsnull);
00556   }
00557   //If it's not something we know about, then just load try loading it directly.
00558   else
00559   {
00560     nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(mDocShell));
00561     if (webNav)
00562       rv = webNav->LoadURI(uri->get(),                        // URI string
00563                            nsIWebNavigation::LOAD_FLAGS_NONE, // Load flags
00564                            nsnull,                            // Referring URI
00565                            nsnull,                            // Post data
00566                            nsnull);                           // Extra headers
00567   }
00568 
00569   if (tString) nsCRT::free(tString);
00570   return rv;
00571 }
00572 
00573 void
00574 nsMsgPrintEngine::InitializeDisplayCharset()
00575 {
00576   // libmime always converts to UTF-8 (both HTML and XML)
00577   if (mDocShell)
00578   {
00579     nsCOMPtr<nsIContentViewer> cv;
00580     mDocShell->GetContentViewer(getter_AddRefs(cv));
00581     if (cv)
00582     {
00583       nsCOMPtr<nsIMarkupDocumentViewer> muDV = do_QueryInterface(cv);
00584       if (muDV)
00585       {
00586         muDV->SetForceCharacterSet(NS_LITERAL_CSTRING("UTF-8"));
00587       }
00588     }
00589   }
00590 }
00591 
00592 void
00593 nsMsgPrintEngine::SetupObserver()
00594 {
00595   if (!mDocShell)
00596     return;
00597 
00598   if (mDocShell)
00599   {
00600     nsCOMPtr<nsIWebProgress> progress(do_GetInterface(mDocShell));
00601     NS_ASSERTION(progress, "we were expecting a nsIWebProgress");
00602     if (progress)
00603     {
00604       (void) progress->AddProgressListener((nsIWebProgressListener *)this,
00605                                         nsIWebProgress::NOTIFY_STATE_DOCUMENT);
00606     }
00607 
00608     // Cache a pointer to the mail message's DOMWindow
00609     // so later we know when we can print when the
00610     // document "loaded" msgs com thru via the Progress listener
00611     mMsgDOMWin = do_GetInterface(mDocShell);
00612   }
00613 }
00614 
00615 nsresult
00616 nsMsgPrintEngine::SetStatusMessage(PRUnichar *aMsgString)
00617 {
00618   if ( (!mFeedback) || (!aMsgString) )
00619     return NS_OK;
00620 
00621   mFeedback->ShowStatusString(aMsgString);
00622   return NS_OK;
00623 }
00624 
00625 #define MESSENGER_STRING_URL       "chrome://messenger/locale/messenger.properties"
00626 
00627 PRUnichar *
00628 nsMsgPrintEngine::GetString(const PRUnichar *aStringName)
00629 {
00630        nsresult    res = NS_OK;
00631   PRUnichar   *ptrv = nsnull;
00632 
00633        if (!mStringBundle)
00634        {
00635               static const char propertyURL[] = MESSENGER_STRING_URL;
00636 
00637               nsCOMPtr<nsIStringBundleService> sBundleService =
00638                        do_GetService(NS_STRINGBUNDLE_CONTRACTID, &res);
00639               if (NS_SUCCEEDED(res) && (nsnull != sBundleService))
00640               {
00641                      res = sBundleService->CreateBundle(propertyURL, getter_AddRefs(mStringBundle));
00642               }
00643        }
00644 
00645        if (mStringBundle)
00646               res = mStringBundle->GetStringFromName(aStringName, &ptrv);
00647 
00648   if ( NS_SUCCEEDED(res) && (ptrv) )
00649     return ptrv;
00650   else
00651     return nsCRT::strdup(aStringName);
00652 }
00653 
00654 //-----------------------------------------------------------
00655 void
00656 nsMsgPrintEngine::PrintMsgWindow()
00657 {
00658   const char* kMsgKeys[] = {"PrintingMessage",  "PrintPreviewMessage",
00659                             "PrintingCard",     "PrintPreviewCard",
00660                             "PrintingAddrBook", "PrintPreviewAddrBook"};
00661 
00662   mDocShell->GetContentViewer(getter_AddRefs(mContentViewer));
00663   if (mContentViewer)
00664   {
00665     mWebBrowserPrint = do_QueryInterface(mContentViewer);
00666     if (mWebBrowserPrint)
00667     {
00668       if (!mPrintSettings)
00669       {
00670         mWebBrowserPrint->GetGlobalPrintSettings(getter_AddRefs(mPrintSettings));
00671       }
00672 
00673       // fix for bug #118887 and bug #176016
00674       // don't show the actual url when printing mail messages or addressbook cards.
00675       // for mail, it can review the salt.  for addrbook, it's a data:// url, which
00676       // means nothing to the end user.
00677       // needs to be " " and not "" or nsnull, otherwise, we'll still print the url
00678       mPrintSettings->SetDocURL(NS_LITERAL_STRING(" ").get());
00679 
00680       nsresult rv = NS_ERROR_FAILURE;
00681       if (mIsDoingPrintPreview)
00682       {
00683         if (mStartupPPObs) {
00684           rv = mStartupPPObs->Observe(nsnull, nsnull, nsnull);
00685         }
00686       }
00687       else
00688       {
00689         mPrintSettings->SetPrintSilent(mCurrentlyPrintingURI != 0);
00690         nsCOMPtr<nsIContentViewerFile> contentViewerFile(do_QueryInterface(mWebBrowserPrint));
00691         if (contentViewerFile && mParentWindow)
00692         {
00693           rv = contentViewerFile->PrintWithParent(mParentWindow, mPrintSettings, (nsIWebProgressListener *)this);
00694         }
00695         else
00696         {
00697           rv = mWebBrowserPrint->Print(mPrintSettings, (nsIWebProgressListener *)this);
00698         }
00699       }
00700 
00701       if (NS_FAILED(rv))
00702       {
00703         mWebBrowserPrint = nsnull;
00704         mContentViewer = nsnull;
00705         PRBool isPrintingCancelled = PR_FALSE;
00706         if (mPrintSettings)
00707         {
00708           mPrintSettings->GetIsCancelled(&isPrintingCancelled);
00709         }
00710         if (!isPrintingCancelled)
00711         {
00712           StartNextPrintOperation();
00713         }
00714         else
00715         {
00716           mWindow->Close();
00717         }
00718       }
00719       else
00720       {
00721         // Tell the user we started printing...
00722         PRUnichar *msg = GetString(NS_ConvertASCIItoUCS2(kMsgKeys[mMsgInx]).get());
00723         SetStatusMessage( msg );
00724         CRTFREEIF(msg)
00725       }
00726     }
00727   }
00728 }
00729 
00730 //---------------------------------------------------------------
00731 //-- PLEvent Notification
00732 //---------------------------------------------------------------
00733 //-----------------------------------------------------------
00734 PRBool
00735 FireEvent(nsMsgPrintEngine* aMPE, PLHandleEventProc handler, PLDestroyEventProc destructor)
00736 {
00737   static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
00738 
00739   nsCOMPtr<nsIEventQueueService> event_service = do_GetService(kEventQueueServiceCID);
00740 
00741   if (!event_service)
00742   {
00743     NS_WARNING("Failed to get event queue service");
00744     return PR_FALSE;
00745   }
00746 
00747   nsCOMPtr<nsIEventQueue> event_queue;
00748 
00749   event_service->GetThreadEventQueue(NS_CURRENT_THREAD,
00750                                      getter_AddRefs(event_queue));
00751 
00752   if (!event_queue)
00753   {
00754     NS_WARNING("Failed to get event queue from service");
00755     return PR_FALSE;
00756   }
00757 
00758   PLEvent *event = new PLEvent;
00759 
00760   if (!event)
00761   {
00762     NS_WARNING("Out of memory?");
00763     return PR_FALSE;
00764   }
00765 
00766   PL_InitEvent(event, aMPE, handler, destructor);
00767 
00768   // The event owns the msgPrintEngine pointer now.
00769   NS_ADDREF(aMPE);
00770 
00771   if (NS_FAILED(event_queue->PostEvent(event)))
00772   {
00773     NS_WARNING("Failed to post event");
00774     PL_DestroyEvent(event);
00775     return PR_FALSE;
00776   }
00777 
00778   return PR_TRUE;
00779 }
00780 
00781 void PR_CALLBACK HandlePLEventPrintMsgWindow(PLEvent* aEvent)
00782 {
00783   nsMsgPrintEngine *msgPrintEngine = (nsMsgPrintEngine*)PL_GetEventOwner(aEvent);
00784 
00785   NS_ASSERTION(msgPrintEngine, "The event owner is null.");
00786   if (msgPrintEngine)
00787   {
00788     msgPrintEngine->PrintMsgWindow();
00789   }
00790 }
00791 
00792 //------------------------------------------------------------------------
00793 void PR_CALLBACK DestroyPLEventPrintMsgWindow(PLEvent* aEvent)
00794 {
00795   nsMsgPrintEngine *msgPrintEngine = (nsMsgPrintEngine*)PL_GetEventOwner(aEvent);
00796   NS_IF_RELEASE(msgPrintEngine);
00797 
00798   delete aEvent;
00799 }
00800 
00801 //-----------------------------------------------------------
00802 PRBool
00803 nsMsgPrintEngine::FirePrintEvent()
00804 {
00805   return FireEvent(this, (PLHandleEventProc)::HandlePLEventPrintMsgWindow,
00806                          (PLDestroyEventProc)::DestroyPLEventPrintMsgWindow);
00807 }
00808 
00809 void PR_CALLBACK HandlePLEventStartNext(PLEvent* aEvent)
00810 {
00811   nsMsgPrintEngine *msgPrintEngine = (nsMsgPrintEngine*)PL_GetEventOwner(aEvent);
00812 
00813   NS_ASSERTION(msgPrintEngine, "The event owner is null.");
00814   if (msgPrintEngine)
00815   {
00816     msgPrintEngine->StartNextPrintOperation();
00817   }
00818 }
00819 
00820 //------------------------------------------------------------------------
00821 void PR_CALLBACK DestroyPLEventStartNext(PLEvent* aEvent)
00822 {
00823   nsMsgPrintEngine *msgPrintEngine = (nsMsgPrintEngine*)PL_GetEventOwner(aEvent);
00824   NS_IF_RELEASE(msgPrintEngine);
00825 
00826   delete aEvent;
00827 }
00828 
00829 //-----------------------------------------------------------
00830 PRBool
00831 nsMsgPrintEngine::FireStartNextEvent()
00832 {
00833   return FireEvent(this, (PLHandleEventProc)::HandlePLEventStartNext,
00834                          (PLDestroyEventProc)::DestroyPLEventStartNext);
00835 }
00836 
00837 /* void setStartupPPObserver (in nsIObserver startupPPObs); */
00838 NS_IMETHODIMP nsMsgPrintEngine::SetStartupPPObserver(nsIObserver *startupPPObs)
00839 {
00840   mStartupPPObs = startupPPObs;
00841   return NS_OK;
00842 }
00843 
00844 /* attribute boolean doPrintPreview; */
00845 NS_IMETHODIMP nsMsgPrintEngine::GetDoPrintPreview(PRBool *aDoPrintPreview)
00846 {
00847   NS_ENSURE_ARG_POINTER(aDoPrintPreview);
00848   *aDoPrintPreview = mIsDoingPrintPreview;
00849   return NS_OK;
00850 }
00851 NS_IMETHODIMP nsMsgPrintEngine::SetDoPrintPreview(PRBool aDoPrintPreview)
00852 {
00853   mIsDoingPrintPreview = aDoPrintPreview;
00854   return NS_OK;
00855 }
00856 
00857 /* readonly attribute nsIWebBrowserPrint webBrowserPrint; */
00858 NS_IMETHODIMP nsMsgPrintEngine::GetWebBrowserPrint(nsIWebBrowserPrint * *aWebBrowserPrint)
00859 {
00860   NS_ENSURE_ARG_POINTER(aWebBrowserPrint);
00861   *aWebBrowserPrint = nsnull;
00862 
00863   NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
00864   mDocShell->GetContentViewer(getter_AddRefs(mContentViewer));
00865   NS_ENSURE_TRUE(mContentViewer, NS_ERROR_FAILURE);
00866   mWebBrowserPrint = do_QueryInterface(mContentViewer);
00867   NS_ENSURE_TRUE(mWebBrowserPrint, NS_ERROR_FAILURE);
00868 
00869   NS_ADDREF(*aWebBrowserPrint = mWebBrowserPrint);
00870 
00871   return NS_OK;
00872 }
00873 
00874 /* void setMsgType (in long aMsgType); */
00875 NS_IMETHODIMP nsMsgPrintEngine::SetMsgType(PRInt32 aMsgType)
00876 {
00877   if (mMsgInx >= nsIMsgPrintEngine::MNAB_START && mMsgInx < nsIMsgPrintEngine::MNAB_END)
00878   {
00879     mMsgInx = aMsgType;
00880     return NS_OK;
00881   }
00882   return NS_ERROR_FAILURE;
00883 }
00884 
00885 /*=============== nsIObserver Interface ======================*/
00886 NS_IMETHODIMP nsMsgPrintEngine::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *aData)
00887 {
00888   return FireThatLoadOperation(&mLoadURI);
00889 }