Bug 889219. Part 1: Clean up nsPrintEngine string usage for document titles/URLs. r=mats
authorRobert O'Callahan <robert@ocallahan.org>
Wed, 24 Jul 2013 23:48:37 +1200
changeset 152105 20b11f54203cb96254a08321ac9c97bde1443ee2
parent 152104 8a3e8b6c04ebba6b6b70c16dd67dacf1b984e265
child 152106 a005d2b576e4b0789b7a51f9741eb75495cc8cff
push id2859
push userakeybl@mozilla.com
push dateMon, 16 Sep 2013 19:14:59 +0000
treeherdermozilla-beta@87d3c51cd2bf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmats
bugs889219
milestone25.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 889219. Part 1: Clean up nsPrintEngine string usage for document titles/URLs. r=mats
gfx/src/nsDeviceContext.cpp
gfx/src/nsDeviceContext.h
layout/generic/nsIPageSequenceFrame.h
layout/generic/nsPageFrame.cpp
layout/generic/nsSimplePageSequence.cpp
layout/generic/nsSimplePageSequence.h
layout/printing/nsPrintData.h
layout/printing/nsPrintEngine.cpp
layout/printing/nsPrintEngine.h
widget/android/nsDeviceContextAndroid.cpp
widget/android/nsDeviceContextAndroid.h
widget/cocoa/nsDeviceContextSpecX.h
widget/cocoa/nsDeviceContextSpecX.mm
widget/gtk2/nsDeviceContextSpecG.cpp
widget/gtk2/nsDeviceContextSpecG.h
widget/nsIDeviceContextSpec.h
widget/os2/nsDeviceContextSpecOS2.cpp
widget/os2/nsDeviceContextSpecOS2.h
widget/qt/nsDeviceContextSpecQt.cpp
widget/qt/nsDeviceContextSpecQt.h
widget/windows/nsDeviceContextSpecWin.h
--- a/gfx/src/nsDeviceContext.cpp
+++ b/gfx/src/nsDeviceContext.cpp
@@ -467,25 +467,25 @@ nsDeviceContext::InitForPrinting(nsIDevi
     Init(nullptr);
 
     CalcPrintingSize();
 
     return NS_OK;
 }
 
 nsresult
-nsDeviceContext::BeginDocument(PRUnichar*  aTitle,
-                               PRUnichar*  aPrintToFileName,
-                               int32_t     aStartPage,
-                               int32_t     aEndPage)
+nsDeviceContext::BeginDocument(const nsAString& aTitle,
+                               PRUnichar*       aPrintToFileName,
+                               int32_t          aStartPage,
+                               int32_t          aEndPage)
 {
     static const PRUnichar kEmpty[] = { '\0' };
     nsresult rv;
 
-    rv = mPrintingSurface->BeginPrinting(nsDependentString(aTitle ? aTitle : kEmpty),
+    rv = mPrintingSurface->BeginPrinting(aTitle,
                                          nsDependentString(aPrintToFileName ? aPrintToFileName : kEmpty));
 
     if (NS_SUCCEEDED(rv) && mDeviceContextSpec)
         rv = mDeviceContextSpec->BeginDocument(aTitle, aPrintToFileName, aStartPage, aEndPage);
 
     return rv;
 }
 
--- a/gfx/src/nsDeviceContext.h
+++ b/gfx/src/nsDeviceContext.h
@@ -166,20 +166,20 @@ public:
      * @param aPrintToFileName - name of file to print to, if nullptr
      * then don't print to file
      * @param aStartPage - starting page number (must be greater than zero)
      * @param aEndPage - ending page number (must be less than or
      * equal to number of pages)
      *
      * @return error status
      */
-    nsresult BeginDocument(PRUnichar  *aTitle,
-                           PRUnichar  *aPrintToFileName,
-                           int32_t     aStartPage,
-                           int32_t     aEndPage);
+    nsresult BeginDocument(const nsAString& aTitle,
+                           PRUnichar*       aPrintToFileName,
+                           int32_t          aStartPage,
+                           int32_t          aEndPage);
 
     /**
      * Inform the output device that output of a document is ending.
      * Used for print related device contexts. Must be matched 1:1 with
      * BeginDocument()
      * @return error status
      */
     nsresult EndDocument();
--- a/layout/generic/nsIPageSequenceFrame.h
+++ b/layout/generic/nsIPageSequenceFrame.h
@@ -30,20 +30,20 @@ public:
    *            progress notifications. Can be NULL
    * @return  NS_OK if successful
    *          NS_ERROR_ABORT if the client cancels printing using the callback
    *            interface
    *          NS_ERROR_INVALID_ARG if printing a range of pages (not all pages)
    *            and the start page is greater than the total number of pages
    *          NS_ERROR_FAILURE if there is an error
    */
-  NS_IMETHOD StartPrint(nsPresContext*  aPresContext,
+  NS_IMETHOD StartPrint(nsPresContext*    aPresContext,
                         nsIPrintSettings* aPrintOptions,
-                        PRUnichar* aDocTitle,
-                        PRUnichar* aDocURL) = 0;
+                        const nsAString&  aDocTitle,
+                        const nsAString&  aDocURL) = 0;
 
   NS_IMETHOD PrePrintNextPage(nsITimerCallback* aCallback, bool* aDone) = 0;
   NS_IMETHOD PrintNextPage() = 0;
   NS_IMETHOD ResetPrintCanvasList() = 0;
   NS_IMETHOD GetCurrentPageNum(int32_t* aPageNum) = 0;
   NS_IMETHOD GetNumPages(int32_t* aNumPages) = 0;
   NS_IMETHOD IsDoingPrintRange(bool* aDoing) = 0;
   NS_IMETHOD GetPrintRange(int32_t* aFromPage, int32_t* aToPage) = 0;
--- a/layout/generic/nsPageFrame.cpp
+++ b/layout/generic/nsPageFrame.cpp
@@ -216,30 +216,22 @@ nsPageFrame::ProcessSpecialCodes(const n
   if (aStr.Find(kPage) != kNotFound) {
     PRUnichar * uStr = nsTextFormatter::smprintf(mPD->mPageNumFormat, mPageNum);
     aNewStr.ReplaceSubstring(kPage.get(), uStr);
     nsMemory::Free(uStr);
   }
 
   NS_NAMED_LITERAL_STRING(kTitle, "&T");
   if (aStr.Find(kTitle) != kNotFound) {
-    if (mPD->mDocTitle != nullptr) {
-      aNewStr.ReplaceSubstring(kTitle.get(), mPD->mDocTitle);
-    } else {
-      aNewStr.ReplaceSubstring(kTitle.get(), EmptyString().get());
-    }
+    aNewStr.ReplaceSubstring(kTitle.get(), mPD->mDocTitle.get());
   }
 
   NS_NAMED_LITERAL_STRING(kDocURL, "&U");
   if (aStr.Find(kDocURL) != kNotFound) {
-    if (mPD->mDocURL != nullptr) {
-      aNewStr.ReplaceSubstring(kDocURL.get(), mPD->mDocURL);
-    } else {
-      aNewStr.ReplaceSubstring(kDocURL.get(), EmptyString().get());
-    }
+    aNewStr.ReplaceSubstring(kDocURL.get(), mPD->mDocURL.get());
   }
 
   NS_NAMED_LITERAL_STRING(kPageTotal, "&L");
   if (aStr.Find(kPageTotal) != kNotFound) {
     PRUnichar * uStr = nsTextFormatter::smprintf(mPD->mPageNumFormat, mTotNumPages);
     aNewStr.ReplaceSubstring(kPageTotal.get(), uStr);
     nsMemory::Free(uStr);
   }
--- a/layout/generic/nsSimplePageSequence.cpp
+++ b/layout/generic/nsSimplePageSequence.cpp
@@ -58,34 +58,30 @@ GetLayoutPrintingLog()
 
 // This object a shared by all the nsPageFrames 
 // parented to a SimplePageSequenceFrame
 nsSharedPageData::nsSharedPageData() :
   mDateTimeStr(nullptr),
   mHeadFootFont(nullptr),
   mPageNumFormat(nullptr),
   mPageNumAndTotalsFormat(nullptr),
-  mDocTitle(nullptr),
-  mDocURL(nullptr),
   mReflowSize(0,0),
   mReflowMargin(0,0,0,0),
   mEdgePaperMargin(0,0,0,0),
   mPageContentXMost(0),
   mPageContentSize(0)
 {
 }
 
 nsSharedPageData::~nsSharedPageData()
 {
   nsMemory::Free(mDateTimeStr);
   delete mHeadFootFont;
   nsMemory::Free(mPageNumFormat);
   nsMemory::Free(mPageNumAndTotalsFormat);
-  if (mDocTitle) nsMemory::Free(mDocTitle);
-  if (mDocURL) nsMemory::Free(mDocURL);
 }
 
 nsIFrame*
 NS_NewSimplePageSequenceFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return new (aPresShell) nsSimplePageSequenceFrame(aContext);
 }
 
@@ -398,31 +394,34 @@ nsSimplePageSequenceFrame::SetPageNumber
   PRUnichar* uStr = ToNewUnicode(pageNumberFormat);
   if (uStr != nullptr) {
     SetPageNumberFormat(uStr, aPageNumOnly); // nsPageFrame will own the memory
   }
 
 }
 
 NS_IMETHODIMP
-nsSimplePageSequenceFrame::StartPrint(nsPresContext*   aPresContext,
+nsSimplePageSequenceFrame::StartPrint(nsPresContext*    aPresContext,
                                       nsIPrintSettings* aPrintSettings,
-                                      PRUnichar*        aDocTitle,
-                                      PRUnichar*        aDocURL)
+                                      const nsAString&  aDocTitle,
+                                      const nsAString&  aDocURL)
 {
   NS_ENSURE_ARG_POINTER(aPresContext);
   NS_ENSURE_ARG_POINTER(aPrintSettings);
 
   if (!mPageData->mPrintSettings) {
     mPageData->mPrintSettings = aPrintSettings;
   }
 
-  // Only set them if they are not null
-  if (aDocTitle) mPageData->mDocTitle = aDocTitle;
-  if (aDocURL) mPageData->mDocURL   = aDocURL;
+  if (!aDocTitle.IsEmpty()) {
+    mPageData->mDocTitle = aDocTitle;
+  }
+  if (!aDocURL.IsEmpty()) {
+    mPageData->mDocURL = aDocURL;
+  }
 
   aPrintSettings->GetStartPageRange(&mFromPageNum);
   aPrintSettings->GetEndPageRange(&mToPageNum);
   aPrintSettings->GetPageRanges(mPageRanges);
 
   mDoingPageRange = nsIPrintSettings::kRangeSpecifiedPageRange == mPrintRangeType ||
                     nsIPrintSettings::kRangeSelection == mPrintRangeType;
 
--- a/layout/generic/nsSimplePageSequence.h
+++ b/layout/generic/nsSimplePageSequence.h
@@ -21,18 +21,18 @@ class nsSharedPageData {
 public:
   nsSharedPageData();
   ~nsSharedPageData();
 
   PRUnichar * mDateTimeStr;
   nsFont *    mHeadFootFont;
   PRUnichar * mPageNumFormat;
   PRUnichar * mPageNumAndTotalsFormat;
-  PRUnichar * mDocTitle;
-  PRUnichar * mDocURL;
+  nsString    mDocTitle;
+  nsString    mDocURL;
 
   nsSize      mReflowSize;
   nsMargin    mReflowMargin;
   // Margin for headers and footers; it defaults to 4/100 of an inch on UNIX 
   // and 0 elsewhere; I think it has to do with some inconsistency in page size
   // computations
   nsMargin    mEdgePaperMargin;
 
@@ -66,20 +66,20 @@ public:
   NS_IMETHOD SetPageNo(int32_t aPageNo) { return NS_OK;}
   NS_IMETHOD SetSelectionHeight(nscoord aYOffset, nscoord aHeight) MOZ_OVERRIDE { mYSelOffset = aYOffset; mSelectionHeight = aHeight; return NS_OK; }
   NS_IMETHOD SetTotalNumPages(int32_t aTotal) MOZ_OVERRIDE { mTotalPages = aTotal; return NS_OK; }
   
   // For Shrink To Fit
   NS_IMETHOD GetSTFPercent(float& aSTFPercent) MOZ_OVERRIDE;
 
   // Async Printing
-  NS_IMETHOD StartPrint(nsPresContext*  aPresContext,
+  NS_IMETHOD StartPrint(nsPresContext*    aPresContext,
                         nsIPrintSettings* aPrintSettings,
-                        PRUnichar*        aDocTitle,
-                        PRUnichar*        aDocURL) MOZ_OVERRIDE;
+                        const nsAString&  aDocTitle,
+                        const nsAString&  aDocURL) MOZ_OVERRIDE;
   NS_IMETHOD PrePrintNextPage(nsITimerCallback* aCallback, bool* aDone) MOZ_OVERRIDE;
   NS_IMETHOD PrintNextPage() MOZ_OVERRIDE;
   NS_IMETHOD ResetPrintCanvasList() MOZ_OVERRIDE;
   NS_IMETHOD GetCurrentPageNum(int32_t* aPageNum) MOZ_OVERRIDE;
   NS_IMETHOD GetNumPages(int32_t* aNumPages) MOZ_OVERRIDE;
   NS_IMETHOD IsDoingPrintRange(bool* aDoing) MOZ_OVERRIDE;
   NS_IMETHOD GetPrintRange(int32_t* aFromPage, int32_t* aToPage) MOZ_OVERRIDE;
   NS_IMETHOD DoPageEnd() MOZ_OVERRIDE;
--- a/layout/printing/nsPrintData.h
+++ b/layout/printing/nsPrintData.h
@@ -36,25 +36,16 @@ class nsIWebProgressListener;
 //   because the document is no longer stable.
 // 
 //------------------------------------------------------------------------
 class nsPrintData {
 public:
 
   typedef enum {eIsPrinting, eIsPrintPreview } ePrintDataType;
 
-  // This enum tells indicates what the default should be for the title
-  // if the title from the document is null
-  enum eDocTitleDefault {
-    eDocTitleDefNone,
-    eDocTitleDefBlank,
-    eDocTitleDefURLDoc
-  };
-
-
   nsPrintData(ePrintDataType aType);
   ~nsPrintData(); // non-virtual
 
   // Listener Helper Methods
   void OnEndPrinting();
   void OnStartPrinting();
   void DoOnProgressChange(int32_t      aProgress,
                           int32_t      aMaxProgress,
--- a/layout/printing/nsPrintEngine.cpp
+++ b/layout/printing/nsPrintEngine.cpp
@@ -901,36 +901,25 @@ nsPrintEngine::EnumerateDocumentNames(ui
   int32_t     numDocs = mPrt->mPrintDocList.Length();
   PRUnichar** array   = (PRUnichar**) nsMemory::Alloc(numDocs * sizeof(PRUnichar*));
   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!");
-    PRUnichar * docTitleStr;
-    PRUnichar * docURLStr;
-    GetDocumentTitleAndURL(po->mDocument, &docTitleStr, &docURLStr);
+    nsAutoString docTitleStr;
+    nsAutoString docURLStr;
+    GetDocumentTitleAndURL(po->mDocument, docTitleStr, docURLStr);
 
     // Use the URL if the doc is empty
-    if (!docTitleStr || !*docTitleStr) {
-      if (docURLStr && *docURLStr) {
-        nsMemory::Free(docTitleStr);
-        docTitleStr = docURLStr;
-      } else {
-        nsMemory::Free(docURLStr);
-      }
-      docURLStr = nullptr;
-      if (!docTitleStr || !*docTitleStr) {
-        CleanupDocTitleArray(array, i);
-        return NS_ERROR_OUT_OF_MEMORY;
-      }
+    if (docTitleStr.IsEmpty() && !docURLStr.IsEmpty()) {
+      docTitleStr = docURLStr;
     }
-    array[i] = docTitleStr;
-    if (docURLStr) nsMemory::Free(docURLStr);
+    array[i] = ToNewUnicode(docTitleStr);
   }
   *aCount  = numDocs;
   *aResult = array;
 
   return NS_OK;
 
 }
 
@@ -1203,32 +1192,26 @@ nsPrintEngine::BuildDocTree(nsIDocShellT
       }
     }
   }
 }
 
 //---------------------------------------------------------------------
 void
 nsPrintEngine::GetDocumentTitleAndURL(nsIDocument* aDoc,
-                                      PRUnichar**  aTitle,
-                                      PRUnichar**  aURLStr)
+                                      nsAString&   aTitle,
+                                      nsAString&   aURLStr)
 {
-  NS_ASSERTION(aDoc,      "Pointer is null!");
-  NS_ASSERTION(aTitle,    "Pointer is null!");
-  NS_ASSERTION(aURLStr,   "Pointer is null!");
-
-  *aTitle  = nullptr;
-  *aURLStr = nullptr;
-
-  nsAutoString docTitle;
+  NS_ASSERTION(aDoc, "Pointer is null!");
+
+  aTitle.Truncate();
+  aURLStr.Truncate();
+
   nsCOMPtr<nsIDOMDocument> doc = do_QueryInterface(aDoc);
-  doc->GetTitle(docTitle);
-  if (!docTitle.IsEmpty()) {
-    *aTitle = ToNewUnicode(docTitle);
-  }
+  doc->GetTitle(aTitle);
 
   nsIURI* url = aDoc->GetDocumentURI();
   if (!url) return;
 
   nsCOMPtr<nsIURIFixup> urifixup(do_GetService(NS_URIFIXUP_CONTRACTID));
   if (!urifixup) return;
 
   nsCOMPtr<nsIURI> exposableURI;
@@ -1239,22 +1222,18 @@ nsPrintEngine::GetDocumentTitleAndURL(ns
   nsAutoCString urlCStr;
   exposableURI->GetSpec(urlCStr);
 
   nsresult rv;
   nsCOMPtr<nsITextToSubURI> textToSubURI = 
     do_GetService(NS_ITEXTTOSUBURI_CONTRACTID, &rv);
   if (NS_FAILED(rv)) return;
 
-  nsAutoString unescapedURI;
-  rv = textToSubURI->UnEscapeURIForUI(NS_LITERAL_CSTRING("UTF-8"),
-                                      urlCStr, unescapedURI);
-  if (NS_FAILED(rv)) return;
-
-  *aURLStr = ToNewUnicode(unescapedURI);
+  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.
@@ -1443,84 +1422,68 @@ nsPrintEngine::SetPrintPO(nsPrintObject*
 }
 
 //---------------------------------------------------------------------
 // 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,
-                                     PRUnichar**       aTitle, 
-                                     PRUnichar**       aURLStr,
-                                     eDocTitleDefault  aDefType)
+nsPrintEngine::GetDisplayTitleAndURL(nsPrintObject*   aPO,
+                                     nsAString&       aTitle,
+                                     nsAString&       aURLStr,
+                                     eDocTitleDefault aDefType)
 {
   NS_ASSERTION(aPO, "Pointer is null!");
-  NS_ASSERTION(aTitle, "Pointer is null!");
-  NS_ASSERTION(aURLStr, "Pointer is null!");
-
-  *aTitle  = nullptr;
-  *aURLStr = nullptr;
 
   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
-  PRUnichar * docTitleStrPS = nullptr;
-  PRUnichar * docURLStrPS   = nullptr;
   if (mPrt->mPrintSettings) {
+    PRUnichar * docTitleStrPS = nullptr;
+    PRUnichar * docURLStrPS   = nullptr;
     mPrt->mPrintSettings->GetTitle(&docTitleStrPS);
     mPrt->mPrintSettings->GetDocURL(&docURLStrPS);
 
-    if (docTitleStrPS && *docTitleStrPS) {
-      *aTitle  = docTitleStrPS;
+    if (docTitleStrPS) {
+      aTitle = docTitleStrPS;
     }
 
-    if (docURLStrPS && *docURLStrPS) {
-      *aURLStr  = docURLStrPS;
+    if (docURLStrPS) {
+      aURLStr = docURLStrPS;
     }
 
-    // short circut
-    if (docTitleStrPS && docURLStrPS) {
-      return;
-    }
+    nsMemory::Free(docTitleStrPS);
+    nsMemory::Free(docURLStrPS);
   }
 
-  PRUnichar* docTitle;
-  PRUnichar* docUrl;
-  GetDocumentTitleAndURL(aPO->mDocument, &docTitle, &docUrl);
-
-  if (docUrl) {
-    if (!docURLStrPS)
-      *aURLStr = docUrl;
-    else
-      nsMemory::Free(docUrl);
+  nsAutoString docTitle;
+  nsAutoString docUrl;
+  GetDocumentTitleAndURL(aPO->mDocument, docTitle, docUrl);
+
+  if (aURLStr.IsEmpty() && !docUrl.IsEmpty()) {
+    aURLStr = docUrl;
   }
 
-  if (docTitle) {
-    if (!docTitleStrPS)
-      *aTitle = docTitle;
-    else
-      nsMemory::Free(docTitle);
-  } else if (!docTitleStrPS) {
-    switch (aDefType) {
-      case eDocTitleDefBlank: *aTitle = ToNewUnicode(EmptyString());
-        break;
-
-      case eDocTitleDefURLDoc:
-        if (*aURLStr) {
-          *aTitle = NS_strdup(*aURLStr);
+  if (aTitle.IsEmpty()) {
+    if (!docTitle.IsEmpty()) {
+      aTitle = docTitle;
+    } else {
+      if (aDefType == eDocTitleDefURLDoc) {
+        if (!aURLStr.IsEmpty()) {
+          aTitle = aURLStr;
         } else if (mPrt->mBrandName) {
-          *aTitle = NS_strdup(mPrt->mBrandName);
+          aTitle = mPrt->mBrandName;
         }
-        break;
-      case eDocTitleDefNone:
-        // *aTitle defaults to nullptr
-        break;
+      }
     }
   }
 }
 
 //---------------------------------------------------------------------
 nsresult nsPrintEngine::DocumentReadyForPrinting()
 {
   if (mPrt->mPrintFrameType == nsIPrintSettings::kEachFrameSep) {
@@ -1799,19 +1762,19 @@ nsPrintEngine::SetupToPrintContent()
   bool isPrintToFile = false;
   mPrt->mPrintSettings->GetPrintToFile(&isPrintToFile);
   if (isPrintToFile) {
   // On some platforms The BeginDocument needs to know the name of the file
   // and it uses the PrintService to get it, so we need to set it into the PrintService here
     mPrt->mPrintSettings->GetToFileName(&fileName);
   }
 
-  PRUnichar * docTitleStr;
-  PRUnichar * docURLStr;
-  GetDisplayTitleAndURL(mPrt->mPrintObject, &docTitleStr, &docURLStr, eDocTitleDefURLDoc); 
+  nsAutoString docTitleStr;
+  nsAutoString docURLStr;
+  GetDisplayTitleAndURL(mPrt->mPrintObject, docTitleStr, docURLStr, eDocTitleDefURLDoc);
 
   int32_t startPage = 1;
   int32_t endPage   = mPrt->mNumPrintablePages;
 
   int16_t printRangeType = nsIPrintSettings::kRangeAllPages;
   mPrt->mPrintSettings->GetPrintRange(&printRangeType);
   if (printRangeType == nsIPrintSettings::kRangeSpecifiedPageRange) {
     mPrt->mPrintSettings->GetStartPageRange(&startPage);
@@ -1826,28 +1789,24 @@ nsPrintEngine::SetupToPrintContent()
   // 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 (!mPrt->mDebugFilePtr && mIsDoingPrinting) {
     rv = mPrt->mPrintDC->BeginDocument(docTitleStr, fileName, startPage, endPage);
   } 
 
   if (mIsCreatingPrintPreview) {
-    // Print Preview -- Pass ownership of docTitleStr and docURLStr
-    // to the pageSequenceFrame, to be displayed in the header
+    // Copy docTitleStr and docURLStr to the pageSequenceFrame, to be displayed
+    // in the header
     nsIPageSequenceFrame *seqFrame = mPrt->mPrintObject->mPresShell->GetPageSequenceFrame();
     if (seqFrame) {
       seqFrame->StartPrint(mPrt->mPrintObject->mPresContext, 
                            mPrt->mPrintSettings, docTitleStr, docURLStr);
-      docTitleStr = nullptr;
-      docURLStr = nullptr;
     }
   }
-  if (docTitleStr) nsMemory::Free(docTitleStr);
-  if (docURLStr) nsMemory::Free(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
@@ -2280,28 +2239,28 @@ nsPrintEngine::ReflowPrintObject(nsPrint
   // 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) {
-      char * docStr;
-      char * urlStr;
+      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?docStr:"");
-        fprintf(fd, "URL:   %s\n", urlStr?urlStr:"");
+        fprintf(fd, "Title: %s\n", docStr.get());
+        fprintf(fd, "URL:   %s\n", urlStr.get());
         fprintf(fd, "--------------- Frames ----------------\n");
         nsRefPtr<nsRenderingContext> renderingContext;
         mPrt->mPrintDocDC->CreateRenderingContext(*getter_AddRefs(renderingContext));
         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();
@@ -2312,18 +2271,16 @@ nsPrintEngine::ReflowPrintObject(nsPrint
         }
         if (docShell) {
           fprintf(fd, "--------------- All Views ----------------\n");
           DumpViews(docShell, fd);
           fprintf(fd, "---------------------------------------\n\n");
         }
         fclose(fd);
       }
-      if (docStr) nsMemory::Free(docStr);
-      if (urlStr) nsMemory::Free(urlStr);
     }
 #endif
 
   return NS_OK;
 }
 
 //-------------------------------------------------------
 // Figure out how many documents and how many total pages we are printing
@@ -2512,35 +2469,32 @@ nsPrintEngine::DoPrint(nsPrintObject * a
       root->DumpRegressionData(poPresContext, mPrt->mDebugFilePtr, 0);
       fclose(mPrt->mDebugFilePtr);
       SetIsPrinting(false);
 #endif
     } else {
 #ifdef EXTENDED_DEBUG_PRINTING
       nsIFrame* rootFrame = poPresShell->FrameManager()->GetRootFrame();
       if (aPO->IsPrintable()) {
-        char * docStr;
-        char * urlStr;
+        nsAutoCString docStr;
+        nsAutoCString urlStr;
         GetDocTitleAndURL(aPO, docStr, urlStr);
-        DumpLayoutData(docStr, urlStr, poPresContext, mPrt->mPrintDocDC, rootFrame, docShell, nullptr);
-        if (docStr) nsMemory::Free(docStr);
-        if (urlStr) nsMemory::Free(urlStr);
+        DumpLayoutData(docStr.get(), urlStr.get(), poPresContext, mPrt->mPrintDocDC, rootFrame, docShell, nullptr);
       }
 #endif
 
       if (!mPrt->mPrintSettings) {
         // not sure what to do here!
         SetIsPrinting(false);
         return NS_ERROR_FAILURE;
       }
 
-      PRUnichar * docTitleStr = nullptr;
-      PRUnichar * docURLStr   = nullptr;
-
-      GetDisplayTitleAndURL(aPO, &docTitleStr, &docURLStr, eDocTitleDefBlank);
+      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
         nsRefPtr<nsRenderingContext> rc;
@@ -2608,18 +2562,16 @@ nsPrintEngine::DoPrint(nsPrintObject * a
             pageSequence->SetTotalNumPages(totalPages);
           }
         }
       }
 
       nsIFrame * seqFrame = do_QueryFrame(pageSequence);
       if (!seqFrame) {
         SetIsPrinting(false);
-        if (docTitleStr) nsMemory::Free(docTitleStr);
-        if (docURLStr) nsMemory::Free(docURLStr);
         return NS_ERROR_FAILURE;
       }
 
       mPageSeqFrame = pageSequence;
       mPageSeqFrame->StartPrint(poPresContext, mPrt->mPrintSettings, docTitleStr, docURLStr);
 
       // Schedule Page to Print
       PR_PL(("Scheduling Print of PO: %p (%s) \n", aPO, gFrameTypesStr[aPO->mFrameType]));
@@ -2630,58 +2582,50 @@ nsPrintEngine::DoPrint(nsPrintObject * a
   return NS_OK;
 }
 
 //---------------------------------------------------------------------
 void
 nsPrintEngine::SetDocAndURLIntoProgress(nsPrintObject* aPO,
                                         nsIPrintProgressParams* aParams)
 {
-  NS_ASSERTION(aPO, "Must have vaild nsPrintObject");
-  NS_ASSERTION(aParams, "Must have vaild nsIPrintProgressParams");
+  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;
 
-  PRUnichar * docTitleStr;
-  PRUnichar * docURLStr;
-  GetDisplayTitleAndURL(aPO, &docTitleStr, &docURLStr, eDocTitleDefURLDoc);
+  nsAutoString docTitleStr;
+  nsAutoString docURLStr;
+  GetDisplayTitleAndURL(aPO, docTitleStr, docURLStr, eDocTitleDefURLDoc);
 
   // Make sure the Titles & URLS don't get too long for the progress dialog
-  ElipseLongString(docTitleStr, kTitleLength, false);
-  ElipseLongString(docURLStr, kTitleLength, true);
-
-  aParams->SetDocTitle(docTitleStr);
-  aParams->SetDocURL(docURLStr);
-
-  if (docTitleStr != nullptr) nsMemory::Free(docTitleStr);
-  if (docURLStr != nullptr) nsMemory::Free(docURLStr);
+  EllipseLongString(docTitleStr, kTitleLength, false);
+  EllipseLongString(docURLStr, kTitleLength, true);
+
+  aParams->SetDocTitle(docTitleStr.get());
+  aParams->SetDocURL(docURLStr.get());
 }
 
 //---------------------------------------------------------------------
 void
-nsPrintEngine::ElipseLongString(PRUnichar *& aStr, const uint32_t aLen, bool aDoFront)
+nsPrintEngine::EllipseLongString(nsAString& aStr, const uint32_t aLen, bool aDoFront)
 {
   // Make sure the URLS don't get too long for the progress dialog
-  if (aStr && NS_strlen(aStr) > aLen) {
+  if (aLen >= 3 && aStr.Length() > aLen) {
     if (aDoFront) {
-      PRUnichar * ptr = &aStr[NS_strlen(aStr) - aLen + 3];
       nsAutoString newStr;
       newStr.AppendLiteral("...");
-      newStr += ptr;
-      nsMemory::Free(aStr);
-      aStr = ToNewUnicode(newStr);
+      newStr += Substring(aStr, aStr.Length() - (aLen - 3), aLen - 3);
+      aStr = newStr;
     } else {
-      nsAutoString newStr(aStr);
-      newStr.SetLength(aLen-3);
-      newStr.AppendLiteral("...");
-      nsMemory::Free(aStr);
-      aStr = ToNewUnicode(newStr);
+      aStr.SetLength(aLen - 3);
+      aStr.AppendLiteral("...");
     }
   }
 }
 
 static bool
 DocHasPrintCallbackCanvas(nsIDocument* aDoc, void* aData)
 {
   if (!aDoc) {
@@ -3937,38 +3881,25 @@ static void DumpPrintObjectsTree(nsPrint
     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, char *& aDocStr, char *& aURLStr)
+static void GetDocTitleAndURL(nsPrintObject* aPO, nsACString& aDocStr, nsACString& aURLStr)
 {
-  aDocStr = nullptr;
-  aURLStr = nullptr;
-
-  PRUnichar * docTitleStr;
-  PRUnichar * docURLStr;
+  nsAutoString docTitleStr;
+  nsAutoString docURLStr;
   nsPrintEngine::GetDisplayTitleAndURL(aPO,
-                                            &docTitleStr, &docURLStr,
-                                            nsPrintEngine::eDocTitleDefURLDoc); 
-
-  if (docTitleStr) {
-    nsAutoString strDocTitle(docTitleStr);
-    aDocStr = ToNewCString(strDocTitle);
-    nsMemory::Free(docTitleStr);
-  }
-
-  if (docURLStr) {
-    nsAutoString strURL(docURLStr);
-    aURLStr = ToNewCString(strURL);
-    nsMemory::Free(docURLStr);
-  }
+                                       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;
@@ -3990,22 +3921,20 @@ static void DumpPrintObjectsTreeLayout(n
     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()) {
-      char * docStr;
-      char * urlStr;
+      nsAutoCString docStr;
+      nsAutoCString urlStr;
       GetDocTitleAndURL(aPO, docStr, urlStr);
-      DumpLayoutData(docStr, urlStr, aPO->mPresContext, aDC, rootFrame, aPO->mDocShell, fd);
-      if (docStr) nsMemory::Free(docStr);
-      if (urlStr) nsMemory::Free(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);
--- a/layout/printing/nsPrintEngine.h
+++ b/layout/printing/nsPrintEngine.h
@@ -66,17 +66,16 @@ public:
   NS_IMETHOD GetDoingPrint(bool *aDoingPrint);
   NS_IMETHOD GetDoingPrintPreview(bool *aDoingPrintPreview);
   NS_IMETHOD GetCurrentPrintSettings(nsIPrintSettings **aCurrentPrintSettings);
 
 
   // This enum tells indicates what the default should be for the title
   // if the title from the document is null
   enum eDocTitleDefault {
-    eDocTitleDefNone,
     eDocTitleDefBlank,
     eDocTitleDefURLDoc
   };
 
   nsPrintEngine();
   ~nsPrintEngine();
 
   void Destroy();
@@ -130,17 +129,17 @@ public:
   void ShowPrintProgress(bool aIsForPrinting, bool& aDoNotify);
   nsresult CleanupOnFailure(nsresult aResult, bool aIsPrinting);
   // If FinishPrintPreview() fails, caller may need to reset the state of the
   // object, for example by calling CleanupOnFailure().
   nsresult FinishPrintPreview();
   static void CloseProgressDialog(nsIWebProgressListener* aWebProgressListener);
   void SetDocAndURLIntoProgress(nsPrintObject* aPO,
                                 nsIPrintProgressParams* aParams);
-  void ElipseLongString(PRUnichar *& aStr, const uint32_t aLen, bool aDoFront);
+  void EllipseLongString(nsAString& aStr, const uint32_t aLen, bool aDoFront);
   nsresult CheckForPrinters(nsIPrintSettings* aPrintSettings);
   void CleanupDocTitleArray(PRUnichar**& aArray, int32_t& aCount);
 
   bool IsThereARangeSelection(nsIDOMWindow * aDOMWin);
 
   //---------------------------------------------------------------------
 
 
@@ -158,22 +157,22 @@ public:
 
   // get the currently infocus frame for the document viewer
   already_AddRefed<nsIDOMWindow> FindFocusedDOMWindow();
 
   //---------------------------------------------------------------------
   // Static Methods
   //---------------------------------------------------------------------
   static void GetDocumentTitleAndURL(nsIDocument* aDoc,
-                                     PRUnichar** aTitle,
-                                     PRUnichar** aURLStr);
-  void GetDisplayTitleAndURL(nsPrintObject*    aPO,
-                             PRUnichar**       aTitle,
-                             PRUnichar**       aURLStr,
-                             eDocTitleDefault  aDefType);
+                                     nsAString&   aTitle,
+                                     nsAString&   aURLStr);
+  void GetDisplayTitleAndURL(nsPrintObject*   aPO,
+                             nsAString&       aTitle,
+                             nsAString&       aURLStr,
+                             eDocTitleDefault aDefType);
   static void ShowPrintErrorDialog(nsresult printerror,
                                    bool aIsPrinting = true);
 
   static bool HasFramesetChild(nsIContent* aContent);
 
   bool     CheckBeforeDestroy();
   nsresult Cancelled();
 
--- a/widget/android/nsDeviceContextAndroid.cpp
+++ b/widget/android/nsDeviceContextAndroid.cpp
@@ -46,20 +46,20 @@ nsDeviceContextSpecAndroid::Init(nsIWidg
                              nsIPrintSettings* aPS,
                              bool aIsPrintPreview)
 {
   mPrintSettings = aPS;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsDeviceContextSpecAndroid::BeginDocument(PRUnichar* aTitle,
-                                      PRUnichar* aPrintToFileName,
-                                      int32_t aStartPage,
-                                      int32_t aEndPage)
+nsDeviceContextSpecAndroid::BeginDocument(const nsAString& aTitle,
+                                          PRUnichar* aPrintToFileName,
+                                          int32_t aStartPage,
+                                          int32_t aEndPage)
 {
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDeviceContextSpecAndroid::EndDocument()
 {
   nsXPIDLString targetPath;
--- a/widget/android/nsDeviceContextAndroid.h
+++ b/widget/android/nsDeviceContextAndroid.h
@@ -10,17 +10,17 @@ class nsDeviceContextSpecAndroid MOZ_FIN
 public:
     NS_DECL_ISUPPORTS
 
     NS_IMETHOD GetSurfaceForPrinter(gfxASurface** surface);
 
     NS_IMETHOD Init(nsIWidget* aWidget,
                     nsIPrintSettings* aPS,
                     bool aIsPrintPreview);
-    NS_IMETHOD BeginDocument(PRUnichar* aTitle,
+    NS_IMETHOD BeginDocument(const nsAString& aTitle,
                              PRUnichar* aPrintToFileName,
                              int32_t aStartPage,
                              int32_t aEndPage);
     NS_IMETHOD EndDocument();
     NS_IMETHOD BeginPage() { return NS_OK; }
     NS_IMETHOD EndPage() { return NS_OK; }
 
     NS_IMETHOD GetPath (const char** aPath);
--- a/widget/cocoa/nsDeviceContextSpecX.h
+++ b/widget/cocoa/nsDeviceContextSpecX.h
@@ -14,20 +14,20 @@ class nsDeviceContextSpecX : public nsID
 {
 public:
     NS_DECL_ISUPPORTS
 
     nsDeviceContextSpecX();
 
     NS_IMETHOD Init(nsIWidget *aWidget, nsIPrintSettings* aPS, bool aIsPrintPreview);
     NS_IMETHOD GetSurfaceForPrinter(gfxASurface **surface);
-    NS_IMETHOD BeginDocument(PRUnichar*  aTitle, 
-                             PRUnichar*  aPrintToFileName,
-                             int32_t     aStartPage, 
-                             int32_t     aEndPage);
+    NS_IMETHOD BeginDocument(const nsAString& aTitle,
+                             PRUnichar*       aPrintToFileName,
+                             int32_t          aStartPage,
+                             int32_t          aEndPage);
     NS_IMETHOD EndDocument();
     NS_IMETHOD BeginPage();
     NS_IMETHOD EndPage();
 
     void GetPaperRect(double* aTop, double* aLeft, double* aBottom, double* aRight);
 
 protected:
     virtual ~nsDeviceContextSpecX();
--- a/widget/cocoa/nsDeviceContextSpecX.mm
+++ b/widget/cocoa/nsDeviceContextSpecX.mm
@@ -52,25 +52,25 @@ NS_IMETHODIMP nsDeviceContextSpecX::Init
   mPageFormat = settings->GetPMPageFormat();
   mPrintSettings = settings->GetPMPrintSettings();
 
   return NS_OK;
 
   NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
 }
 
-NS_IMETHODIMP nsDeviceContextSpecX::BeginDocument(PRUnichar*  aTitle, 
-                                                  PRUnichar*  aPrintToFileName,
-                                                  int32_t     aStartPage, 
-                                                  int32_t     aEndPage)
+NS_IMETHODIMP nsDeviceContextSpecX::BeginDocument(const nsAString& aTitle, 
+                                                  PRUnichar*       aPrintToFileName,
+                                                  int32_t          aStartPage, 
+                                                  int32_t          aEndPage)
 {
     NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
 
-    if (aTitle) {
-      CFStringRef cfString = ::CFStringCreateWithCharacters(NULL, aTitle, NS_strlen(aTitle));
+    if (!aTitle.IsEmpty()) {
+      CFStringRef cfString = ::CFStringCreateWithCharacters(NULL, aTitle, aTitle.Length());
       if (cfString) {
         ::PMPrintSettingsSetJobName(mPrintSettings, cfString);
         ::CFRelease(cfString);
       }
     }
 
     OSStatus status;
     status = ::PMSetFirstPage(mPrintSettings, aStartPage, false);
--- a/widget/gtk2/nsDeviceContextSpecG.cpp
+++ b/widget/gtk2/nsDeviceContextSpecG.cpp
@@ -546,17 +546,17 @@ print_callback(GtkPrintJob *aJob, gpoint
 }
 
 static void
 ns_release_macro(gpointer aData) {
   nsIFile* spoolFile = (nsIFile*) aData;
   NS_RELEASE(spoolFile);
 }
 
-NS_IMETHODIMP nsDeviceContextSpecGTK::BeginDocument(PRUnichar * aTitle, PRUnichar * aPrintToFileName,
+NS_IMETHODIMP nsDeviceContextSpecGTK::BeginDocument(const nsAString& aTitle, PRUnichar * aPrintToFileName,
                                                     int32_t aStartPage, int32_t aEndPage)
 {
   if (mToPrinter) {
     if (!GTK_IS_PRINTER(mGtkPrinter))
       return NS_ERROR_FAILURE;
 
     mPrintJob = gtk_print_job_new(NS_ConvertUTF16toUTF8(aTitle).get(), mGtkPrinter,
                                   mGtkPrintSettings, mGtkPageSetup);
--- a/widget/gtk2/nsDeviceContextSpecG.h
+++ b/widget/gtk2/nsDeviceContextSpecG.h
@@ -37,17 +37,17 @@ class nsDeviceContextSpecGTK : public ns
 public:
   nsDeviceContextSpecGTK();
 
   NS_DECL_ISUPPORTS
 
   NS_IMETHOD GetSurfaceForPrinter(gfxASurface **surface);
 
   NS_IMETHOD Init(nsIWidget *aWidget, nsIPrintSettings* aPS, bool aIsPrintPreview);
-  NS_IMETHOD BeginDocument(PRUnichar * aTitle, PRUnichar * aPrintToFileName, int32_t aStartPage, int32_t aEndPage);
+  NS_IMETHOD BeginDocument(const nsAString& aTitle, PRUnichar * aPrintToFileName, int32_t aStartPage, int32_t aEndPage);
   NS_IMETHOD EndDocument();
   NS_IMETHOD BeginPage() { return NS_OK; }
   NS_IMETHOD EndPage() { return NS_OK; }
 
   NS_IMETHOD GetPath (const char **aPath);    
   static nsresult GetPrintMethod(const char *aPrinter, PrintMethod &aMethod);
   virtual ~nsDeviceContextSpecGTK();
   
--- a/widget/nsIDeviceContextSpec.h
+++ b/widget/nsIDeviceContextSpec.h
@@ -8,18 +8,18 @@
 
 #include "nsISupports.h"
 
 class nsIWidget;
 class nsIPrintSettings;
 class gfxASurface;
 
 #define NS_IDEVICE_CONTEXT_SPEC_IID   \
-{ 0x205c614f, 0x39f8, 0x42e1, \
-{ 0x92, 0x53, 0x04, 0x9b, 0x48, 0xc3, 0xcb, 0xd8 } }
+{ 0xb5548fb1, 0xf43e, 0x4921, \
+  { 0x82, 0x19, 0xc3, 0x82, 0x06, 0xee, 0x74, 0x5c } }
 
 class nsIDeviceContextSpec : public nsISupports
 {
 public:
    NS_DECLARE_STATIC_IID_ACCESSOR(NS_IDEVICE_CONTEXT_SPEC_IID)
 
    /**
     * Initialize the device context spec.
@@ -29,20 +29,20 @@ public:
     * @return NS_OK or a suitable error code.
     */
    NS_IMETHOD Init(nsIWidget *aWidget,
                    nsIPrintSettings* aPrintSettings,
                    bool aIsPrintPreview) = 0;
 
    NS_IMETHOD GetSurfaceForPrinter(gfxASurface **nativeSurface) = 0;
 
-   NS_IMETHOD BeginDocument(PRUnichar*  aTitle,
-                            PRUnichar*  aPrintToFileName,
-                            int32_t     aStartPage,
-                            int32_t     aEndPage) = 0;
+   NS_IMETHOD BeginDocument(const nsAString& aTitle,
+                            PRUnichar*       aPrintToFileName,
+                            int32_t          aStartPage,
+                            int32_t          aEndPage) = 0;
 
    NS_IMETHOD EndDocument() = 0;
    NS_IMETHOD BeginPage() = 0;
    NS_IMETHOD EndPage() = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIDeviceContextSpec,
                               NS_IDEVICE_CONTEXT_SPEC_IID)
--- a/widget/os2/nsDeviceContextSpecOS2.cpp
+++ b/widget/os2/nsDeviceContextSpecOS2.cpp
@@ -427,38 +427,45 @@ NS_IMETHODIMP nsDeviceContextSpecOS2::Ge
   }
   *surface = newSurface;
   NS_ADDREF(*surface);
   return NS_OK;
 }
 
 // Helper function to convert the string to the native codepage,
 // similar to UnicodeToCodepage() in nsDragService.cpp.
-char *GetACPString(const PRUnichar* aStr)
+char *GetACPString(const nsAString& aStr)
 {
-   nsString str(aStr);
-   if (str.Length() == 0) {
+   if (aStr.Length() == 0) {
       return nullptr;
    }
 
    nsAutoCharBuffer buffer;
    int32_t bufLength;
-   WideCharToMultiByte(0, PromiseFlatString(str).get(), str.Length(),
+   WideCharToMultiByte(0, PromiseFlatString(aStr).get(), aStr.Length(),
                        buffer, bufLength);
    return ToNewCString(nsDependentCString(buffer.Elements()));
 }
 
-NS_IMETHODIMP nsDeviceContextSpecOS2::BeginDocument(PRUnichar* aTitle,
+// Helper function to convert the string to the native codepage,
+// similar to UnicodeToCodepage() in nsDragService.cpp.
+char *GetACPString(const PRUnichar* aStr)
+{
+   nsString str(aStr);
+   return GetACPString(str);
+}
+
+NS_IMETHODIMP nsDeviceContextSpecOS2::BeginDocument(const nsAString& aTitle,
                                                     PRUnichar* aPrintToFileName,
                                                     int32_t aStartPage,
                                                     int32_t aEndPage)
 {
 #ifdef debug_thebes_print
   printf("nsDeviceContextSpecOS2[%#x]::BeginPrinting(%s, %s)\n", (unsigned)this,
-         NS_LossyConvertUTF16toASCII(nsString(aTitle)).get(),
+         NS_LossyConvertUTF16toASCII(aTitle).get(),
          NS_LossyConvertUTF16toASCII(nsString(aPrintToFileName)).get());
 #endif
   // don't try to send device escapes for non-native output (like PDF)
   int16_t outputFormat;
   mPrintSettings->GetOutputFormat(&outputFormat);
   if (outputFormat != nsIPrintSettings::kOutputFormatNative) {
     return NS_OK;
   }
--- a/widget/os2/nsDeviceContextSpecOS2.h
+++ b/widget/os2/nsDeviceContextSpecOS2.h
@@ -58,17 +58,17 @@ public:
 
   NS_IMETHOD GetPath ( char **aPath );    
 
   NS_IMETHOD GetUserCancelled( bool &aCancel );      
 
   NS_IMETHOD GetPRTQUEUE(PRTQUEUE *&p);
 
   NS_IMETHOD GetSurfaceForPrinter(gfxASurface **nativeSurface);
-  NS_IMETHOD BeginDocument(PRUnichar* aTitle, PRUnichar* aPrintToFileName,
+  NS_IMETHOD BeginDocument(const nsAString& aTitle, PRUnichar* aPrintToFileName,
                            int32_t aStartPage, int32_t aEndPage);
   NS_IMETHOD EndDocument();
   NS_IMETHOD BeginPage();
   NS_IMETHOD EndPage();
 
 /**
  * Destructor for nsDeviceContextSpecOS2, this will release the printrecord
  * @update  dc 2/16/98
--- a/widget/qt/nsDeviceContextSpecQt.cpp
+++ b/widget/qt/nsDeviceContextSpecQt.cpp
@@ -156,17 +156,17 @@ NS_IMETHODIMP nsDeviceContextSpecQt::Ini
 
 NS_IMETHODIMP nsDeviceContextSpecQt::GetPath(const char** aPath)
 {
     *aPath = mPath;
     return NS_OK;
 }
 
 NS_IMETHODIMP nsDeviceContextSpecQt::BeginDocument(
-        PRUnichar* aTitle,
+        const nsAString& aTitle,
         PRUnichar* aPrintToFileName,
         int32_t aStartPage,
         int32_t aEndPage)
 {
     if (mToPrinter) {
         return NS_ERROR_NOT_IMPLEMENTED;
     }
     return NS_OK;
--- a/widget/qt/nsDeviceContextSpecQt.h
+++ b/widget/qt/nsDeviceContextSpecQt.h
@@ -23,17 +23,17 @@ public:
 
     NS_DECL_ISUPPORTS
 
     NS_IMETHOD GetSurfaceForPrinter(gfxASurface** surface);
 
     NS_IMETHOD Init(nsIWidget* aWidget,
                     nsIPrintSettings* aPS,
                     bool aIsPrintPreview);
-    NS_IMETHOD BeginDocument(PRUnichar* aTitle,
+    NS_IMETHOD BeginDocument(const nsAString& aTitle,
                              PRUnichar* aPrintToFileName,
                              int32_t aStartPage,
                              int32_t aEndPage);
     NS_IMETHOD EndDocument();
     NS_IMETHOD BeginPage() { return NS_OK; }
     NS_IMETHOD EndPage() { return NS_OK; }
 
     NS_IMETHOD GetPath (const char** aPath);
--- a/widget/windows/nsDeviceContextSpecWin.h
+++ b/widget/windows/nsDeviceContextSpecWin.h
@@ -19,20 +19,20 @@ class nsIWidget;
 class nsDeviceContextSpecWin : public nsIDeviceContextSpec
 {
 public:
   nsDeviceContextSpecWin();
 
   NS_DECL_ISUPPORTS
 
   NS_IMETHOD GetSurfaceForPrinter(gfxASurface **surface);
-  NS_IMETHOD BeginDocument(PRUnichar*  aTitle, 
-                           PRUnichar*  aPrintToFileName,
-                           int32_t     aStartPage, 
-                           int32_t     aEndPage) { return NS_OK; }
+  NS_IMETHOD BeginDocument(const nsAString& aTitle,
+                           PRUnichar*       aPrintToFileName,
+                           int32_t          aStartPage,
+                           int32_t          aEndPage) { return NS_OK; }
   NS_IMETHOD EndDocument() { return NS_OK; }
   NS_IMETHOD BeginPage() { return NS_OK; }
   NS_IMETHOD EndPage() { return NS_OK; }
 
   NS_IMETHOD Init(nsIWidget* aWidget, nsIPrintSettings* aPS, bool aIsPrintPreview);
 
   void GetDriverName(PRUnichar *&aDriverName) const   { aDriverName = mDriverName;     }
   void GetDeviceName(PRUnichar *&aDeviceName) const   { aDeviceName = mDeviceName;     }