Bug 1090444 - The Printing Progress dialog does not show progress or close when opened from the child process. r=blassey.

We now proxy progress updates from the child up to the parent over IPC.

--HG--
extra : rebase_source : a66557462e013ccf2b6e253c4b401d6baa0baa01
This commit is contained in:
Mike Conley 2014-11-10 15:18:06 -05:00
parent d24a6348c0
commit c6e0d26cab
11 changed files with 530 additions and 50 deletions

View File

@ -0,0 +1,35 @@
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PPrinting;
namespace mozilla {
namespace embedding {
protocol PPrintProgressDialog
{
manager PPrinting;
parent:
StateChange(long stateFlags,
nsresult status);
ProgressChange(long curSelfProgress,
long maxSelfProgress,
long curTotalProgress,
long maxTotalProgress);
DocTitleChange(nsString newTitle);
DocURLChange(nsString newURL);
__delete__();
child:
DialogOpened();
};
} // namespace embedding
} // namespace mozilla

View File

@ -5,6 +5,7 @@
include protocol PContent;
include protocol PBrowser;
include protocol PPrintProgressDialog;
namespace mozilla {
namespace embedding {
@ -87,12 +88,20 @@ struct PrintData {
sync protocol PPrinting
{
manager PContent;
manages PPrintProgressDialog;
parent:
sync ShowProgress(PBrowser browser, bool isForPrinting);
sync ShowProgress(PBrowser browser,
PPrintProgressDialog printProgressDialog,
bool isForPrinting)
returns(bool notifyOnOpen,
bool success);
sync ShowPrintDialog(PBrowser browser, PrintData settings)
returns(PrintData modifiedSettings, bool success);
PPrintProgressDialog();
child:
__delete__();
};

View File

@ -0,0 +1,132 @@
/* 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 "mozilla/unused.h"
#include "nsIObserver.h"
#include "PrintProgressDialogChild.h"
class nsIWebProgress;
class nsIRequest;
using mozilla::unused;
namespace mozilla {
namespace embedding {
NS_IMPL_ISUPPORTS(PrintProgressDialogChild,
nsIWebProgressListener,
nsIPrintProgressParams)
MOZ_IMPLICIT PrintProgressDialogChild::PrintProgressDialogChild(
nsIObserver* aOpenObserver) :
mOpenObserver(aOpenObserver)
{
MOZ_COUNT_CTOR(PrintProgressDialogChild);
}
MOZ_IMPLICIT PrintProgressDialogChild::~PrintProgressDialogChild()
{
// When the printing engine stops supplying information about printing
// progress, it'll drop references to us and destroy us. We need to signal
// the parent to decrement its refcount, as well as prevent it from attempting
// to contact us further.
unused << Send__delete__(this);
MOZ_COUNT_DTOR(PrintProgressDialogChild);
}
bool
PrintProgressDialogChild::RecvDialogOpened()
{
// nsPrintEngine's observer, which we're reporting to here, doesn't care
// what gets passed as the subject, topic or data, so we'll just send
// nullptrs.
mOpenObserver->Observe(nullptr, nullptr, nullptr);
return true;
}
// nsIWebProgressListener
NS_IMETHODIMP
PrintProgressDialogChild::OnStateChange(nsIWebProgress* aProgress,
nsIRequest* aRequest,
uint32_t aStateFlags,
nsresult aStatus)
{
unused << SendStateChange(aStateFlags, aStatus);
return NS_OK;
}
NS_IMETHODIMP
PrintProgressDialogChild::OnProgressChange(nsIWebProgress * aProgress,
nsIRequest * aRequest,
int32_t aCurSelfProgress,
int32_t aMaxSelfProgress,
int32_t aCurTotalProgress,
int32_t aMaxTotalProgress)
{
unused << SendProgressChange(aCurSelfProgress, aMaxSelfProgress,
aCurTotalProgress, aMaxTotalProgress);
return NS_OK;
}
NS_IMETHODIMP
PrintProgressDialogChild::OnLocationChange(nsIWebProgress* aProgress,
nsIRequest* aRequest,
nsIURI* aURI,
uint32_t aFlags)
{
return NS_OK;
}
NS_IMETHODIMP
PrintProgressDialogChild::OnStatusChange(nsIWebProgress* aProgress,
nsIRequest* aRequest,
nsresult aStatus,
const char16_t* aMessage)
{
return NS_OK;
}
NS_IMETHODIMP
PrintProgressDialogChild::OnSecurityChange(nsIWebProgress* aProgress,
nsIRequest* aRequest,
uint32_t aState)
{
return NS_OK;
}
// nsIPrintProgressParams
NS_IMETHODIMP PrintProgressDialogChild::GetDocTitle(char16_t* *aDocTitle)
{
NS_ENSURE_ARG(aDocTitle);
*aDocTitle = ToNewUnicode(mDocTitle);
return NS_OK;
}
NS_IMETHODIMP PrintProgressDialogChild::SetDocTitle(const char16_t* aDocTitle)
{
mDocTitle = aDocTitle;
unused << SendDocTitleChange(nsString(aDocTitle));
return NS_OK;
}
NS_IMETHODIMP PrintProgressDialogChild::GetDocURL(char16_t **aDocURL)
{
NS_ENSURE_ARG(aDocURL);
*aDocURL = ToNewUnicode(mDocURL);
return NS_OK;
}
NS_IMETHODIMP PrintProgressDialogChild::SetDocURL(const char16_t* aDocURL)
{
mDocURL = aDocURL;
unused << SendDocURLChange(nsString(aDocURL));
return NS_OK;
}
} // namespace embedding
} // namespace mozilla

View File

@ -0,0 +1,40 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_embedding_PrintProgressDialogChild_h
#define mozilla_embedding_PrintProgressDialogChild_h
#include "mozilla/embedding/PPrintProgressDialogChild.h"
#include "nsIPrintProgressParams.h"
#include "nsIWebProgressListener.h"
class nsIObserver;
namespace mozilla {
namespace embedding {
class PrintProgressDialogChild MOZ_FINAL : public PPrintProgressDialogChild,
public nsIWebProgressListener,
public nsIPrintProgressParams
{
NS_DECL_ISUPPORTS
NS_DECL_NSIWEBPROGRESSLISTENER
NS_DECL_NSIPRINTPROGRESSPARAMS
public:
MOZ_IMPLICIT PrintProgressDialogChild(nsIObserver* aOpenObserver);
virtual bool RecvDialogOpened();
private:
virtual ~PrintProgressDialogChild();
nsCOMPtr<nsIObserver> mOpenObserver;
nsString mDocTitle;
nsString mDocURL;
};
} // namespace embedding
} // namespace mozilla
#endif

View File

@ -0,0 +1,113 @@
/* 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 "mozilla/unused.h"
#include "nsIPrintProgressParams.h"
#include "nsIWebProgressListener.h"
#include "PrintProgressDialogParent.h"
using mozilla::unused;
namespace mozilla {
namespace embedding {
NS_IMPL_ISUPPORTS(PrintProgressDialogParent, nsIObserver)
MOZ_IMPLICIT PrintProgressDialogParent::PrintProgressDialogParent() :
mActive(true)
{
MOZ_COUNT_CTOR(PrintProgressDialogParent);
}
MOZ_IMPLICIT PrintProgressDialogParent::~PrintProgressDialogParent()
{
MOZ_COUNT_DTOR(PrintProgressDialogParent);
}
void
PrintProgressDialogParent::SetWebProgressListener(nsIWebProgressListener* aListener)
{
mWebProgressListener = aListener;
}
void
PrintProgressDialogParent::SetPrintProgressParams(nsIPrintProgressParams* aParams)
{
mPrintProgressParams = aParams;
}
bool
PrintProgressDialogParent::RecvStateChange(const long& stateFlags,
const nsresult& status)
{
if (mWebProgressListener) {
mWebProgressListener->OnStateChange(nullptr, nullptr, stateFlags, status);
}
return true;
}
bool
PrintProgressDialogParent::RecvProgressChange(const long& curSelfProgress,
const long& maxSelfProgress,
const long& curTotalProgress,
const long& maxTotalProgress)
{
if (mWebProgressListener) {
mWebProgressListener->OnProgressChange(nullptr, nullptr, curSelfProgress,
maxSelfProgress, curTotalProgress,
maxTotalProgress);
}
return true;
}
bool
PrintProgressDialogParent::RecvDocTitleChange(const nsString& newTitle)
{
if (mPrintProgressParams) {
mPrintProgressParams->SetDocTitle(newTitle.get());
}
return true;
}
bool
PrintProgressDialogParent::RecvDocURLChange(const nsString& newURL)
{
if (mPrintProgressParams) {
mPrintProgressParams->SetDocURL(newURL.get());
}
return true;
}
void
PrintProgressDialogParent::ActorDestroy(ActorDestroyReason aWhy)
{
}
bool
PrintProgressDialogParent::Recv__delete__()
{
// The child has requested that we tear down the connection, so we set a
// member to make sure we don't try to contact it after the fact.
mActive = false;
return true;
}
// nsIObserver
NS_IMETHODIMP
PrintProgressDialogParent::Observe(nsISupports *aSubject, const char *aTopic,
const char16_t *aData)
{
if (mActive) {
unused << SendDialogOpened();
} else {
NS_WARNING("The print progress dialog finished opening, but communications "
"with the child have been closed.");
}
return NS_OK;
}
} // namespace embedding
} // namespace mozilla

View File

@ -0,0 +1,64 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_embedding_PrintProgressDialogParent_h
#define mozilla_embedding_PrintProgressDialogParent_h
#include "mozilla/embedding/PPrintProgressDialogParent.h"
#include "nsIObserver.h"
class nsIPrintProgressParams;
class nsIWebProgressListener;
namespace mozilla {
namespace embedding {
class PrintProgressDialogParent MOZ_FINAL : public PPrintProgressDialogParent,
public nsIObserver
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
MOZ_IMPLICIT PrintProgressDialogParent();
void SetWebProgressListener(nsIWebProgressListener* aListener);
void SetPrintProgressParams(nsIPrintProgressParams* aParams);
virtual bool
RecvStateChange(
const long& stateFlags,
const nsresult& status);
virtual bool
RecvProgressChange(
const long& curSelfProgress,
const long& maxSelfProgress,
const long& curTotalProgress,
const long& maxTotalProgress);
virtual bool
RecvDocTitleChange(const nsString& newTitle);
virtual bool
RecvDocURLChange(const nsString& newURL);
virtual void
ActorDestroy(ActorDestroyReason aWhy);
virtual bool
Recv__delete__();
private:
virtual ~PrintProgressDialogParent();
nsCOMPtr<nsIWebProgressListener> mWebProgressListener;
nsCOMPtr<nsIPrintProgressParams> mPrintProgressParams;
bool mActive;
};
} // namespace embedding
} // namespace mozilla
#endif

View File

@ -10,12 +10,13 @@
#include "nsIDocument.h"
#include "nsIDOMWindow.h"
#include "nsIPrintingPromptService.h"
#include "nsIPrintOptions.h"
#include "nsIPrintProgressParams.h"
#include "nsIServiceManager.h"
#include "nsIWebProgressListener.h"
#include "PrintingParent.h"
#include "nsIPrintOptions.h"
#include "PrintDataUtils.h"
#include "PrintProgressDialogParent.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -24,24 +25,14 @@ namespace mozilla {
namespace embedding {
bool
PrintingParent::RecvShowProgress(PBrowserParent* parent,
const bool& isForPrinting)
PPrintProgressDialogParent* printProgressDialog,
const bool& isForPrinting,
bool* notifyOnOpen,
bool* success)
{
TabParent* tabParent = static_cast<TabParent*>(parent);
if (!tabParent) {
return true;
}
*success = false;
nsCOMPtr<Element> frameElement = tabParent->GetOwnerElement();
if (!frameElement) {
return true;
}
nsCOMPtr<nsIContent> frame(do_QueryInterface(frameElement));
if (!frame) {
return true;
}
nsCOMPtr<nsIDOMWindow> parentWin = do_QueryInterface(frame->OwnerDoc()->GetWindow());
nsCOMPtr<nsIDOMWindow> parentWin = DOMWindowFromBrowserParent(parent);
if (!parentWin) {
return true;
}
@ -52,18 +43,24 @@ PrintingParent::RecvShowProgress(PBrowserParent* parent,
return true;
}
PrintProgressDialogParent* dialogParent =
static_cast<PrintProgressDialogParent*>(printProgressDialog);
nsCOMPtr<nsIObserver> observer = do_QueryInterface(dialogParent);
nsCOMPtr<nsIWebProgressListener> printProgressListener;
nsCOMPtr<nsIPrintProgressParams> printProgressParams;
// TODO: What do I do with this thing?
bool doNotify = false;
nsresult rv = pps->ShowProgress(parentWin, nullptr, nullptr, observer,
isForPrinting,
getter_AddRefs(printProgressListener),
getter_AddRefs(printProgressParams),
notifyOnOpen);
NS_ENSURE_SUCCESS(rv, true);
pps->ShowProgress(parentWin, nullptr, nullptr, nullptr,
isForPrinting,
getter_AddRefs(printProgressListener),
getter_AddRefs(printProgressParams),
&doNotify);
dialogParent->SetWebProgressListener(printProgressListener);
dialogParent->SetPrintProgressParams(printProgressParams);
*success = true;
return true;
}
@ -75,28 +72,12 @@ PrintingParent::RecvShowPrintDialog(PBrowserParent* parent,
{
*success = false;
TabParent* tabParent = static_cast<TabParent*>(parent);
if (!tabParent) {
return true;
}
nsCOMPtr<Element> frameElement = tabParent->GetOwnerElement();
if (!frameElement) {
return true;
}
nsCOMPtr<nsIContent> frame(do_QueryInterface(frameElement));
if (!frame) {
return true;
}
nsCOMPtr<nsIDOMWindow> parentWin = do_QueryInterface(frame->OwnerDoc()->GetWindow());
nsCOMPtr<nsIDOMWindow> parentWin = DOMWindowFromBrowserParent(parent);
if (!parentWin) {
return true;
}
nsCOMPtr<nsIPrintingPromptService> pps(do_GetService("@mozilla.org/embedcomp/printingprompt-service;1"));
if (!pps) {
return true;
}
@ -130,11 +111,61 @@ PrintingParent::RecvShowPrintDialog(PBrowserParent* parent,
return true;
}
PPrintProgressDialogParent*
PrintingParent::AllocPPrintProgressDialogParent()
{
PrintProgressDialogParent* actor = new PrintProgressDialogParent();
NS_ADDREF(actor); // De-ref'd in the __delete__ handler for
// PrintProgressDialogParent.
return actor;
}
bool
PrintingParent::DeallocPPrintProgressDialogParent(PPrintProgressDialogParent* doomed)
{
// We can't just delete the PrintProgressDialogParent since somebody might
// still be holding a reference to it as nsIObserver, so just decrement the
// refcount instead.
PrintProgressDialogParent* actor = static_cast<PrintProgressDialogParent*>(doomed);
NS_RELEASE(actor);
return true;
}
void
PrintingParent::ActorDestroy(ActorDestroyReason aWhy)
{
}
nsIDOMWindow*
PrintingParent::DOMWindowFromBrowserParent(PBrowserParent* parent)
{
if (!parent) {
return nullptr;
}
TabParent* tabParent = static_cast<TabParent*>(parent);
if (!tabParent) {
return nullptr;
}
nsCOMPtr<Element> frameElement = tabParent->GetOwnerElement();
if (!frameElement) {
return nullptr;
}
nsCOMPtr<nsIContent> frame(do_QueryInterface(frameElement));
if (!frame) {
return nullptr;
}
nsCOMPtr<nsIDOMWindow> parentWin = do_QueryInterface(frame->OwnerDoc()->GetWindow());
if (!parentWin) {
return nullptr;
}
return parentWin;
}
MOZ_IMPLICIT PrintingParent::PrintingParent()
{
MOZ_COUNT_CTOR(PrintingParent);

View File

@ -7,28 +7,45 @@
#ifndef mozilla_embedding_PrintingParent_h
#define mozilla_embedding_PrintingParent_h
#include "mozilla/embedding/PPrintingParent.h"
#include "mozilla/dom/PBrowserParent.h"
#include "mozilla/embedding/PPrintingParent.h"
#include "mozilla/embedding/PPrintProgressDialogParent.h"
class nsIDOMWindow;
namespace mozilla {
namespace embedding {
class PrintingParent : public PPrintingParent
class PrintingParent MOZ_FINAL : public PPrintingParent
{
public:
virtual bool
RecvShowProgress(PBrowserParent* parent,
const bool& isForPrinting);
PPrintProgressDialogParent* printProgressDialog,
const bool& isForPrinting,
bool* notifyOnOpen,
bool* success);
virtual bool
RecvShowPrintDialog(PBrowserParent* parent,
const PrintData& initSettings,
PrintData* retVal,
bool* success);
virtual PPrintProgressDialogParent*
AllocPPrintProgressDialogParent();
virtual bool
DeallocPPrintProgressDialogParent(PPrintProgressDialogParent* aActor);
virtual void
ActorDestroy(ActorDestroyReason aWhy);
MOZ_IMPLICIT PrintingParent();
virtual ~PrintingParent();
private:
nsIDOMWindow*
DOMWindowFromBrowserParent(PBrowserParent* parent);
};
} // namespace embedding
} // namespace mozilla

View File

@ -12,10 +12,13 @@ UNIFIED_SOURCES += [
'nsPrintingPromptServiceProxy.cpp',
'PrintDataUtils.cpp',
'PrintingParent.cpp',
'PrintProgressDialogChild.cpp',
'PrintProgressDialogParent.cpp',
]
IPDL_SOURCES += [
'PPrinting.ipdl',
'PPrintProgressDialog.ipdl',
]
include('/ipc/chromium/chromium-config.mozbuild')

View File

@ -9,11 +9,12 @@
#include "mozilla/unused.h"
#include "nsIDocShell.h"
#include "nsIDocShellTreeOwner.h"
#include "nsIPrintingPromptService.h"
#include "nsPIDOMWindow.h"
#include "nsPrintingPromptServiceProxy.h"
#include "nsIPrintingPromptService.h"
#include "PrintDataUtils.h"
#include "nsPrintOptionsImpl.h"
#include "PrintDataUtils.h"
#include "PrintProgressDialogChild.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -112,7 +113,17 @@ nsPrintingPromptServiceProxy::ShowProgress(nsIDOMWindow* parent,
nsCOMPtr<nsITabChild> tabchild = do_GetInterface(owner);
TabChild* pBrowser = static_cast<TabChild*>(tabchild.get());
mozilla::unused << SendShowProgress(pBrowser, isForPrinting);
nsRefPtr<PrintProgressDialogChild> dialogChild =
new PrintProgressDialogChild(openDialogObserver);
SendPPrintProgressDialogConstructor(dialogChild);
bool success = false;
mozilla::unused << SendShowProgress(pBrowser, dialogChild,
isForPrinting, notifyOnOpen, &success);
NS_ADDREF(*webProgressListener = dialogChild);
NS_ADDREF(*printProgressParams = dialogChild);
return NS_OK;
}
@ -122,7 +133,7 @@ nsPrintingPromptServiceProxy::ShowPageSetup(nsIDOMWindow *parent,
nsIPrintSettings *printSettings,
nsIObserver *aObs)
{
return NS_ERROR_NOT_IMPLEMENTED;
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
@ -130,6 +141,25 @@ nsPrintingPromptServiceProxy::ShowPrinterProperties(nsIDOMWindow *parent,
const char16_t *printerName,
nsIPrintSettings *printSettings)
{
return NS_ERROR_NOT_IMPLEMENTED;
return NS_ERROR_NOT_IMPLEMENTED;
}
PPrintProgressDialogChild*
nsPrintingPromptServiceProxy::AllocPPrintProgressDialogChild()
{
// The parent process will never initiate the PPrintProgressDialog
// protocol connection, so no need to provide an allocator here.
NS_NOTREACHED("Allocator for PPrintProgressDialogChild should not be "
"called on nsPrintingPromptServiceProxy.");
return nullptr;
}
bool
nsPrintingPromptServiceProxy::DeallocPPrintProgressDialogChild(PPrintProgressDialogChild* aActor)
{
// The parent process will never initiate the PPrintProgressDialog
// protocol connection, so no need to provide an deallocator here.
NS_NOTREACHED("Deallocator for PPrintProgressDialogChild should not be "
"called on nsPrintingPromptServiceProxy.");
return false;
}

View File

@ -21,6 +21,12 @@ public:
NS_DECL_ISUPPORTS
NS_DECL_NSIPRINTINGPROMPTSERVICE
virtual PPrintProgressDialogChild*
AllocPPrintProgressDialogChild();
virtual bool
DeallocPPrintProgressDialogChild(PPrintProgressDialogChild* aActor);
};
#endif