--- a/content/base/src/nsFrameLoader.cpp
+++ b/content/base/src/nsFrameLoader.cpp
@@ -993,17 +993,17 @@ nsFrameLoader::Destroy()
doc->SetSubDocumentFor(mOwnerContent, nsnull);
}
mOwnerContent = nsnull;
}
#ifdef MOZ_IPC
if (mChildProcess) {
mChildProcess->SetOwnerElement(nsnull);
- ContentProcessParent::GetSingleton()->SendPIFrameEmbeddingDestructor(mChildProcess);
+ PIFrameEmbeddingParent::Send__delete__(mChildProcess);
mChildProcess = nsnull;
}
#endif
// Let the tree owner know we're gone.
if (mIsTopLevelContent) {
nsCOMPtr<nsIDocShellTreeItem> ourItem = do_QueryInterface(mDocShell);
if (ourItem) {
--- a/content/canvas/public/DocumentRendererParent.h
+++ b/content/canvas/public/DocumentRendererParent.h
@@ -52,16 +52,19 @@ public:
DocumentRendererParent();
virtual ~DocumentRendererParent();
void SetCanvasContext(nsICanvasRenderingContextInternal* aCanvas,
gfxContext* ctx);
void DrawToCanvas(PRUint32 aWidth, PRUint32 aHeight,
const nsCString& aData);
+ virtual bool Recv__delete__(const PRUint32& w, const PRUint32& h,
+ const nsCString& data);
+
private:
nsCOMPtr<nsICanvasRenderingContextInternal> mCanvas;
nsRefPtr<gfxContext> mCanvasContext;
DISALLOW_EVIL_CONSTRUCTORS(DocumentRendererParent);
};
}
--- a/content/canvas/src/DocumentRendererParent.cpp
+++ b/content/canvas/src/DocumentRendererParent.cpp
@@ -70,8 +70,16 @@ void DocumentRendererParent::DrawToCanva
mCanvasContext->Fill();
// get rid of the pattern surface ref, because aData is very likely to go away shortly
mCanvasContext->SetColor(gfxRGBA(1,1,1,1));
gfxRect damageRect = mCanvasContext->UserToDevice(gfxRect(0, 0, aWidth, aHeight));
mCanvas->Redraw(damageRect);
}
+
+bool
+DocumentRendererParent::Recv__delete__(const PRUint32& w, const PRUint32& h,
+ const nsCString& data)
+{
+ DrawToCanvas(w, h, data);
+ return true;
+}
--- a/dom/ipc/ContentProcessParent.cpp
+++ b/dom/ipc/ContentProcessParent.cpp
@@ -93,17 +93,17 @@ TestShellParent*
ContentProcessParent::CreateTestShell()
{
return static_cast<TestShellParent*>(SendPTestShellConstructor());
}
bool
ContentProcessParent::DestroyTestShell(TestShellParent* aTestShell)
{
- return SendPTestShellDestructor(aTestShell);
+ return PTestShellParent::Send__delete__(aTestShell);
}
ContentProcessParent::ContentProcessParent()
: mMonitor("ContentProcessParent::mMonitor")
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
mSubprocess = new GeckoChildProcessHost(GeckoProcessType_Content, this);
mSubprocess->AsyncLaunch();
--- a/dom/ipc/PContentProcess.ipdl
+++ b/dom/ipc/PContentProcess.ipdl
@@ -48,22 +48,19 @@ namespace dom {
sync protocol PContentProcess
{
manages PIFrameEmbedding;
manages PTestShell;
manages PNecko;
child:
PIFrameEmbedding();
- ~PIFrameEmbedding();
PTestShell();
- ~PTestShell();
Quit();
parent:
PNecko();
- ~PNecko();
};
}
}
--- a/dom/ipc/PDocumentRenderer.ipdl
+++ b/dom/ipc/PDocumentRenderer.ipdl
@@ -38,12 +38,15 @@
include protocol "PIFrameEmbedding.ipdl";
namespace mozilla {
namespace ipc {
protocol PDocumentRenderer
{
manager PIFrameEmbedding;
+
+parent:
+ __delete__(PRUint32 w, PRUint32 h, nsCString data);
};
} // namespace ipc
} // namespace mozilla
--- a/dom/ipc/PIFrameEmbedding.ipdl
+++ b/dom/ipc/PIFrameEmbedding.ipdl
@@ -38,29 +38,30 @@
* ***** END LICENSE BLOCK ***** */
include protocol "PContentProcess.ipdl";
include protocol "PDocumentRenderer.ipdl";
include "mozilla/TabTypes.h";
include "TabMessageUtils.h";
-using PRUint32;
-using PRInt32;
using MagicWindowHandle;
using RemoteDOMEvent;
namespace mozilla {
namespace dom {
async protocol PIFrameEmbedding
{
manager PContentProcess;
manages PDocumentRenderer;
+child:
+ __delete__();
+
parent:
/**
* When child sends this message, parent should move focus to
* the next or previous focusable element.
*/
moveFocus(bool forward);
sendEvent(RemoteDOMEvent aEvent);
@@ -91,16 +92,12 @@ child:
bool aIgnoreRootScrollFrame);
/**
* Activate event forwarding from client to parent.
*/
activateFrameEvent(nsString aType, bool capture);
PDocumentRenderer(PRInt32 x, PRInt32 y, PRInt32 w, PRInt32 h, nsString bgcolor, PRUint32 flags, bool flush);
-
-parent:
-
- ~PDocumentRenderer(PRUint32 w, PRUint32 h, nsCString data);
};
}
}
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -356,23 +356,19 @@ TabChild::AllocPDocumentRenderer(
const nsString& bgcolor,
const PRUint32& flags,
const bool& flush)
{
return new mozilla::ipc::DocumentRendererChild();
}
bool
-TabChild::DeallocPDocumentRenderer(
- mozilla::ipc::PDocumentRendererChild* __a,
- const PRUint32& w,
- const PRUint32& h,
- const nsCString& data)
+TabChild::DeallocPDocumentRenderer(PDocumentRendererChild* actor)
{
- delete __a;
+ delete actor;
return true;
}
bool
TabChild::RecvPDocumentRendererConstructor(
mozilla::ipc::PDocumentRendererChild *__a,
const PRInt32& aX,
const PRInt32& aY,
@@ -397,17 +393,17 @@ TabChild::RecvPDocumentRendererConstruct
PRUint32 width, height;
nsCString data;
bool ret = render->RenderDocument(window, aX, aY, aW, aH, bgcolor, flags, flush,
width, height, data);
if (!ret)
return true; // silently ignore
- return SendPDocumentRendererDestructor(__a, width, height, data);
+ return PDocumentRendererChild::Send__delete__(__a, width, height, data);
}
bool
TabChild::RecvactivateFrameEvent(const nsString& aType, const bool& capture)
{
nsCOMPtr<nsPIDOMWindow> window = do_GetInterface(mWebNav);
NS_ENSURE_TRUE(window, true);
nsCOMPtr<nsIDOMEventTarget> chromeHandler =
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -100,21 +100,17 @@ public:
virtual mozilla::ipc::PDocumentRendererChild* AllocPDocumentRenderer(
const PRInt32& x,
const PRInt32& y,
const PRInt32& w,
const PRInt32& h,
const nsString& bgcolor,
const PRUint32& flags,
const bool& flush);
- virtual bool DeallocPDocumentRenderer(
- mozilla::ipc::PDocumentRendererChild* __a,
- const PRUint32& w,
- const PRUint32& h,
- const nsCString& data);
+ virtual bool DeallocPDocumentRenderer(PDocumentRendererChild* actor);
virtual bool RecvPDocumentRendererConstructor(
mozilla::ipc::PDocumentRendererChild *__a,
const PRInt32& x,
const PRInt32& y,
const PRInt32& w,
const PRInt32& h,
const nsString& bgcolor,
const PRUint32& flags,
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -118,32 +118,19 @@ mozilla::ipc::PDocumentRendererParent*
TabParent::AllocPDocumentRenderer(const PRInt32& x,
const PRInt32& y, const PRInt32& w, const PRInt32& h, const nsString& bgcolor,
const PRUint32& flags, const bool& flush)
{
return new DocumentRendererParent();
}
bool
-TabParent::DeallocPDocumentRenderer(mozilla::ipc::PDocumentRendererParent* __a,
- const PRUint32& w, const PRUint32& h, const nsCString& data)
+TabParent::DeallocPDocumentRenderer(PDocumentRendererParent* actor)
{
- NS_ENSURE_ARG_POINTER(__a);
- delete __a;
- return true;
-}
-
-bool
-TabParent::RecvPDocumentRendererDestructor(PDocumentRendererParent* __a,
- const PRUint32& w, const PRUint32& h, const nsCString& data)
-{
- NS_ENSURE_ARG_POINTER(__a);
- DocumentRendererParent *renderer = static_cast<DocumentRendererParent *>(__a);
- renderer->DrawToCanvas(w, h, data);
-
+ delete actor;
return true;
}
void
TabParent::SendMouseEvent(const nsAString& aType, float aX, float aY,
PRInt32 aButton, PRInt32 aClickCount,
PRInt32 aModifiers, PRBool aIgnoreRootScrollFrame)
{
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -69,26 +69,17 @@ public:
virtual mozilla::ipc::PDocumentRendererParent* AllocPDocumentRenderer(
const PRInt32& x,
const PRInt32& y,
const PRInt32& w,
const PRInt32& h,
const nsString& bgcolor,
const PRUint32& flags,
const bool& flush);
- virtual bool DeallocPDocumentRenderer(
- mozilla::ipc::PDocumentRendererParent* __a,
- const PRUint32& w,
- const PRUint32& h,
- const nsCString& data);
- virtual bool RecvPDocumentRendererDestructor(
- mozilla::ipc::PDocumentRendererParent* __a,
- const PRUint32& w,
- const PRUint32& h,
- const nsCString& data);
+ virtual bool DeallocPDocumentRenderer(PDocumentRendererParent* actor);
protected:
nsIDOMElement* mFrameElement;
};
} // namespace dom
} // namespace mozilla
#endif
--- a/dom/plugins/BrowserStreamChild.cpp
+++ b/dom/plugins/BrowserStreamChild.cpp
@@ -122,16 +122,26 @@ BrowserStreamChild::AnswerNPP_StreamAsFi
if (mClosed)
return true;
mInstance->mPluginIface->asfile(&mInstance->mData, &mStream,
fname.get());
return true;
}
+bool
+BrowserStreamChild::Answer__delete__(const NPError& reason,
+ const bool& artificial)
+{
+ AssertPluginThread();
+ if (!artificial)
+ NPP_DestroyStream(reason);
+ return true;
+}
+
NPError
BrowserStreamChild::NPN_RequestRead(NPByteRange* aRangeList)
{
AssertPluginThread();
IPCByteRanges ranges;
for (; aRangeList; aRangeList = aRangeList->next) {
IPCByteRange br = {aRangeList->offset, aRangeList->length};
--- a/dom/plugins/BrowserStreamChild.h
+++ b/dom/plugins/BrowserStreamChild.h
@@ -66,16 +66,19 @@ public:
virtual bool AnswerNPP_WriteReady(const int32_t& newlength,
int32_t *size);
virtual bool AnswerNPP_Write(const int32_t& offset,
const Buffer& data,
int32_t* consumed);
virtual bool AnswerNPP_StreamAsFile(const nsCString& fname);
+ virtual bool Answer__delete__(const NPError& reason,
+ const bool& artificial);
+
void EnsureCorrectInstance(PluginInstanceChild* i)
{
if (i != mInstance)
NS_RUNTIMEABORT("Incorrect stream instance");
}
void EnsureCorrectStream(NPStream* s)
{
--- a/dom/plugins/BrowserStreamParent.cpp
+++ b/dom/plugins/BrowserStreamParent.cpp
@@ -39,16 +39,25 @@ BrowserStreamParent::AnswerNPN_RequestRe
rp[i].next = &rp[i + 1];
}
rp[ranges.size() - 1].next = NULL;
*result = mNPP->mNPNIface->requestread(mStream, rp);
return true;
}
+bool
+BrowserStreamParent::Answer__delete__(const NPError& reason,
+ const bool& artificial)
+{
+ if (!artificial)
+ NPN_DestroyStream(reason);
+ return true;
+}
+
int32_t
BrowserStreamParent::WriteReady()
{
_MOZ_LOG(__FUNCTION__);
int32_t result;
if (!CallNPP_WriteReady(mStream->end, &result))
return -1;
--- a/dom/plugins/BrowserStreamParent.h
+++ b/dom/plugins/BrowserStreamParent.h
@@ -56,22 +56,26 @@ public:
NPStream* stream);
virtual ~BrowserStreamParent();
NS_OVERRIDE virtual bool IsBrowserStream() { return true; }
virtual bool AnswerNPN_RequestRead(const IPCByteRanges& ranges,
NPError* result);
+ virtual bool
+ Answer__delete__(const NPError& reason, const bool& artificial);
+
int32_t WriteReady();
int32_t Write(int32_t offset, int32_t len, void* buffer);
void StreamAsFile(const char* fname);
+
+private:
NPError NPN_DestroyStream(NPError reason);
-private:
PluginInstanceParent* mNPP;
NPStream* mStream;
};
} // namespace plugins
} // namespace mozilla
#endif
--- a/dom/plugins/PBrowserStream.ipdl
+++ b/dom/plugins/PBrowserStream.ipdl
@@ -38,16 +38,17 @@
include protocol "PPluginInstance.ipdl";
include "mozilla/plugins/PluginMessageUtils.h";
using mozilla::plugins::Buffer;
using mozilla::plugins::IPCByteRanges;
using NPError;
+using NPReason;
namespace mozilla {
namespace plugins {
/**
* NPBrowserStream represents a NPStream sent from the browser to the plugin.
*/
@@ -63,12 +64,20 @@ child:
Buffer data)
returns (int32_t consumed);
rpc NPP_StreamAsFile(nsCString fname);
parent:
rpc NPN_RequestRead(IPCByteRanges ranges)
returns (NPError result);
+
+both:
+ /**
+ * ~PBrowserStream is for both NPN_DestroyStream and NPP_DestroyStream.
+ * @param artificial True when the stream is closed as a by-product of
+ * some other call (such as a failure in NPP_Write).
+ */
+ rpc __delete__(NPReason reason, bool artificial);
};
} // namespace plugins
} // namespace mozilla
--- a/dom/plugins/PPluginInstance.ipdl
+++ b/dom/plugins/PPluginInstance.ipdl
@@ -43,32 +43,34 @@ include protocol "PBrowserStream.ipdl";
include protocol "PPluginStream.ipdl";
include protocol "PStreamNotify.ipdl";
include "mozilla/plugins/PluginMessageUtils.h";
using NPError;
using NPRemoteWindow;
using NPRemoteEvent;
-using NPReason;
using NPRect;
namespace mozilla {
namespace plugins {
rpc protocol PPluginInstance
{
manager PPluginModule;
manages PPluginScriptableObject;
manages PBrowserStream;
manages PPluginStream;
manages PStreamNotify;
child:
+ rpc __delete__()
+ returns (NPError rv);
+
rpc NPP_SetWindow(NPRemoteWindow window)
returns (NPError rv);
rpc NPP_GetValue_NPPVpluginWindow()
returns (bool value, NPError result);
rpc NPP_GetValue_NPPVpluginTransparent()
returns (bool value, NPError result);
// this message is not used on non-X platforms
@@ -114,56 +116,32 @@ parent:
async NPN_InvalidateRect(NPRect rect);
rpc NPN_PushPopupsEnabledState(bool aState)
returns (bool aSuccess);
rpc NPN_PopPopupsEnabledState()
returns (bool aSuccess);
-child:
- /**
- * Represents NPP_URLNotify
- */
- rpc ~PStreamNotify(NPReason reason);
-
both:
rpc PPluginScriptableObject();
- rpc ~PPluginScriptableObject();
child:
/* NPP_NewStream */
rpc PBrowserStream(nsCString url,
uint32_t length,
uint32_t lastmodified,
nullable PStreamNotify notifyData,
nsCString headers,
nsCString mimeType,
bool seekable)
returns (NPError rv,
uint16_t stype);
-both:
- /**
- * ~PBrowserStream is for both NPN_DestroyStream and NPP_DestroyStream.
- * @param artificial True when the stream is closed as a by-product of
- * some other call (such as a failure in NPP_Write).
- */
- rpc ~PBrowserStream(NPReason reason,
- bool artificial);
-
parent:
/* NPN_NewStream */
rpc PPluginStream(nsCString mimeType,
nsCString target)
returns (NPError result);
-
-both:
- /**
- * ~PPluginStream is for both NPN_DestroyStream and NPP_DestroyStream.
- * @param artificial True when the stream is closed as a by-product of
- * some other call (such as a failure in NPN_Write).
- */
- rpc ~PPluginStream(NPReason reason, bool artificial);
};
} // namespace plugins
} // namespace mozilla
--- a/dom/plugins/PPluginModule.ipdl
+++ b/dom/plugins/PPluginModule.ipdl
@@ -58,19 +58,16 @@ child:
returns (NPError rv);
rpc PPluginInstance(nsCString aMimeType,
uint16_t aMode,
nsCString[] aNames,
nsCString[] aValues)
returns (NPError rv);
- rpc ~PPluginInstance()
- returns (NPError rv);
-
rpc NP_Shutdown()
returns (NPError rv);
parent:
rpc NPN_UserAgent()
returns (nsCString userAgent);
sync NPN_GetStringIdentifier(nsCString aString)
--- a/dom/plugins/PPluginScriptableObject.ipdl
+++ b/dom/plugins/PPluginScriptableObject.ipdl
@@ -59,16 +59,19 @@ union Variant {
nsCString;
nullable PPluginScriptableObject;
};
rpc protocol PPluginScriptableObject
{
manager PPluginInstance;
+both:
+ rpc __delete__();
+
parent:
rpc NPN_Evaluate(nsCString aScript)
returns (Variant aResult,
bool aSuccess);
both:
// NPClass methods
rpc Invalidate();
--- a/dom/plugins/PPluginStream.ipdl
+++ b/dom/plugins/PPluginStream.ipdl
@@ -36,26 +36,35 @@
* ***** END LICENSE BLOCK ***** */
include protocol "PPluginInstance.ipdl";
include "mozilla/plugins/PluginMessageUtils.h";
using mozilla::plugins::Buffer;
using NPError;
+using NPReason;
namespace mozilla {
namespace plugins {
/**
* PPluginStream represents an NPStream sent from the plugin to the browser.
*/
rpc protocol PPluginStream
{
manager PPluginInstance;
parent:
rpc NPN_Write(Buffer data) returns (int32_t written);
+
+both:
+ /**
+ * ~PPluginStream is for both NPN_DestroyStream and NPP_DestroyStream.
+ * @param artificial True when the stream is closed as a by-product of
+ * some other call (such as a failure in NPN_Write).
+ */
+ rpc __delete__(NPReason reason, bool artificial);
};
} // namespace plugins
} // namespace mozilla
--- a/dom/plugins/PStreamNotify.ipdl
+++ b/dom/plugins/PStreamNotify.ipdl
@@ -1,17 +1,27 @@
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
include protocol "PPluginInstance.ipdl";
+include "npapi.h";
+
+using NPReason;
+
namespace mozilla {
namespace plugins {
/**
* This empty protocol exists only to be constructed and destroyed.
*/
rpc protocol PStreamNotify
{
manager PPluginInstance;
+
+child:
+ /**
+ * Represents NPP_URLNotify
+ */
+ rpc __delete__(NPReason reason);
};
} // namespace plugins
} // namespace mozilla
--- a/dom/plugins/PluginInstanceChild.cpp
+++ b/dom/plugins/PluginInstanceChild.cpp
@@ -82,16 +82,24 @@ PluginInstanceChild::PluginInstanceChild
PluginInstanceChild::~PluginInstanceChild()
{
#if defined(OS_WIN)
DestroyPluginWindow();
#endif
}
+bool
+PluginInstanceChild::Answer__delete__(NPError* rv)
+{
+ return static_cast<PluginModuleChild*>(Manager())->
+ PluginInstanceDestroyed(this, rv);
+}
+
+
NPError
PluginInstanceChild::NPN_GetValue(NPNVariable aVar,
void* aValue)
{
printf ("[PluginInstanceChild] NPN_GetValue(%s)\n",
NPNVariableToString(aVar));
AssertPluginThread();
@@ -716,17 +724,17 @@ PluginInstanceChild::AllocPPluginScripta
*object = new PluginScriptableObjectChild();
NS_ENSURE_TRUE(*object, nsnull);
return object->get();
}
bool
PluginInstanceChild::DeallocPPluginScriptableObject(
- PPluginScriptableObjectChild* aObject)
+ PPluginScriptableObjectChild* aObject)
{
AssertPluginThread();
PluginScriptableObjectChild* object =
reinterpret_cast<PluginScriptableObjectChild*>(aObject);
NPObject* npobject = object->GetObject();
if (npobject &&
@@ -783,61 +791,34 @@ PluginInstanceChild::AllocPBrowserStream
uint16_t *stype)
{
AssertPluginThread();
return new BrowserStreamChild(this, url, length, lastmodified, notifyData,
headers, mimeType, seekable, rv, stype);
}
bool
-PluginInstanceChild::AnswerPBrowserStreamDestructor(PBrowserStreamChild* stream,
- const NPError& reason,
- const bool& artificial)
-{
- AssertPluginThread();
- if (!artificial)
- static_cast<BrowserStreamChild*>(stream)->NPP_DestroyStream(reason);
- return true;
-}
-
-bool
-PluginInstanceChild::DeallocPBrowserStream(PBrowserStreamChild* stream,
- const NPError& reason,
- const bool& artificial)
+PluginInstanceChild::DeallocPBrowserStream(PBrowserStreamChild* stream)
{
AssertPluginThread();
delete stream;
return true;
}
PPluginStreamChild*
PluginInstanceChild::AllocPPluginStream(const nsCString& mimeType,
const nsCString& target,
NPError* result)
{
NS_RUNTIMEABORT("not callable");
return NULL;
}
bool
-PluginInstanceChild::AnswerPPluginStreamDestructor(PPluginStreamChild* stream,
- const NPReason& reason,
- const bool& artificial)
-{
- AssertPluginThread();
- if (!artificial) {
- static_cast<PluginStreamChild*>(stream)->NPP_DestroyStream(reason);
- }
- return true;
-}
-
-bool
-PluginInstanceChild::DeallocPPluginStream(PPluginStreamChild* stream,
- const NPError& reason,
- const bool& artificial)
+PluginInstanceChild::DeallocPPluginStream(PPluginStreamChild* stream)
{
AssertPluginThread();
delete stream;
return true;
}
PStreamNotifyChild*
PluginInstanceChild::AllocPStreamNotify(const nsCString& url,
@@ -848,32 +829,37 @@ PluginInstanceChild::AllocPStreamNotify(
NPError* result)
{
AssertPluginThread();
NS_RUNTIMEABORT("not reached");
return NULL;
}
bool
-PluginInstanceChild::AnswerPStreamNotifyDestructor(PStreamNotifyChild* notifyData,
- const NPReason& reason)
+StreamNotifyChild::Answer__delete__(const NPReason& reason)
{
AssertPluginThread();
+ return static_cast<PluginInstanceChild*>(Manager())
+ ->NotifyStream(this, reason);
+}
- StreamNotifyChild* sn = static_cast<StreamNotifyChild*>(notifyData);
- if (sn->mClosure)
- mPluginIface->urlnotify(&mData, sn->mURL.get(), reason, sn->mClosure);
-
+bool
+PluginInstanceChild::NotifyStream(StreamNotifyChild* notifyData,
+ NPReason reason)
+{
+ if (notifyData->mClosure)
+ mPluginIface->urlnotify(&mData, notifyData->mURL.get(), reason,
+ notifyData->mClosure);
return true;
}
bool
-PluginInstanceChild::DeallocPStreamNotify(PStreamNotifyChild* notifyData,
- const NPReason& reason)
+PluginInstanceChild::DeallocPStreamNotify(PStreamNotifyChild* notifyData)
{
+ AssertPluginThread();
delete notifyData;
return true;
}
PluginScriptableObjectChild*
PluginInstanceChild::GetActorForNPObject(NPObject* aObject)
{
AssertPluginThread();
@@ -909,24 +895,24 @@ PluginInstanceChild::GetActorForNPObject
}
NPError
PluginInstanceChild::NPN_NewStream(NPMIMEType aMIMEType, const char* aWindow,
NPStream** aStream)
{
AssertPluginThread();
- PluginStreamChild* ps = new PluginStreamChild(this);
+ PluginStreamChild* ps = new PluginStreamChild();
NPError result;
CallPPluginStreamConstructor(ps, nsDependentCString(aMIMEType),
NullableString(aWindow), &result);
if (NPERR_NO_ERROR != result) {
*aStream = NULL;
- CallPPluginStreamDestructor(ps, NPERR_GENERIC_ERROR, true);
+ PPluginStreamChild::Call__delete__(ps, NPERR_GENERIC_ERROR, true);
return result;
}
*aStream = &ps->mStream;
return NPERR_NO_ERROR;
}
bool
--- a/dom/plugins/PluginInstanceChild.h
+++ b/dom/plugins/PluginInstanceChild.h
@@ -36,16 +36,17 @@
*
* ***** END LICENSE BLOCK ***** */
#ifndef dom_plugins_PluginInstanceChild_h
#define dom_plugins_PluginInstanceChild_h 1
#include "mozilla/plugins/PPluginInstanceChild.h"
#include "mozilla/plugins/PluginScriptableObjectChild.h"
+#include "mozilla/plugins/StreamNotifyChild.h"
#if defined(OS_WIN)
#include "mozilla/gfx/SharedDIBWin.h"
#endif
#include "npfunctions.h"
#include "nsAutoPtr.h"
#include "nsTArray.h"
@@ -68,16 +69,18 @@ class PluginInstanceChild : public PPlug
UINT message,
WPARAM wParam,
LPARAM lParam);
#endif
protected:
virtual bool AnswerNPP_SetWindow(const NPRemoteWindow& window, NPError* rv);
+ virtual bool Answer__delete__(NPError* rv);
+
virtual bool
AnswerNPP_GetValue_NPPVpluginWindow(bool* windowed, NPError* rv);
virtual bool
AnswerNPP_GetValue_NPPVpluginTransparent(bool* transparent, NPError* rv);
virtual bool
AnswerNPP_GetValue_NPPVpluginNeedsXEmbed(bool* needs, NPError* rv);
virtual bool
@@ -103,53 +106,34 @@ protected:
PStreamNotifyChild* notifyData,
const nsCString& headers,
const nsCString& mimeType,
const bool& seekable,
NPError* rv,
uint16_t *stype);
virtual bool
- AnswerPBrowserStreamDestructor(PBrowserStreamChild* stream,
- const NPError& reason,
- const bool& artificial);
-
- virtual bool
- DeallocPBrowserStream(PBrowserStreamChild* stream,
- const NPError& reason,
- const bool& artificial);
+ DeallocPBrowserStream(PBrowserStreamChild* stream);
virtual PPluginStreamChild*
AllocPPluginStream(const nsCString& mimeType,
const nsCString& target,
NPError* result);
virtual bool
- AnswerPPluginStreamDestructor(PPluginStreamChild* stream,
- const NPReason& reason,
- const bool& artificial);
-
- virtual bool
- DeallocPPluginStream(PPluginStreamChild* stream,
- const NPReason& reason,
- const bool& artificial);
+ DeallocPPluginStream(PPluginStreamChild* stream);
virtual PStreamNotifyChild*
AllocPStreamNotify(const nsCString& url, const nsCString& target,
const bool& post, const nsCString& buffer,
const bool& file,
NPError* result);
NS_OVERRIDE virtual bool
- AnswerPStreamNotifyDestructor(PStreamNotifyChild* notifyData,
- const NPReason& reason);
-
- NS_OVERRIDE virtual bool
- DeallocPStreamNotify(PStreamNotifyChild* notifyData,
- const NPReason& reason);
+ DeallocPStreamNotify(PStreamNotifyChild* notifyData);
public:
PluginInstanceChild(const NPPluginFuncs* aPluginIface);
virtual ~PluginInstanceChild();
bool Initialize();
void Destroy();
@@ -172,16 +156,18 @@ public:
NPN_NewStream(NPMIMEType aMIMEType, const char* aWindow,
NPStream** aStream);
// Return true if you want to send the notification to the parent process
// also.
bool
InternalInvalidateRect(NPRect* aInvalidRect);
+ bool NotifyStream(StreamNotifyChild* notifyData, NPReason reason);
+
private:
#if defined(OS_WIN)
static bool RegisterWindowClass();
bool CreatePluginWindow();
void DestroyPluginWindow();
void ReparentPluginWindow(HWND hWndParent);
void SizePluginWindow(int width, int height);
--- a/dom/plugins/PluginInstanceParent.cpp
+++ b/dom/plugins/PluginInstanceParent.cpp
@@ -109,51 +109,33 @@ PluginInstanceParent::AllocPBrowserStrea
NPError* rv,
uint16_t *stype)
{
NS_RUNTIMEABORT("Not reachable");
return NULL;
}
bool
-PluginInstanceParent::AnswerPBrowserStreamDestructor(PBrowserStreamParent* stream,
- const NPError& reason,
- const bool& artificial)
-{
- if (!artificial) {
- static_cast<BrowserStreamParent*>(stream)->NPN_DestroyStream(reason);
- }
- return true;
-}
-
-bool
-PluginInstanceParent::DeallocPBrowserStream(PBrowserStreamParent* stream,
- const NPError& reason,
- const bool& artificial)
+PluginInstanceParent::DeallocPBrowserStream(PBrowserStreamParent* stream)
{
delete stream;
return true;
}
PPluginStreamParent*
PluginInstanceParent::AllocPPluginStream(const nsCString& mimeType,
const nsCString& target,
NPError* result)
{
return new PluginStreamParent(this, mimeType, target, result);
}
bool
-PluginInstanceParent::DeallocPPluginStream(PPluginStreamParent* stream,
- const NPError& reason,
- const bool& artificial)
+PluginInstanceParent::DeallocPPluginStream(PPluginStreamParent* stream)
{
- if (!artificial) {
- static_cast<PluginStreamParent*>(stream)->NPN_DestroyStream(reason);
- }
delete stream;
return true;
}
bool
PluginInstanceParent::AnswerNPN_GetValue_NPNVjavascriptEnabledBool(
bool* value,
NPError* result)
@@ -305,24 +287,23 @@ PluginInstanceParent::AnswerPStreamNotif
NullableStringGet(url),
NullableStringGet(target),
buffer.Length(),
NullableStringGet(buffer),
file, actor);
}
if (*result != NPERR_NO_ERROR)
- CallPStreamNotifyDestructor(actor, NPERR_GENERIC_ERROR);
+ PStreamNotifyParent::Call__delete__(actor, NPERR_GENERIC_ERROR);
return true;
}
bool
-PluginInstanceParent::DeallocPStreamNotify(PStreamNotifyParent* notifyData,
- const NPReason& reason)
+PluginInstanceParent::DeallocPStreamNotify(PStreamNotifyParent* notifyData)
{
delete notifyData;
return true;
}
bool
PluginInstanceParent::RecvNPN_InvalidateRect(const NPRect& rect)
{
@@ -542,43 +523,43 @@ PluginInstanceParent::NPP_NewStream(NPMI
stream->lastmodified,
static_cast<PStreamNotifyParent*>(stream->notifyData),
NullableString(stream->headers),
NullableString(type), seekable,
&err, stype))
return NPERR_GENERIC_ERROR;
if (NPERR_NO_ERROR != err)
- CallPBrowserStreamDestructor(bs, NPERR_GENERIC_ERROR, true);
+ PBrowserStreamParent::Call__delete__(bs, NPERR_GENERIC_ERROR, true);
return err;
}
NPError
PluginInstanceParent::NPP_DestroyStream(NPStream* stream, NPReason reason)
{
_MOZ_LOG(__FUNCTION__);
AStream* s = static_cast<AStream*>(stream->pdata);
if (s->IsBrowserStream()) {
BrowserStreamParent* sp =
static_cast<BrowserStreamParent*>(s);
if (sp->mNPP != this)
NS_RUNTIMEABORT("Mismatched plugin data");
- CallPBrowserStreamDestructor(sp, reason, false);
+ PBrowserStreamParent::Call__delete__(sp, reason, false);
return NPERR_NO_ERROR;
}
else {
PluginStreamParent* sp =
static_cast<PluginStreamParent*>(s);
if (sp->mInstance != this)
NS_RUNTIMEABORT("Mismatched plugin data");
- CallPPluginStreamDestructor(sp, reason, false);
+ PPluginStreamParent::Call__delete__(sp, reason, false);
return NPERR_NO_ERROR;
}
}
PPluginScriptableObjectParent*
PluginInstanceParent::AllocPPluginScriptableObject()
{
nsAutoPtr<PluginScriptableObjectParent>* object =
@@ -640,17 +621,17 @@ PluginInstanceParent::AnswerPPluginScrip
void
PluginInstanceParent::NPP_URLNotify(const char* url, NPReason reason,
void* notifyData)
{
_MOZ_LOG(__FUNCTION__);
PStreamNotifyParent* streamNotify =
static_cast<PStreamNotifyParent*>(notifyData);
- CallPStreamNotifyDestructor(streamNotify, reason);
+ PStreamNotifyParent::Call__delete__(streamNotify, reason);
}
PluginScriptableObjectParent*
PluginInstanceParent::GetActorForNPObject(NPObject* aObject)
{
NS_ASSERTION(aObject, "Null pointer!");
if (aObject->_class == PluginScriptableObjectParent::GetClass()) {
--- a/dom/plugins/PluginInstanceParent.h
+++ b/dom/plugins/PluginInstanceParent.h
@@ -52,17 +52,16 @@
#undef _MOZ_LOG
#define _MOZ_LOG(s) printf("[PluginInstanceParent] %s\n", s)
namespace mozilla {
namespace plugins {
class PBrowserStreamParent;
-class BrowserStreamParent;
class PluginModuleParent;
class PluginInstanceParent : public PPluginInstanceParent
{
friend class PluginModuleParent;
friend class BrowserStreamParent;
friend class PluginStreamParent;
@@ -88,36 +87,25 @@ public:
const uint32_t& length,
const uint32_t& lastmodified,
PStreamNotifyParent* notifyData,
const nsCString& headers,
const nsCString& mimeType,
const bool& seekable,
NPError* rv,
uint16_t *stype);
-
virtual bool
- AnswerPBrowserStreamDestructor(PBrowserStreamParent* stream,
- const NPError& reason,
- const bool& artificial);
-
- virtual bool
- DeallocPBrowserStream(PBrowserStreamParent* stream,
- const NPError& reason,
- const bool& artificial);
+ DeallocPBrowserStream(PBrowserStreamParent* stream);
virtual PPluginStreamParent*
AllocPPluginStream(const nsCString& mimeType,
const nsCString& target,
NPError* result);
-
virtual bool
- DeallocPPluginStream(PPluginStreamParent* stream,
- const NPError& reason,
- const bool& artificial);
+ DeallocPPluginStream(PPluginStreamParent* stream);
virtual bool
AnswerNPN_GetValue_NPNVjavascriptEnabledBool(bool* value, NPError* result);
virtual bool
AnswerNPN_GetValue_NPNVisOfflineBool(bool* value, NPError* result);
virtual bool
AnswerNPN_GetValue_NPNVWindowNPObject(
PPluginScriptableObjectParent** value,
@@ -154,18 +142,17 @@ public:
AnswerPStreamNotifyConstructor(PStreamNotifyParent* actor,
const nsCString& url,
const nsCString& target,
const bool& post, const nsCString& buffer,
const bool& file,
NPError* result);
virtual bool
- DeallocPStreamNotify(PStreamNotifyParent* notifyData,
- const NPReason& reason);
+ DeallocPStreamNotify(PStreamNotifyParent* notifyData);
virtual bool
RecvNPN_InvalidateRect(const NPRect& rect);
virtual bool
AnswerNPN_PushPopupsEnabledState(const bool& aState,
bool* aSuccess);
--- a/dom/plugins/PluginModuleChild.cpp
+++ b/dom/plugins/PluginModuleChild.cpp
@@ -733,22 +733,22 @@ NPError NP_CALLBACK
_MOZ_LOG(__FUNCTION__);
AssertPluginThread();
PluginInstanceChild* p = InstCast(aNPP);
AStream* s = static_cast<AStream*>(aStream->ndata);
if (s->IsBrowserStream()) {
BrowserStreamChild* bs = static_cast<BrowserStreamChild*>(s);
bs->EnsureCorrectInstance(p);
- p->CallPBrowserStreamDestructor(bs, aReason, false);
+ PBrowserStreamChild::Call__delete__(bs, aReason, false);
}
else {
PluginStreamChild* ps = static_cast<PluginStreamChild*>(s);
ps->EnsureCorrectInstance(p);
- p->CallPPluginStreamDestructor(ps, aReason, false);
+ PPluginStreamChild::Call__delete__(ps, aReason, false);
}
return NPERR_NO_ERROR;
}
void NP_CALLBACK
_status(NPP aNPP,
const char* aMessage)
{
@@ -1437,33 +1437,31 @@ PluginModuleChild::AnswerPPluginInstance
return false;
}
printf ("[PluginModuleChild] %s: returning %hd\n", __FUNCTION__, *rv);
return true;
}
bool
-PluginModuleChild::DeallocPPluginInstance(PPluginInstanceChild* aActor,
- NPError* rv)
+PluginModuleChild::DeallocPPluginInstance(PPluginInstanceChild* aActor)
{
_MOZ_LOG(__FUNCTION__);
AssertPluginThread();
delete aActor;
return true;
}
bool
-PluginModuleChild::AnswerPPluginInstanceDestructor(PPluginInstanceChild* aActor,
- NPError* rv)
+PluginModuleChild::PluginInstanceDestroyed(PluginInstanceChild* aActor,
+ NPError* rv)
{
_MOZ_LOG(__FUNCTION__);
AssertPluginThread();
- PluginInstanceChild* inst = static_cast<PluginInstanceChild*>(aActor);
- *rv = mFunctions.destroy(inst->GetNPP(), 0);
- inst->Destroy();
- inst->GetNPP()->ndata = 0;
+ *rv = mFunctions.destroy(aActor->GetNPP(), 0);
+ aActor->Destroy();
+ aActor->GetNPP()->ndata = 0;
return true;
}
--- a/dom/plugins/PluginModuleChild.h
+++ b/dom/plugins/PluginModuleChild.h
@@ -104,22 +104,17 @@ protected:
virtual PPluginInstanceChild*
AllocPPluginInstance(const nsCString& aMimeType,
const uint16_t& aMode,
const nsTArray<nsCString>& aNames,
const nsTArray<nsCString>& aValues,
NPError* rv);
virtual bool
- DeallocPPluginInstance(PPluginInstanceChild* aActor,
- NPError* rv);
-
- virtual bool
- AnswerPPluginInstanceDestructor(PPluginInstanceChild* aActor,
- NPError* rv);
+ DeallocPPluginInstance(PPluginInstanceChild* aActor);
virtual bool
AnswerPPluginInstanceConstructor(PPluginInstanceChild* aActor,
const nsCString& aMimeType,
const uint16_t& aMode,
const nsTArray<nsCString>& aNames,
const nsTArray<nsCString>& aValues,
NPError* rv);
@@ -149,16 +144,20 @@ public:
void UnregisterNPObject(NPObject* aObject);
PluginScriptableObjectChild* GetActorForNPObject(NPObject* aObject);
#ifdef DEBUG
bool NPObjectIsRegisteredForActor(PluginScriptableObjectChild* aActor);
#endif
+ bool
+ PluginInstanceDestroyed(PluginInstanceChild* aActor,
+ NPError* rv);
+
private:
bool InitGraphics();
std::string mPluginFilename;
PRLibrary* mLibrary;
nsCString mUserAgent;
// we get this from the plugin
--- a/dom/plugins/PluginModuleParent.cpp
+++ b/dom/plugins/PluginModuleParent.cpp
@@ -92,22 +92,20 @@ PluginModuleParent::AllocPPluginInstance
const nsTArray<nsCString>& aValues,
NPError* rv)
{
NS_ERROR("Not reachable!");
return NULL;
}
bool
-PluginModuleParent::DeallocPPluginInstance(PPluginInstanceParent* aActor,
- NPError* _retval)
+PluginModuleParent::DeallocPPluginInstance(PPluginInstanceParent* aActor)
{
_MOZ_LOG(__FUNCTION__);
delete aActor;
- *_retval = NPERR_NO_ERROR;
return true;
}
void
PluginModuleParent::SetPluginFuncs(NPPluginFuncs* aFuncs)
{
aFuncs->version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR;
aFuncs->javaClass = nsnull;
@@ -142,17 +140,17 @@ PluginModuleParent::NPP_Destroy(NPP inst
static_cast<PluginInstanceParent*>(instance->pdata);
if (!parentInstance)
return NPERR_NO_ERROR;
parentInstance->Destroy();
NPError prv;
- if (!parentInstance->Module()->CallPPluginInstanceDestructor(parentInstance, &prv)) {
+ if (!PPluginInstanceParent::Call__delete__(parentInstance, &prv)) {
prv = NPERR_GENERIC_ERROR;
}
instance->pdata = nsnull;
return prv;
}
bool
@@ -551,17 +549,17 @@ PluginModuleParent::NPP_New(NPMIMEType p
*error = NPERR_GENERIC_ERROR;
return NS_ERROR_FAILURE;
}
printf ("[PluginModuleParent] %s: got return value %hd\n", __FUNCTION__,
*error);
if (*error != NPERR_NO_ERROR) {
- CallPPluginInstanceDestructor(parentInstance, error);
+ PPluginInstanceParent::Call__delete__(parentInstance, error);
instance->pdata = nsnull;
return NS_ERROR_FAILURE;
}
return NS_OK;
}
bool
--- a/dom/plugins/PluginModuleParent.h
+++ b/dom/plugins/PluginModuleParent.h
@@ -61,16 +61,18 @@
#undef _MOZ_LOG
#define _MOZ_LOG(s) printf("[PluginModuleParent] %s\n", s)
namespace mozilla {
namespace plugins {
//-----------------------------------------------------------------------------
+class BrowserStreamParent;
+
/**
* PluginModuleParent
*
* This class implements the NPP API from the perspective of the rest
* of Gecko, forwarding NPP calls along to the child process that is
* actually running the plugin.
*
* This class /also/ implements a version of the NPN API, because the
@@ -86,18 +88,17 @@ protected:
PPluginInstanceParent*
AllocPPluginInstance(const nsCString& aMimeType,
const uint16_t& aMode,
const nsTArray<nsCString>& aNames,
const nsTArray<nsCString>& aValues,
NPError* rv);
virtual bool
- DeallocPPluginInstance(PPluginInstanceParent* aActor,
- NPError* _retval);
+ DeallocPPluginInstance(PPluginInstanceParent* aActor);
public:
PluginModuleParent(const char* aFilePath);
virtual ~PluginModuleParent();
/**
* LoadModule
--- a/dom/plugins/PluginScriptableObjectChild.cpp
+++ b/dom/plugins/PluginScriptableObjectChild.cpp
@@ -211,17 +211,17 @@ PluginScriptableObjectChild::ScriptableI
if (actor && !actor->CallInvalidate()) {
NS_WARNING("Failed to send message!");
}
object->invalidated = true;
if (instance &&
- !instance->CallPPluginScriptableObjectDestructor(object->parent)) {
+ !PPluginScriptableObjectChild::Call__delete__(object->parent)) {
NS_WARNING("Failed to send message!");
}
}
// static
void
PluginScriptableObjectChild::ScriptableDeallocate(NPObject* aObject)
{
--- a/dom/plugins/PluginScriptableObjectParent.cpp
+++ b/dom/plugins/PluginScriptableObjectParent.cpp
@@ -301,17 +301,17 @@ PluginScriptableObjectParent::Scriptable
if (!actor->CallInvalidate()) {
NS_WARNING("Failed to send message!");
}
object->invalidated = true;
if (instance &&
- !instance->CallPPluginScriptableObjectDestructor(actor)) {
+ !PPluginScriptableObjectParent::Call__delete__(actor)) {
NS_WARNING("Failed to send message!");
}
}
// static
void
PluginScriptableObjectParent::ScriptableDeallocate(NPObject* aObject)
{
--- a/dom/plugins/PluginStreamChild.cpp
+++ b/dom/plugins/PluginStreamChild.cpp
@@ -36,43 +36,60 @@
* ***** END LICENSE BLOCK ***** */
#include "PluginStreamChild.h"
#include "mozilla/plugins/PluginInstanceChild.h"
namespace mozilla {
namespace plugins {
-PluginStreamChild::PluginStreamChild(PluginInstanceChild* instance)
- : mInstance(instance)
+PluginStreamChild::PluginStreamChild()
{
memset(&mStream, 0, sizeof(mStream));
mStream.ndata = static_cast<AStream*>(this);
}
+bool
+PluginStreamChild::Answer__delete__(const NPReason& reason,
+ const bool& artificial)
+{
+ AssertPluginThread();
+ if (!artificial)
+ NPP_DestroyStream(reason);
+ return true;
+}
+
int32_t
PluginStreamChild::NPN_Write(int32_t length, void* buffer)
{
AssertPluginThread();
int32_t written = 0;
CallNPN_Write(nsCString(static_cast<char*>(buffer), length),
&written);
if (written < 0)
- mInstance->CallPPluginStreamDestructor(this, NPERR_GENERIC_ERROR, true);
+ PPluginStreamChild::Call__delete__(this, NPERR_GENERIC_ERROR, true);
+ // careful after here! |this| just got deleted
return written;
}
void
PluginStreamChild::NPP_DestroyStream(NPError reason)
{
AssertPluginThread();
if (mClosed)
return;
mClosed = true;
- mInstance->mPluginIface->destroystream(&mInstance->mData, &mStream, reason);
+ Instance()->mPluginIface->destroystream(
+ &Instance()->mData, &mStream, reason);
+}
+
+PluginInstanceChild*
+PluginStreamChild::Instance()
+{
+ return static_cast<PluginInstanceChild*>(Manager());
}
} // namespace plugins
} // namespace mozilla
--- a/dom/plugins/PluginStreamChild.h
+++ b/dom/plugins/PluginStreamChild.h
@@ -46,37 +46,41 @@ namespace plugins {
class PluginInstanceChild;
class PluginStreamChild : public PPluginStreamChild, public AStream
{
friend class PluginInstanceChild;
public:
- PluginStreamChild(PluginInstanceChild* instance);
+ PluginStreamChild();
virtual ~PluginStreamChild() { }
NS_OVERRIDE virtual bool IsBrowserStream() { return false; }
+ virtual bool Answer__delete__(const NPReason& reason,
+ const bool& artificial);
+
int32_t NPN_Write(int32_t length, void* buffer);
void NPP_DestroyStream(NPError reason);
void EnsureCorrectInstance(PluginInstanceChild* i)
{
- if (i != mInstance)
+ if (i != Instance())
NS_RUNTIMEABORT("Incorrect stream instance");
}
void EnsureCorrectStream(NPStream* s)
{
if (s != &mStream)
NS_RUNTIMEABORT("Incorrect stream data");
}
private:
- PluginInstanceChild* mInstance;
+ PluginInstanceChild* Instance();
+
NPStream mStream;
bool mClosed;
};
} // namespace plugins
} // namespace mozilla
--- a/dom/plugins/PluginStreamParent.cpp
+++ b/dom/plugins/PluginStreamParent.cpp
@@ -70,16 +70,25 @@ PluginStreamParent::AnswerNPN_Write(cons
data.Length(),
const_cast<char*>(data.get()));
if (*written < 0)
mClosed = true;
return true;
}
+bool
+PluginStreamParent::Answer__delete__(const NPError& reason,
+ const bool& artificial)
+{
+ if (!artificial)
+ this->NPN_DestroyStream(reason);
+ return true;
+}
+
void
PluginStreamParent::NPN_DestroyStream(NPReason reason)
{
if (mClosed)
return;
mInstance->mNPNIface->destroystream(mInstance->mNPP, mStream, reason);
mClosed = true;
--- a/dom/plugins/PluginStreamParent.h
+++ b/dom/plugins/PluginStreamParent.h
@@ -55,19 +55,21 @@ public:
PluginStreamParent(PluginInstanceParent* npp, const nsCString& mimeType,
const nsCString& target, NPError* result);
virtual ~PluginStreamParent() { }
NS_OVERRIDE virtual bool IsBrowserStream() { return false; }
virtual bool AnswerNPN_Write(const Buffer& data, int32_t* written);
+ virtual bool Answer__delete__(const NPError& reason, const bool& artificial);
+
+private:
void NPN_DestroyStream(NPReason reason);
-private:
PluginInstanceParent* mInstance;
NPStream* mStream;
bool mClosed;
};
} // namespace plugins
} // namespace mozilla
--- a/dom/plugins/StreamNotifyChild.h
+++ b/dom/plugins/StreamNotifyChild.h
@@ -54,16 +54,18 @@ public:
: mURL(aURL)
, mClosure(NULL)
{ }
void SetValid(void* aClosure) {
mClosure = aClosure;
}
+ bool Answer__delete__(const NPReason& reason);
+
private:
nsCString mURL;
void* mClosure;
};
} // namespace plugins
} // namespace mozilla
--- a/ipc/ipdl/ipdl/ast.py
+++ b/ipc/ipdl/ipdl/ast.py
@@ -291,33 +291,39 @@ class MessageDecl(Node):
self.inParams += inParamsList
def addOutParams(self, outParamsList):
self.outParams += outParamsList
def hasReply(self):
return self.sendSemantics is SYNC or self.sendSemantics is RPC
-class TransitionStmt(Node):
- def __init__(self, loc, state, transitions):
- Node.__init__(self, loc)
- self.state = state
- self.transitions = transitions
-
class Transition(Node):
def __init__(self, loc, trigger, msg, toStates):
Node.__init__(self, loc)
self.trigger = trigger
self.msg = msg
self.toStates = toStates
@staticmethod
def nameToTrigger(name):
return { 'send': SEND, 'recv': RECV, 'call': CALL, 'answer': ANSWER }[name]
+Transition.NULL = Transition(Loc.NONE, None, None, [ ])
+
+class TransitionStmt(Node):
+ def __init__(self, loc, state, transitions):
+ Node.__init__(self, loc)
+ self.state = state
+ self.transitions = transitions
+
+ @staticmethod
+ def makeNullStmt(state):
+ return TransitionStmt(Loc.NONE, state, [ Transition.NULL ])
+
class SEND:
pretty = 'send'
@classmethod
def __hash__(cls): return hash(cls.pretty)
@classmethod
def direction(cls): return OUT
class RECV:
pretty = 'recv'
@@ -350,17 +356,17 @@ class State(Node):
def __hash__(self):
return hash(repr(self))
def __ne__(self, o):
return not (self == o)
def __repr__(self): return '<State %r start=%r>'% (self.name, self.start)
def __str__(self): return '<State %s start=%s>'% (self.name, self.start)
State.ANY = State(Loc.NONE, '[any]', start=True)
-State.NONE = State(Loc.NONE, '[none]', start=False)
+State.DEAD = State(Loc.NONE, '[dead]', start=False)
class Param(Node):
def __init__(self, loc, typespec, name):
Node.__init__(self, loc)
self.name = name
self.typespec = typespec
class TypeSpec(Node):
--- a/ipc/ipdl/ipdl/builtin.py
+++ b/ipc/ipdl/ipdl/builtin.py
@@ -51,16 +51,29 @@ Types = (
'uint16_t',
'int32_t',
'uint32_t',
'int64_t',
'uint64_t',
'intptr_t',
'uintptr_t',
+ # NSPR types
+ 'PRBool',
+ 'PRPackedBool'
+ 'PRInt8',
+ 'PRUint8',
+ 'PRInt16',
+ 'PRUint16',
+ 'PRInt32',
+ 'PRUint32',
+ 'PRInt64',
+ 'PRUint64',
+ 'PRSize',
+
# Mozilla types: "less" standard things we know how serialize/deserialize
'nsresult',
'nsString',
'nsCString',
)
Includes = (
--- a/ipc/ipdl/ipdl/cxx/ast.py
+++ b/ipc/ipdl/ipdl/cxx/ast.py
@@ -463,22 +463,22 @@ class MethodDecl(Node):
self.ret = ret # Type or None
self.virtual = virtual # bool
self.const = const # bool
self.pure = pure # bool
self.static = static # bool
self.typeop = typeop # Type or None
def __deepcopy__(self, memo):
- return MethodDecl(self.name,
- copy.deepcopy(self.params, memo),
- copy.deepcopy(self.ret, memo),
- self.virtual,
- self.const,
- self.pure)
+ return MethodDecl(
+ self.name,
+ copy.deepcopy(self.params, memo),
+ copy.deepcopy(self.ret, memo),
+ self.virtual, self.const, self.pure, self.static,
+ copy.deepcopy(self.typeop, memo))
class MethodDefn(Block):
def __init__(self, decl):
Block.__init__(self)
self.decl = decl
class ConstructorDecl(MethodDecl):
def __init__(self, name, params=[ ], explicit=0):
--- a/ipc/ipdl/ipdl/lower.py
+++ b/ipc/ipdl/ipdl/lower.py
@@ -382,16 +382,23 @@ class _Result:
def errfnSend(msg, errcode=ExprLiteral.FALSE):
return [
_fatalError(msg),
StmtReturn(errcode)
]
def errfnSendCtor(msg): return errfnSend(msg, errcode=ExprLiteral.NULL)
+# TODO should this error handling be strengthened for dtors?
+def errfnSendDtor(msg):
+ return [
+ _printErrorMessage(msg),
+ StmtReturn(ExprLiteral.FALSE)
+ ]
+
# used in |OnMessage*()| handlers that hand in-messages off to Recv*()
# interface methods
def errfnRecv(msg, errcode=_Result.ValuError):
return [
_fatalError(msg),
StmtReturn(errcode)
]
@@ -420,16 +427,21 @@ class _ConvertToCxxType(TypeVisitor):
def visitShmemType(self, s):
return Type(s.name())
def visitProtocolType(self, p): assert 0
def visitMessageType(self, m): assert 0
def visitVoidType(self, v): assert 0
def visitStateType(self, st): assert 0
+def _allocMethod(ptype):
+ return ExprVar('Alloc'+ ptype.name())
+
+def _deallocMethod(ptype):
+ return ExprVar('Dealloc'+ ptype.name())
class _ConvertToSerializableCxxType(TypeVisitor):
def visitBuiltinCxxType(self, t):
return Type(t.name())
def visitImportedCxxType(self, t):
return Type(t.name())
@@ -1081,71 +1093,58 @@ IPDL union type."""
elif it.isActor():
return _HybridDecl.bareType(self, otherside)
else: assert 0
##--------------------------------------------------
class MessageDecl(ipdl.ast.MessageDecl):
def baseName(self):
- if self.decl.type.isDtor():
- return self.name[1:]
return self.name
def recvMethod(self):
name = _recvPrefix(self.decl.type) + self.baseName()
if self.decl.type.isCtor():
name += 'Constructor'
- elif self.decl.type.isDtor():
- name += 'Destructor'
return ExprVar(name)
def sendMethod(self):
name = _sendPrefix(self.decl.type) + self.baseName()
if self.decl.type.isCtor():
name += 'Constructor'
- elif self.decl.type.isDtor():
- name += 'Destructor'
return ExprVar(name)
def hasReply(self):
return (self.decl.type.hasReply()
or self.decl.type.isCtor()
or self.decl.type.isDtor())
- # XXX best place for this?
- def allocMethod(self):
- return ExprVar('Alloc'+ self.baseName())
-
- def deallocMethod(self):
- return ExprVar('Dealloc'+ self.baseName())
-
def msgClass(self):
return 'Msg_%s'% (self.decl.progname)
def pqMsgClass(self):
return '%s::%s'% (self.namespace, self.msgClass())
def msgCast(self, msgexpr):
return ExprCast(msgexpr, Type(self.pqMsgClass(), const=1, ptr=1),
- reinterpret=1)
+ static=1)
def msgId(self): return self.msgClass()+ '__ID'
def pqMsgId(self):
return '%s::%s'% (self.namespace, self.msgId())
def replyClass(self):
return 'Reply_%s'% (self.decl.progname)
def pqReplyClass(self):
return '%s::%s'% (self.namespace, self.replyClass())
def replyCast(self, replyexpr):
return ExprCast(replyexpr, Type(self.pqReplyClass(), const=1, ptr=1),
- reinterpret=1)
+ static=1)
def replyId(self): return self.replyClass()+ '__ID'
def pqReplyId(self):
return '%s::%s'% (self.namespace, self.replyId())
def actorDecl(self):
return self.params[0]
@@ -1257,31 +1256,46 @@ class Protocol(ipdl.ast.Protocol):
return '/'.join(_semsToChannelParts(self.sendSems())) +'.h'
def listenerName(self):
return _semsToListener(self.sendSems())
def fqListenerName(self):
return self.channelName() +'::'+ _semsToListener(self.sendSems())
- def managerCxxType(self, ptr=0):
+ def managerInterfaceType(self, ptr=0):
return Type('mozilla::ipc::IProtocolManager',
ptr=ptr,
T=Type(self.fqListenerName()))
+ def managerActorType(self, side, ptr=0):
+ return Type(_actorName(self.decl.type.manager.name(), side),
+ ptr=ptr)
+
+ def managerMethod(self, actorThis=None):
+ if actorThis is not None:
+ return ExprSelect(actorThis, '->', 'Manager')
+ return ExprVar('Manager');
+
+ # FIXME/bug 525181: implement
+ def stateMethod(self):
+ return ExprVar('state');
+
def registerMethod(self):
return ExprVar('Register')
def registerIDMethod(self):
return ExprVar('RegisterID')
def lookupIDMethod(self):
return ExprVar('Lookup')
- def unregisterMethod(self):
+ def unregisterMethod(self, actorThis=None):
+ if actorThis is not None:
+ return ExprSelect(actorThis, '->', 'Unregister')
return ExprVar('Unregister')
def otherProcessMethod(self):
return ExprVar('OtherProcess')
def nextActorIdExpr(self, side):
assert self.decl.type.isToplevel()
if side is 'parent': op = '++'
@@ -1301,27 +1315,31 @@ class Protocol(ipdl.ast.Protocol):
def lastActorIdVar(self):
assert self.decl.type.isToplevel()
return ExprVar('mLastRouteId')
def actorMapVar(self):
assert self.decl.type.isToplevel()
return ExprVar('mActorMap')
- def channelVar(self):
+ def channelVar(self, actorThis=None):
+ if actorThis is not None:
+ return ExprSelect(actorThis, '->', 'mChannel')
return ExprVar('mChannel')
def channelForSubactor(self):
if self.decl.type.isToplevel():
return ExprAddrOf(self.channelVar())
return self.channelVar()
- def routingId(self):
+ def routingId(self, actorThis=None):
if self.decl.type.isToplevel():
return ExprVar('MSG_ROUTING_CONTROL')
+ if actorThis is not None:
+ return ExprSelect(actorThis, '->', self.idVar().name)
return self.idVar()
def idVar(self):
assert not self.decl.type.isToplevel()
return ExprVar('mId')
def managerVar(self):
assert not self.decl.type.isToplevel()
@@ -1387,18 +1405,19 @@ relevant to C++ code generation.
This pass results in an AST that is a poor man's "IR"; in reality, a
"hybrid" AST mainly consisting of IPDL nodes with new C++ info along
with some new IPDL/C++ nodes that are tuned for C++ codegen."""
def __init__(self):
# the set of typedefs that allow generated classes to
# reference known C++ types by their "short name" rather than
# fully-qualified name. e.g. |Foo| rather than |a::b::Foo|.
- self.typedefs = [ Typedef(Type('mozilla::ipc::ActorHandle'),
- 'ActorHandle') ]
+ self.typedefs = [
+ Typedef(Type('mozilla::ipc::ActorHandle'), 'ActorHandle')
+ ]
self.protocolName = None
def visitProtocol(self, pro):
self.protocolName = pro.name
pro.decl.cxxtypedefs = self.typedefs
Protocol.upgrade(pro)
return ipdl.ast.Visitor.visitProtocol(self, pro)
@@ -1421,17 +1440,17 @@ with some new IPDL/C++ nodes that are tu
newcomponents.append(_UnionMember(ctype, ud, side='child'))
else:
newcomponents.append(_UnionMember(ctype, ud))
ud.components = newcomponents
UnionDecl.upgrade(ud)
if ud.decl.fullname is not None:
self.typedefs.append(Typedef(Type(ud.fqClassName()), ud.name))
-
+
def visitDecl(self, decl):
return _HybridDecl(decl.type, decl.progname)
def visitMessageDecl(self, md):
md.namespace = self.protocolName
md.params = [ param.accept(self) for param in md.inParams ]
md.returns = [ ret.accept(self) for ret in md.outParams ]
@@ -2432,23 +2451,26 @@ class _GenerateProtocolActorCode(ipdl.as
self.hdrfile.addthing(CppDirective('include', '"base/id_map.h"'))
self.hdrfile.addthings([
CppDirective('include', '"'+ p.channelHeaderFile() +'"'),
Whitespace.NL ])
inherits = [ Inherit(Type(p.fqListenerName())) ]
if p.decl.type.isManager():
- inherits.append(Inherit(p.managerCxxType()))
+ inherits.append(Inherit(p.managerInterfaceType()))
self.cls = Class(self.clsname, inherits=inherits, abstract=True)
friends = _FindFriends().findFriends(p.decl.type)
if p.decl.type.isManaged():
friends.add(p.decl.type.manager)
+ # |friend| managed actors so that they can call our Dealloc*()
+ friends.update(p.decl.type.manages)
+
for friend in friends:
self.hdrfile.addthings([
Whitespace.NL,
_makeForwardDecl(friend, self.prettyside),
Whitespace.NL
])
self.cls.addstmts([
FriendClassDecl(_actorName(friend.fullname(),
@@ -2460,49 +2482,55 @@ class _GenerateProtocolActorCode(ipdl.as
self.cls.addstmt(typedef)
for typedef in self.includedActorTypedefs:
self.cls.addstmt(typedef)
self.cls.addstmt(Whitespace.NL)
# interface methods that the concrete subclass has to impl
for md in p.messageDecls:
isctor, isdtor = md.decl.type.isCtor(), md.decl.type.isDtor()
- if isctor:
- self.cls.addstmt(StmtDecl(MethodDecl(
- md.allocMethod().name,
- params=md.makeCxxParams(paramsems='in', returnsems='out',
- side=self.side,
- implicit=0),
- ret=md.actorDecl().bareType(self.side),
- virtual=1, pure=1)))
- elif isdtor:
- self.cls.addstmt(StmtDecl(MethodDecl(
- md.deallocMethod().name,
- params=md.makeCxxParams(paramsems='in', returnsems='out',
- side=self.side,
- implicit=1),
- ret=Type.BOOL,
- virtual=1, pure=1)))
if self.receivesMessage(md):
# generate Recv/Answer* interface
+ implicit = (not isdtor)
recvDecl = MethodDecl(
md.recvMethod().name,
params=md.makeCxxParams(paramsems='in', returnsems='out',
- side=self.side, implicit=1),
+ side=self.side, implicit=implicit),
ret=Type.BOOL, virtual=1)
if isctor or isdtor:
defaultRecv = MethodDefn(recvDecl)
defaultRecv.addstmt(StmtReturn(ExprLiteral.TRUE))
self.cls.addstmt(defaultRecv)
else:
recvDecl.pure = 1
self.cls.addstmt(StmtDecl(recvDecl))
+ for md in p.messageDecls:
+ managed = md.decl.type.constructedType()
+ if not p.decl.type.isManagerOf(managed):
+ continue
+
+ # add the Alloc/Dealloc interface for managed actors
+ actortype = md.actorDecl().bareType(self.side)
+
+ self.cls.addstmt(StmtDecl(MethodDecl(
+ _allocMethod(managed).name,
+ params=md.makeCxxParams(side=self.side, implicit=0),
+ ret=actortype,
+ virtual=1, pure=1)))
+
+ self.cls.addstmt(StmtDecl(MethodDecl(
+ _deallocMethod(managed).name,
+ params=[ Decl(actortype, 'actor') ],
+ ret=Type.BOOL,
+ virtual=1, pure=1)))
+
+
self.cls.addstmt(Whitespace.NL)
self.cls.addstmts((
[ Label.PRIVATE ]
+ self.standardTypedefs()
+ [ Whitespace.NL ]
))
@@ -2559,16 +2587,25 @@ class _GenerateProtocolActorCode(ipdl.as
Whitespace.NL ])
# Close()
closemeth = MethodDefn(MethodDecl('Close'))
closemeth.addstmt(StmtExpr(
ExprCall(ExprSelect(p.channelVar(), '.', 'Close'))))
self.cls.addstmts([ closemeth, Whitespace.NL ])
+ if not p.decl.type.isToplevel():
+ ## manager()
+ managertype = p.managerActorType(self.side, ptr=1)
+ managermeth = MethodDefn(MethodDecl(
+ p.managerMethod().name, ret=managertype))
+ managermeth.addstmt(StmtReturn(p.managerVar()))
+
+ self.cls.addstmts([ managermeth, Whitespace.NL ])
+
## OnMessageReceived()/OnCallReceived()
# save these away for use in message handler case stmts
msgvar = ExprVar('msg')
self.msgvar = msgvar
replyvar = ExprVar('reply')
self.replyvar = replyvar
@@ -2713,17 +2750,18 @@ class _GenerateProtocolActorCode(ipdl.as
p.actorMapVar().name)),
StmtDecl(Decl(_actorIdType(), p.lastActorIdVar().name)),
StmtDecl(Decl(Type('ProcessHandle'),
p.otherProcessVar().name))
])
elif p.decl.type.isManaged():
self.cls.addstmts([
StmtDecl(Decl(_actorIdType(), p.idVar().name)),
- StmtDecl(Decl(p.managerCxxType(ptr=1), p.managerVar().name))
+ StmtDecl(Decl(p.managerActorType(self.side, ptr=1),
+ p.managerVar().name))
])
if p.usesShmem():
self.cls.addstmts([
StmtDecl(Decl(Type('IDMap', T=_rawShmemType()),
p.shmemMapVar().name)),
StmtDecl(Decl(_shmemIdType(), p.lastShmemIdVar().name))
])
@@ -3009,29 +3047,39 @@ class _GenerateProtocolActorCode(ipdl.as
elif isdtor and isasync:
sendmethod, (recvlbl, recvcase) = self.genAsyncDtor(md)
elif isdtor:
sendmethod = self.genBlockingDtorMethod(md)
elif isasync:
sendmethod = self.genAsyncSendMethod(md)
else:
sendmethod = self.genBlockingSendMethod(md)
+
+ # XXX figure out what to do here
+ if isdtor and md.decl.type.constructedType().isToplevel():
+ sendmethod = None
+
if sendmethod is not None:
self.cls.addstmts([ sendmethod, Whitespace.NL ])
if recvcase is not None:
addRecvCase(recvlbl, recvcase)
recvlbl, recvcase = None, None
if self.receivesMessage(md):
if isctor:
recvlbl, recvcase = self.genCtorRecvCase(md)
elif isdtor:
recvlbl, recvcase = self.genDtorRecvCase(md)
else:
recvlbl, recvcase = self.genRecvCase(md)
+
+ # XXX figure out what to do here
+ if isdtor and md.decl.type.constructedType().isToplevel():
+ return
+
addRecvCase(recvlbl, recvcase)
def genAsyncCtor(self, md):
actor = md.actorDecl()
method = MethodDefn(self.makeSendMethodDecl(md))
method.addstmts(self.ctorPrologue(md) + [ Whitespace.NL ])
@@ -3112,90 +3160,93 @@ class _GenerateProtocolActorCode(ipdl.as
callctor = self.callAllocActor(md, retsems='out')
helper.addstmt(StmtReturn(ExprCall(
ExprVar(helperdecl.name), args=[ callctor ] + callctor.args)))
return helper
def genAsyncDtor(self, md):
actor = md.actorDecl()
- method = MethodDefn(self.makeSendMethodDecl(md))
+ actorvar = actor.var()
+ method = MethodDefn(self.makeDtorMethodDecl(md))
method.addstmts(self.dtorPrologue(actor.var()))
-
- msgvar, stmts = self.makeMessage(md, errfnSend)
- sendok, sendstmts = self.sendAsync(md, msgvar)
+ method.addstmts(self.dtorPrologue(actorvar))
+
+ msgvar, stmts = self.makeMessage(md, errfnSendDtor, actorvar)
+ sendok, sendstmts = self.sendAsync(md, msgvar, actorvar)
method.addstmts(
stmts
+ sendstmts
+ [ Whitespace.NL ]
- + self.dtorEpilogue(md, actor.var(), retsems='out')
+ + self.dtorEpilogue(md, actor.var())
+ [ StmtReturn(sendok) ])
lbl = CaseLabel(md.pqReplyId())
case = StmtBlock()
case.addstmt(StmtReturn(_Result.Processed))
# TODO if the dtor is "inherently racy", keep the actor alive
# until the other side acks
return method, (lbl, case)
def genBlockingDtorMethod(self, md):
actor = md.actorDecl()
- method = MethodDefn(self.makeSendMethodDecl(md))
-
- method.addstmts(self.dtorPrologue(actor.var()))
-
- msgvar, stmts = self.makeMessage(md, errfnSend)
+ actorvar = actor.var()
+ method = MethodDefn(self.makeDtorMethodDecl(md))
+
+ method.addstmts(self.dtorPrologue(actorvar))
+
+ msgvar, stmts = self.makeMessage(md, errfnSendDtor, actorvar)
replyvar = self.replyvar
- sendok, sendstmts = self.sendBlocking(md, msgvar, replyvar)
+ sendok, sendstmts = self.sendBlocking(md, msgvar, replyvar, actorvar)
method.addstmts(
stmts
+ [ Whitespace.NL,
StmtDecl(Decl(Type('Message'), replyvar.name)) ]
+ sendstmts)
readok, destmts = self.deserializeReply(
md, ExprAddrOf(replyvar), self.side, errfnSend)
ifsendok = StmtIf(sendok)
ifsendok.addifstmts(destmts)
ifsendok.addifstmts([ Whitespace.NL,
StmtExpr(ExprAssn(sendok, readok, '&=')) ])
method.addstmts(
[ ifsendok ]
- + self.dtorEpilogue(md, actor.var(), retsems='out')
+ + self.dtorEpilogue(md, actor.var())
+ [ Whitespace.NL, StmtReturn(sendok) ])
return method
def dtorPrologue(self, actorexpr):
return [ self.failIfNullActor(actorexpr), Whitespace.NL ]
- def dtorEpilogue(self, md, actorexpr, retsems):
+ def dtorEpilogue(self, md, actorexpr):
return (self.unregisterActor(actorexpr)
- + [ StmtExpr(self.callDeallocActor(md, retsems)) ])
+ + [ StmtExpr(self.callDeallocActor(md, actorexpr)) ])
def genAsyncSendMethod(self, md):
method = MethodDefn(self.makeSendMethodDecl(md))
msgvar, stmts = self.makeMessage(md, errfnSend)
sendok, sendstmts = self.sendAsync(md, msgvar)
method.addstmts(stmts
+[ Whitespace.NL ]
+ sendstmts
+[ StmtReturn(sendok) ])
return method
- def genBlockingSendMethod(self, md):
+ def genBlockingSendMethod(self, md, fromActor=None):
method = MethodDefn(self.makeSendMethodDecl(md))
- msgvar, serstmts = self.makeMessage(md, errfnSend)
+ msgvar, serstmts = self.makeMessage(md, errfnSend, fromActor)
replyvar = self.replyvar
sendok, sendstmts = self.sendBlocking(md, msgvar, replyvar)
failif = StmtIf(ExprNot(sendok))
failif.addifstmt(StmtReturn(ExprLiteral.FALSE))
readok, desstmts = self.deserializeReply(
md, ExprAddrOf(replyvar), self.side, errfnSend)
@@ -3251,19 +3302,19 @@ class _GenerateProtocolActorCode(ipdl.as
failif = StmtIf(ExprNot(readok))
failif.addifstmt(StmtReturn(_Result.PayloadError))
case.addstmts(
stmts
+ [ failif, Whitespace.NL ]
+ [ StmtDecl(Decl(r.bareType(self.side), r.var().name))
for r in md.returns ]
- + self.invokeRecvHandler(md)
+ + self.invokeRecvHandler(md, implicit=0)
+ [ Whitespace.NL ]
- + self.dtorEpilogue(md, md.actorDecl().var(), retsems='in')
+ + self.dtorEpilogue(md, md.actorDecl().var())
+ self.makeReply(md, errfnRecv)
+ [ Whitespace.NL,
StmtReturn(_Result.Processed) ])
return lbl, case
def genRecvCase(self, md):
@@ -3290,36 +3341,36 @@ class _GenerateProtocolActorCode(ipdl.as
# helper methods
def failIfNullActor(self, actorExpr, retOnNull=ExprLiteral.FALSE):
failif = StmtIf(ExprNot(actorExpr))
failif.addifstmt(StmtReturn(retOnNull))
return failif
def unregisterActor(self, actorexpr):
- return [ StmtExpr(ExprCall(self.protocol.unregisterMethod(),
+ return [ StmtExpr(ExprCall(self.protocol.unregisterMethod(actorexpr),
args=[ _actorId(actorexpr) ])),
StmtExpr(ExprAssn(_actorId(actorexpr), _FREED_ACTOR_ID)) ]
- def makeMessage(self, md, errfn):
+ def makeMessage(self, md, errfn, fromActor=None):
msgvar = self.msgvar
stmts = [ StmtDecl(Decl(Type(md.pqMsgClass(), ptr=1), msgvar.name)),
Whitespace.NL ]
msgCtorArgs = [ ]
for param in md.params:
arg, sstmts = param.serialize(param.var(), self.side, errfn)
msgCtorArgs.append(arg)
stmts.extend(sstmts)
stmts.extend([
StmtExpr(ExprAssn(
msgvar,
ExprNew(Type(md.pqMsgClass()), args=msgCtorArgs))) ]
- + self.setMessageFlags(md, msgvar, reply=0))
+ + self.setMessageFlags(md, msgvar, reply=0, actor=fromActor))
return msgvar, stmts
def makeReply(self, md, errfn):
# TODO special cases for async ctor/dtor replies
if md.decl.type.isAsync():
return [ ]
@@ -3337,20 +3388,20 @@ class _GenerateProtocolActorCode(ipdl.as
replyvar,
ExprNew(Type(md.pqReplyClass()), args=replyCtorArgs))) ]
+ self.setMessageFlags(md, replyvar, reply=1)
+[ self.logMessage(md, md.replyCast(replyvar), 'Sending reply ') ])
return stmts
- def setMessageFlags(self, md, var, reply):
+ def setMessageFlags(self, md, var, reply, actor=None):
stmts = [ StmtExpr(ExprCall(
ExprSelect(var, '->', 'set_routing_id'),
- args=[ self.protocol.routingId() ])) ]
+ args=[ self.protocol.routingId(actor) ])) ]
if md.decl.type.isSync():
stmts.append(StmtExpr(ExprCall(
ExprSelect(var, '->', 'set_sync'))))
elif md.decl.type.isRpc():
stmts.append(StmtExpr(ExprCall(
ExprSelect(var, '->', 'set_rpc'))))
@@ -3431,65 +3482,72 @@ class _GenerateProtocolActorCode(ipdl.as
ExprDeref(readexprs[i]), side, sems='out',
errfn=errfn))
if len(ifok.ifb.stmts):
stmts.extend([ Whitespace.NL, ifok ])
return okvar, stmts
- def sendAsync(self, md, msgexpr):
+ def sendAsync(self, md, msgexpr, actor=None):
sendok = ExprVar('__sendok')
return (
sendok,
[ Whitespace.NL,
self.logMessage(md, msgexpr, 'Sending '),
Whitespace.NL,
StmtDecl(Decl(Type.BOOL, sendok.name),
init=ExprCall(
- ExprSelect(self.protocol.channelVar(),
+ ExprSelect(self.protocol.channelVar(actor),
self.protocol.channelSel(), 'Send'),
args=[ msgexpr ]))
])
- def sendBlocking(self, md, msgexpr, replyexpr):
+ def sendBlocking(self, md, msgexpr, replyexpr, actor=None):
sendok = ExprVar('__sendok')
return (
sendok,
[ Whitespace.NL,
self.logMessage(md, msgexpr, 'Sending '),
Whitespace.NL,
- StmtDecl(Decl(Type.BOOL, sendok.name),
- init=ExprCall(ExprSelect(self.protocol.channelVar(),
- self.protocol.channelSel(),
- _sendPrefix(md.decl.type)),
- args=[ msgexpr,
- ExprAddrOf(replyexpr) ]))
+ StmtDecl(
+ Decl(Type.BOOL, sendok.name),
+ init=ExprCall(ExprSelect(self.protocol.channelVar(actor),
+ self.protocol.channelSel(),
+ _sendPrefix(md.decl.type)),
+ args=[ msgexpr, ExprAddrOf(replyexpr) ]))
])
-
def callAllocActor(self, md, retsems):
return ExprCall(
- md.allocMethod(),
+ _allocMethod(md.decl.type.constructedType()),
args=md.makeCxxArgs(params=1, retsems=retsems, retcallsems='out',
implicit=0))
- def callDeallocActor(self, md, retsems):
+ def callDeallocActor(self, md, actorexpr):
+ actor = md.decl.type.constructedType()
return ExprCall(
- md.deallocMethod(),
- args=md.makeCxxArgs(params=1, retsems=retsems, retcallsems='out'))
-
- def invokeRecvHandler(self, md):
+ ExprSelect(ExprCall(self.protocol.managerMethod(actorexpr)), '->',
+ _deallocMethod(md.decl.type.constructedType()).name),
+ args=[ actorexpr ])
+
+ def invokeRecvHandler(self, md, implicit=1):
failif = StmtIf(ExprNot(
ExprCall(md.recvMethod(),
args=md.makeCxxArgs(params=1,
- retsems='in', retcallsems='out'))))
+ retsems='in', retcallsems='out',
+ implicit=implicit))))
failif.addifstmt(StmtReturn(_Result.ValuError))
return [ failif ]
+ def makeDtorMethodDecl(self, md):
+ decl = self.makeSendMethodDecl(md)
+ decl.static = 1
+ return decl
+
def makeSendMethodDecl(self, md):
implicit = md.decl.type.hasImplicitActorParam()
decl = MethodDecl(
md.sendMethod().name,
params=md.makeCxxParams(paramsems='in', returnsems='out',
side=self.side, implicit=implicit),
ret=Type.BOOL)
if md.decl.type.isCtor():
--- a/ipc/ipdl/ipdl/parser.py
+++ b/ipc/ipdl/ipdl/parser.py
@@ -140,16 +140,18 @@ def locFromTok(p, num):
##-----------------------------------------------------------------------------
reserved = set((
'answer',
'async',
'both',
'call',
'child',
+ '__delete__',
+ 'delete', # reserve 'delete' to prevent its use
'goto',
'include',
'manager',
'manages',
'namespace',
'nullable',
'or',
'parent',
@@ -390,19 +392,23 @@ def p_MessageBody(p):
msg = MessageDecl(locFromTok(p, 1))
msg.name = p[1]
msg.addInParams(p[2])
msg.addOutParams(p[3])
p[0] = msg
def p_MessageId(p):
"""MessageId : ID
+ | __DELETE__
+ | DELETE
| '~' ID"""
if 3 == len(p):
- p[1] += p[2] # munge dtor name to "~Foo". handled later
+ _error(locFromTok(p, 1), "sorry, `%s()' destructor syntax is a relic from a bygone era. Declare `__delete__()' in the `%s' protocol instead", p[1]+p[2], p[2])
+ elif 'delete' == p[1]:
+ _error(locFromTok(p, 1), "`delete' is a reserved identifier")
p[0] = p[1]
def p_MessageInParams(p):
"""MessageInParams : '(' ParamList ')'"""
p[0] = p[2]
def p_MessageOutParams(p):
"""MessageOutParams : RETURNS '(' ParamList ')'
@@ -447,19 +453,28 @@ def p_Transitions(p):
| Transition"""
if 3 == len(p):
p[1].append(p[2])
p[0] = p[1]
else:
p[0] = [ p[1] ]
def p_Transition(p):
- """Transition : Trigger MessageId GOTO StateList ';'"""
+ """Transition : Trigger ID GOTO StateList ';'
+ | Trigger __DELETE__ ';'
+ | Trigger DELETE ';'"""
+ if 'delete' == p[2]:
+ _error(locFromTok(p, 1), "`delete' is a reserved identifier")
+
loc, trigger = p[1]
- p[0] = Transition(loc, trigger, p[2], p[4])
+ if 6 == len(p):
+ nextstates = p[4]
+ else:
+ nextstates = [ State.DEAD ]
+ p[0] = Transition(loc, trigger, p[2], nextstates)
def p_Trigger(p):
"""Trigger : SEND
| RECV
| CALL
| ANSWER"""
p[0] = [ locFromTok(p, 1), Transition.nameToTrigger(p[1]) ]
--- a/ipc/ipdl/ipdl/type.py
+++ b/ipc/ipdl/ipdl/type.py
@@ -27,19 +27,20 @@
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
import os, sys
-from ipdl.ast import CxxInclude, Decl, Loc, QualifiedId, State, TypeSpec, UsingStmt, Visitor, ASYNC, SYNC, RPC, IN, OUT, INOUT, ANSWER, CALL, RECV, SEND
+from ipdl.ast import CxxInclude, Decl, Loc, QualifiedId, State, TransitionStmt, TypeSpec, UsingStmt, Visitor, ASYNC, SYNC, RPC, IN, OUT, INOUT, ANSWER, CALL, RECV, SEND
import ipdl.builtin as builtin
+_DELETE_MSG = '__delete__'
class TypeVisitor:
def defaultVisit(self, node, *args):
raise Exception, "INTERNAL ERROR: no visitor for node type `%s'"% (
node.__class__.__name__)
def visitVoidType(self, v, *args):
pass
@@ -225,21 +226,22 @@ class MessageType(IPDLType):
def isIn(self): return self.direction is IN
def isOut(self): return self.direction is OUT
def isInout(self): return self.direction is INOUT
def hasImplicitActorParam(self):
return self.isCtor() or self.isDtor()
class ProtocolType(IPDLType):
- def __init__(self, qname, sendSemantics):
+ def __init__(self, qname, sendSemantics, stateless=False):
self.qname = qname
self.sendSemantics = sendSemantics
self.manager = None
self.manages = [ ]
+ self.stateless = stateless
def isProtocol(self): return True
def name(self):
return self.qname.baseid
def fullname(self):
return str(self.qname)
def managedBy(self, mgr):
@@ -442,17 +444,16 @@ With this information, it finally type c
# now that the nodes have decls, type checking is much easier.
if not runpass(CheckTypes(self.errors)):
return False
if (len(tu.protocol.startStates)
and not runpass(CheckStateMachine(self.errors))):
return False
-
return True
def reportErrors(self, errout):
for error in self.errors:
print >>errout, error
class TcheckVisitor(Visitor):
@@ -509,17 +510,18 @@ class GatherDecls(TcheckVisitor):
# that works for C++ and protocol types?
qname = p.qname()
if 0 == len(qname.quals):
fullname = None
else:
fullname = str(qname)
p.decl = self.declare(
loc=p.loc,
- type=ProtocolType(qname, p.sendSemantics),
+ type=ProtocolType(qname, p.sendSemantics,
+ stateless=(0 == len(p.transitionStmts))),
shortname=p.name,
fullname=fullname)
# XXX ugh, this sucks. but we need this information to compute
# what friend decls we need in generated C++
p.decl.type._p = p
# make sure we have decls for all dependent protocols
@@ -538,16 +540,21 @@ class GatherDecls(TcheckVisitor):
p.accept(self)
tu.type = VOID
self.symtab = savedSymtab
def visitProtocolInclude(self, pi):
+ if pi.tu is None:
+ self.error(
+ pi.loc,
+ "(type checking here will be unreliable because of an earlier error)")
+ return
pi.tu.accept(self)
self.symtab.declare(pi.tu.protocol.decl)
def visitUnionDecl(self, ud):
qname = ud.qname()
if 0 == len(qname.quals):
fullname = None
else:
@@ -599,53 +606,69 @@ class GatherDecls(TcheckVisitor):
"top-level protocol `%s' cannot be empty",
p.name)
setattr(self, 'currentProtocolDecl', p.decl)
for msg in p.messageDecls:
msg.accept(self)
del self.currentProtocolDecl
+ if not p.decl.type.isToplevel():
+ dtordecl = self.symtab.lookup(_DELETE_MSG)
+ if not dtordecl:
+ self.error(
+ p.loc,
+ "destructor declaration `delete(...)' required for managed protocol `%s'",
+ p.name)
+
for managed in p.managesStmts:
mgdname = managed.name
ctordecl = self.symtab.lookup(mgdname +'Constructor')
- dtordecl = self.symtab.lookup(mgdname +'Destructor')
- if not(ctordecl and dtordecl
- and ctordecl.type.isCtor() and dtordecl.type.isDtor()):
+ if not (ctordecl and ctordecl.type.isCtor()):
self.error(
managed.loc,
- "constructor and destructor declarations are required for managed protocol `%s' (managed by protocol `%s')",
+ "constructor declaration required for managed protocol `%s' (managed by protocol `%s')",
mgdname, p.name)
p.states = { }
if len(p.transitionStmts):
p.startStates = [ ts for ts in p.transitionStmts
if ts.state.start ]
if 0 == len(p.startStates):
p.startStates = [ p.transitionStmts[0] ]
+
+ # declare implicit "any" and "dead" states
+ self.declare(loc=State.ANY.loc,
+ type=StateType(p.decl.type, State.ANY.name, start=False),
+ progname=State.ANY.name)
+ self.declare(loc=State.DEAD.loc,
+ type=StateType(p.decl.type, State.DEAD.name, start=False),
+ progname=State.DEAD.name)
# declare each state before decorating their mention
for trans in p.transitionStmts:
p.states[trans.state] = trans
trans.state.decl = self.declare(
loc=trans.state.loc,
type=StateType(p.decl.type, trans.state, trans.state.start),
progname=trans.state.name)
- # declare implicit "any" state
- self.declare(loc=State.ANY.loc,
- type=StateType(p.decl.type, State.ANY.name, start=False),
- progname=State.ANY.name)
-
for trans in p.transitionStmts:
self.seentriggers = set()
trans.accept(self)
+ if not (p.decl.type.stateless
+ or (p.decl.type.isToplevel()
+ and None is self.symtab.lookup(_DELETE_MSG))):
+ # add a special state |state DEAD: null goto DEAD;|
+ deadtrans = TransitionStmt.makeNullStmt(State.DEAD)
+ p.states[State.DEAD] = deadtrans
+
# visit the message decls once more and resolve the state names
# attached to actor params and returns
def resolvestate(loc, actortype):
assert actortype.isIPDL() and actortype.isActor()
# already resolved this guy's state
if isinstance(actortype.state, Decl):
return
@@ -745,43 +768,31 @@ class GatherDecls(TcheckVisitor):
def visitMessageDecl(self, md):
msgname = md.name
loc = md.loc
isctor = False
isdtor = False
cdtype = None
- if '~' == msgname[0]:
- # it's a destructor. look up the constructed type
- msgname = msgname[1:]
-
- decl = self.symtab.lookup(msgname)
- if decl is None:
- self.error(loc, "type `%s' has not been declared", msgname)
- elif not decl.type.isProtocol():
- self.error(loc, "destructor for non-protocol type `%s'",
- msgname)
- else:
- msgname += 'Destructor'
- isdtor = True
- cdtype = decl.type
-
decl = self.symtab.lookup(msgname)
-
if decl is not None and decl.type.isProtocol():
# probably a ctor. we'll check validity later.
msgname += 'Constructor'
isctor = True
cdtype = decl.type
elif decl is not None:
self.error(loc, "message name `%s' already declared as `%s'",
msgname, decl.type.typename())
# if we error here, no big deal; move on to find more
- decl = None
+
+ if _DELETE_MSG == msgname:
+ isdtor = True
+ cdtype = self.currentProtocolDecl.type
+
# enter message scope
self.symtab.enterScope(md)
msgtype = MessageType(md.sendSemantics, md.direction,
ctor=isctor, dtor=isdtor, cdtype=cdtype)
# replace inparam Param nodes with proper Decls
@@ -933,16 +944,27 @@ class CheckTypes(TcheckVisitor):
mgrtype = ptype.manager
if mgrtype is not None and ptype.needsMoreJuiceThan(mgrtype):
mgrname = p.manager.decl.shortname
self.error(
p.decl.loc,
"protocol `%s' requires more powerful send semantics than its manager `%s' provides",
pname, mgrname)
+ # XXX currently we don't require a delete() message of top-level
+ # actors. need to let experience guide this decision
+ if not p.decl.type.isToplevel():
+ for md in p.messageDecls:
+ if _DELETE_MSG == md.name: break
+ else:
+ self.error(
+ p.decl.loc,
+ "managed protocol `%s' requires a `delete()' message to be declared",
+ p.name)
+
return Visitor.visitProtocol(self, p)
def visitManagesStmt(self, mgs):
pdecl = mgs.manager.decl
ptype, pname = pdecl.type, pdecl.shortname
mgsdecl = mgs.decl
@@ -1004,30 +1026,30 @@ class CheckTypes(TcheckVisitor):
mname, pname)
if mtype.isAsync() and len(mtype.returns):
# XXX/cjones could modify grammar to disallow this ...
self.error(loc,
"asynchronous message `%s' declares return values",
mname)
- if (mtype.isCtor() or mtype.isDtor()) and not ptype.isManagerOf(mtype.constructedType()):
+ if mtype.isCtor() and not ptype.isManagerOf(mtype.constructedType()):
self.error(
loc,
- "ctor/dtor for protocol `%s', which is not managed by protocol `%s'",
+ "ctor for protocol `%s', which is not managed by protocol `%s'",
mname[:-len('constructor')], pname)
def visitTransition(self, t):
_YNC = [ ASYNC, SYNC ]
loc = t.loc
impliedDirection, impliedSems = {
SEND: [ OUT, _YNC ], RECV: [ IN, _YNC ],
- CALL: [ OUT, RPC ], ANSWER: [ IN, RPC ]
+ CALL: [ OUT, RPC ], ANSWER: [ IN, RPC ],
} [t.trigger]
if (OUT is impliedDirection and t.msg.type.isIn()
or IN is impliedDirection and t.msg.type.isOut()
or _YNC is impliedSems and t.msg.type.isRpc()
or RPC is impliedSems and (not t.msg.type.isRpc())):
mtype = t.msg.type
@@ -1248,23 +1270,35 @@ direction as trigger |t|'''
# violation per state. there may be O(n^4)
# total, way too many for a human to parse
#
# XXX/cjones: could set a limit on #printed
# and stop after that limit ...
return
def checkReachability(self, p):
- visited = set() # set(State)
- def explore(ts):
+ def explore(ts, visited):
if ts.state in visited:
return
visited.add(ts.state)
for outedge in ts.transitions:
for toState in outedge.toStates:
- explore(p.states[toState])
+ explore(p.states[toState], visited)
+ checkfordelete = (State.DEAD in p.states)
+
+ allvisited = set() # set(State)
for root in p.startStates:
- explore(root)
- for ts in p.transitionStmts:
- if ts.state not in visited:
- self.error(ts.loc, "unreachable state `%s' in protocol `%s'",
+ visited = set()
+
+ explore(root, visited)
+ allvisited.update(visited)
+
+ if checkfordelete and State.DEAD not in visited:
+ self.error(
+ root.loc,
+ "when starting from state `%s', actors of protocol `%s' cannot be deleted", root.state.name, p.name)
+
+ for ts in p.states.itervalues():
+ if ts.state is not State.DEAD and ts.state not in allvisited:
+ self.error(ts.loc,
+ "unreachable state `%s' in protocol `%s'",
ts.state.name, p.name)
--- a/ipc/ipdl/test/cxx/PTestArrays.ipdl
+++ b/ipc/ipdl/test/cxx/PTestArrays.ipdl
@@ -32,17 +32,17 @@ sync protocol PTestArrays {
manages PTestArraysSub;
child:
PTestArraysSub(int i);
Start();
parent:
- ~PTestArraysSub();
+ __delete__();
sync Test1(int[] i1)
returns (int[] o1);
sync Test2(PTestArraysSub[] i1)
returns (PTestArraysSub[] o1);
sync Test3(IntDouble i1,
@@ -79,13 +79,31 @@ parent:
Unions i4)
returns (Unions o1,
Unions o2,
Unions o3,
Unions o4);
sync Test10(Unions[] i1)
returns (Unions[] o1);
+
+
+state START:
+ send Start goto TEST1;
+
+state TEST1: recv Test1 goto TEST2;
+state TEST2: recv Test2 goto TEST3;
+state TEST3: recv Test3 goto TEST4;
+state TEST4: recv Test4 goto TEST5;
+state TEST5: recv Test5 goto TEST6;
+state TEST6: recv Test6 goto TEST7;
+state TEST7: recv Test7 goto TEST8;
+state TEST8: recv Test8 goto TEST9;
+state TEST9: recv Test9 goto TEST10;
+state TEST10: recv Test10 goto DEAD;
+
+state DEAD:
+ recv __delete__;
};
} // namespace _ipdltest
} // namespace mozilla
--- a/ipc/ipdl/test/cxx/PTestArraysSub.ipdl
+++ b/ipc/ipdl/test/cxx/PTestArraysSub.ipdl
@@ -1,12 +1,14 @@
include protocol "PTestArrays.ipdl";
namespace mozilla {
namespace _ipdltest {
protocol PTestArraysSub {
manager PTestArrays;
- // empty
+
+parent:
+ __delete__();
};
} // namespace _ipdltest
} // namespace mozilla
--- a/ipc/ipdl/test/cxx/PTestDesc.ipdl
+++ b/ipc/ipdl/test/cxx/PTestDesc.ipdl
@@ -3,17 +3,16 @@ include protocol "PTestDescSubsub.ipdl";
namespace mozilla {
namespace _ipdltest {
protocol PTestDesc {
manages PTestDescSub;
child:
PTestDescSub();
- ~PTestDescSub();
Test(PTestDescSubsub a);
parent:
Ok(PTestDescSubsub a);
state START:
--- a/ipc/ipdl/test/cxx/PTestDescSub.ipdl
+++ b/ipc/ipdl/test/cxx/PTestDescSub.ipdl
@@ -4,14 +4,15 @@ include protocol "PTestDescSubsub.ipdl";
namespace mozilla {
namespace _ipdltest {
protocol PTestDescSub {
manager PTestDesc;
manages PTestDescSubsub;
child:
+ __delete__();
+
PTestDescSubsub();
- ~PTestDescSubsub();
};
}
}
--- a/ipc/ipdl/test/cxx/PTestDescSubsub.ipdl
+++ b/ipc/ipdl/test/cxx/PTestDescSubsub.ipdl
@@ -1,13 +1,15 @@
+
include protocol "PTestDescSub.ipdl";
namespace mozilla {
namespace _ipdltest {
protocol PTestDescSubsub {
manager PTestDescSub;
- // empty
+child:
+ __delete__();
};
}
}
--- a/ipc/ipdl/test/cxx/PTestLatency.ipdl
+++ b/ipc/ipdl/test/cxx/PTestLatency.ipdl
@@ -1,16 +1,17 @@
namespace mozilla {
namespace _ipdltest {
protocol PTestLatency {
child:
+ __delete__();
Ping();
Ping5();
parent:
Pong();
Pong5();
// Trial 1: single ping/pong latency
@@ -19,17 +20,18 @@ state PING:
send Ping5 goto PING4;
state PONG:
recv Pong goto PING;
// Trial 2: "overlapped" ping/pong latency
state PING5:
send Ping5 goto PING4;
- //send delete; SOMEDAY!
+ send __delete__;
+
state PING4: send Ping5 goto PING3;
state PING3: send Ping5 goto PING2;
state PING2: send Ping5 goto PING1;
state PING1: send Ping5 goto PONG1;
state PONG1: recv Pong5 goto PONG2;
state PONG2: recv Pong5 goto PONG3;
state PONG3: recv Pong5 goto PONG4;
--- a/ipc/ipdl/test/cxx/PTestManyChildAllocs.ipdl
+++ b/ipc/ipdl/test/cxx/PTestManyChildAllocs.ipdl
@@ -4,18 +4,16 @@ namespace mozilla {
namespace _ipdltest {
protocol PTestManyChildAllocs {
manages PTestManyChildAllocsSub;
child:
Go(); // start allocating
- ~PTestManyChildAllocsSub();
-
parent:
Done();
PTestManyChildAllocsSub();
};
} // namespace _ipdltest
} // namespace mozilla
--- a/ipc/ipdl/test/cxx/PTestManyChildAllocsSub.ipdl
+++ b/ipc/ipdl/test/cxx/PTestManyChildAllocsSub.ipdl
@@ -1,16 +1,19 @@
include protocol "PTestManyChildAllocs.ipdl";
namespace mozilla {
namespace _ipdltest {
protocol PTestManyChildAllocsSub {
manager PTestManyChildAllocs;
+child:
+ __delete__();
+
parent:
Hello();
// empty
};
} // namespace _ipdltest
} // namespace mozilla
--- a/ipc/ipdl/test/cxx/PTestSanity.ipdl
+++ b/ipc/ipdl/test/cxx/PTestSanity.ipdl
@@ -2,30 +2,27 @@
namespace mozilla {
namespace _ipdltest {
protocol PTestSanity {
child:
Ping(int zero, float zeroPtFive);
+ __delete__();
parent:
Pong(int one, float zeroPtTwoFive);
-both:
- UNREACHED();
-
state PING:
send Ping goto PONG;
state PONG:
recv Pong goto DEAD;
- // hmm ... maybe support this idiom natively?
state DEAD:
- send UNREACHED goto DEAD;
+ send __delete__;
};
} // namespace mozilla
} // namespace _ipdltest
--- a/ipc/ipdl/test/cxx/TestArrays.cpp
+++ b/ipc/ipdl/test/cxx/TestArrays.cpp
@@ -57,21 +57,22 @@ TestArraysParent::Main()
if (!SendPTestArraysSubConstructor(i))
fail("can't alloc actor");
if (!SendStart())
fail("can't send Start()");
}
bool
-TestArraysParent::RecvPTestArraysSubDestructor(PTestArraysSubParent* actor)
+TestArraysParent::DeallocPTestArraysSub(PTestArraysSubParent* actor)
{
test_assert(Cast(actor).mI == Cast(mKids[0]).mI,
"dtor sent to wrong actor");
mKids.RemoveElementAt(0);
+ delete actor;
if (mKids.Length() > 0)
return true;
passed("with flying colors");
static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
nsCOMPtr<nsIAppShell> appShell (do_GetService(kAppShellCID));
appShell->Exit();
@@ -316,17 +317,17 @@ TestArraysChild::RecvStart()
Test5();
Test6();
Test7();
Test8();
Test9();
Test10();
for (uint32 i = 0; i < nactors; ++i)
- if (!SendPTestArraysSubDestructor(mKids[i]))
+ if (!PTestArraysSubChild::Send__delete__(mKids[i]))
fail("can't send dtor");
return true;
}
void
TestArraysChild::Test1()
{
--- a/ipc/ipdl/test/cxx/TestArrays.h
+++ b/ipc/ipdl/test/cxx/TestArrays.h
@@ -41,24 +41,17 @@ public:
protected:
virtual PTestArraysSubParent* AllocPTestArraysSub(const int& i)
{
PTestArraysSubParent* actor = new TestArraysSub(i);
mKids.AppendElement(actor);
return actor;
}
- virtual bool DeallocPTestArraysSub(PTestArraysSubParent* actor)
- {
- delete actor;
- return true;
- }
-
- virtual bool
- RecvPTestArraysSubDestructor(PTestArraysSubParent* actor);
+ virtual bool DeallocPTestArraysSub(PTestArraysSubParent* actor);
virtual bool RecvTest1(
const nsTArray<int>& i1,
nsTArray<int>* o1);
virtual bool RecvTest2(
const nsTArray<PTestArraysSubParent*>& i1,
nsTArray<PTestArraysSubParent*>* o1);
new file mode 100644
--- /dev/null
+++ b/ipc/ipdl/test/ipdl/error/DeleteRace.ipdl
@@ -0,0 +1,14 @@
+// XXX kind of a gray area whether |delete| should be a part of the
+// top-level protocol. but if it's ever not, this test will break and
+// we'll notice, right?
+protocol DeleteRace {
+parent:
+ M1();
+
+child:
+ delete();
+
+state START:
+ send delete;
+ recv M1 goto START;
+};
--- a/ipc/ipdl/test/ipdl/error/actorparam_badState.ipdl
+++ b/ipc/ipdl/test/ipdl/error/actorparam_badState.ipdl
@@ -1,9 +1,10 @@
protocol actorparam_badState {
child:
Msg(actorparam_badState:FARGEL p);
+ delete();
state S1:
send Msg goto S1;
-
+ send delete;
};
--- a/ipc/ipdl/test/ipdl/error/dtorReserved.ipdl
+++ b/ipc/ipdl/test/ipdl/error/dtorReserved.ipdl
@@ -1,8 +1,8 @@
protocol dtorReserved {
- // it's an error to use dtor syntax for non-dtor messages
+ // it's an error to use old-style dtor syntax
child:
~SomeMsg();
};
--- a/ipc/ipdl/test/ipdl/error/managedNoCtor.ipdl
+++ b/ipc/ipdl/test/ipdl/error/managedNoCtor.ipdl
@@ -1,6 +1,7 @@
include protocol "managerNoCtor.ipdl";
protocol managedNoCtor {
manager managerNoCtor;
// empty
+child: delete();
};
--- a/ipc/ipdl/test/ipdl/error/managerNoCtor.ipdl
+++ b/ipc/ipdl/test/ipdl/error/managerNoCtor.ipdl
@@ -1,9 +1,8 @@
include protocol "managedNoCtor.ipdl";
protocol managerNoCtor {
manages managedNoCtor;
parent:
// error: no ctor defined
- ~managedNoCtor();
};
--- a/ipc/ipdl/test/ipdl/error/race_OverlappingMultiOut.ipdl
+++ b/ipc/ipdl/test/ipdl/error/race_OverlappingMultiOut.ipdl
@@ -1,29 +1,35 @@
protocol race_OverlappingMultiOut {
child:
Msg1();
Msg1_();
+ delete(); suppressUndeleteableError()
+
parent:
Msg2();
Msg2_();
+
+start state _:
+ send delete;
+ send suppressUndeleteableError goto S10;
+
// *** ERROR: send/recv of Msg1/Msg2 in state S10 goes to overlapping
// sets { S11, S12 }, { S12, S13 } and thus can't be unidirectional
-start state S10:
+state S10:
send Msg1 goto S11 or S12;
recv Msg2 goto S12 or S13;
state S11:
recv Msg2 goto S14;
state S12:
send Msg1 goto S14;
recv Msg2 goto S14;
state S13:
send Msg1 goto S14;
state S14:
send Msg1 goto S14;
recv Msg2 goto S14;
-
};
--- a/ipc/ipdl/test/ipdl/error/race_ViolateSameDirection.ipdl
+++ b/ipc/ipdl/test/ipdl/error/race_ViolateSameDirection.ipdl
@@ -1,25 +1,29 @@
protocol race_ViolateSameDirection {
child:
Msg1();
Msg1_();
+ delete(); suppressUndeleteableError();
parent:
Msg2();
Msg2_();
// *** ERROR: state S7 doesn't have all-same-direction
-start state S6:
+start state _:
+ send delete;
+ send suppressUndeleteableError goto S6;
+
+state S6:
send Msg1 goto S7;
recv Msg2 goto S8;
state S7:
recv Msg2 goto S9;
send Msg1 goto S9;
state S8:
send Msg1 goto S9;
state S9:
send Msg1 goto S9;
recv Msg2 goto S9;
-
};
--- a/ipc/ipdl/test/ipdl/error/redefState.ipdl
+++ b/ipc/ipdl/test/ipdl/error/redefState.ipdl
@@ -1,11 +1,14 @@
protocol redefState {
// error: redefining state in state machine
child:
Msg();
+ delete();
state S1: send Msg goto S1;
state S1: send Msg goto S1;
+start state _:
+ send delete;
};
--- a/ipc/ipdl/test/ipdl/error/repeatedOutState.ipdl
+++ b/ipc/ipdl/test/ipdl/error/repeatedOutState.ipdl
@@ -1,12 +1,12 @@
protocol repeatedOutState {
-child: Msg();
+child: Msg(); delete();
// error: S2 repeated in multi-out set
state S1:
send Msg goto S2 or S2 or S4;
state S2: send Msg goto S2;
state S3: send Msg goto S3;
-state S4: send Msg goto S4;
+state S4: send Mesg goto S4; send delete;
};
--- a/ipc/ipdl/test/ipdl/error/trans_WrongDirection.ipdl
+++ b/ipc/ipdl/test/ipdl/error/trans_WrongDirection.ipdl
@@ -1,9 +1,12 @@
protocol trans_WrongDirection {
child:
Msg();
+ delete();
state S1:
recv Msg goto S1;
+start state _:
+ send delete();
};
--- a/ipc/ipdl/test/ipdl/error/trans_WrongDirection2.ipdl
+++ b/ipc/ipdl/test/ipdl/error/trans_WrongDirection2.ipdl
@@ -1,9 +1,12 @@
protocol trans_WrongDirection2 {
parent:
Msg();
+ delete();
state S1:
send Msg goto S1;
+start state _:
+ recv delete;
};
--- a/ipc/ipdl/test/ipdl/error/trans_WrongDirection3.ipdl
+++ b/ipc/ipdl/test/ipdl/error/trans_WrongDirection3.ipdl
@@ -1,9 +1,12 @@
sync protocol trans_WrongDirection3 {
parent:
sync Msg();
+ delete();
state S1:
send Msg goto S1;
+start state _:
+ recv delete;
};
--- a/ipc/ipdl/test/ipdl/error/trans_WrongDirection4.ipdl
+++ b/ipc/ipdl/test/ipdl/error/trans_WrongDirection4.ipdl
@@ -1,9 +1,12 @@
rpc protocol trans_WrongDirection4 {
child:
rpc Msg();
+ delete();
state S1:
answer Msg goto S1;
+start state _:
+ send delete;
};
--- a/ipc/ipdl/test/ipdl/error/trans_WrongDirection5.ipdl
+++ b/ipc/ipdl/test/ipdl/error/trans_WrongDirection5.ipdl
@@ -1,9 +1,12 @@
rpc protocol trans_WrongDirection5 {
parent:
rpc Msg();
+ delete()
state S1:
call Msg goto S1;
+start state_:
+ recv delete;
};
--- a/ipc/ipdl/test/ipdl/error/trans_WrongName.ipdl
+++ b/ipc/ipdl/test/ipdl/error/trans_WrongName.ipdl
@@ -1,9 +1,10 @@
protocol trans_WrongName {
child:
Msg();
+ delete();
state S1:
call Msg goto S1;
-
+ send delete();
};
--- a/ipc/ipdl/test/ipdl/error/trans_WrongName2.ipdl
+++ b/ipc/ipdl/test/ipdl/error/trans_WrongName2.ipdl
@@ -1,9 +1,10 @@
protocol trans_WrongName2 {
parent:
Msg();
+ delete();
state S1:
answer Msg goto S1;
-
+ recv delete;
};
--- a/ipc/ipdl/test/ipdl/error/trans_WrongName3.ipdl
+++ b/ipc/ipdl/test/ipdl/error/trans_WrongName3.ipdl
@@ -1,9 +1,10 @@
sync protocol trans_WrongName3 {
parent:
sync Msg();
+ delete();
state S1:
answer Msg goto S1;
-
+ recv delete();
};
--- a/ipc/ipdl/test/ipdl/error/trans_WrongName4.ipdl
+++ b/ipc/ipdl/test/ipdl/error/trans_WrongName4.ipdl
@@ -1,9 +1,10 @@
rpc protocol trans_WrongName4 {
child:
rpc Msg();
+ delete();
state S1:
send Msg goto S1;
-
+ send delete;
};
--- a/ipc/ipdl/test/ipdl/error/trans_WrongName5.ipdl
+++ b/ipc/ipdl/test/ipdl/error/trans_WrongName5.ipdl
@@ -1,9 +1,10 @@
rpc protocol trans_WrongName5 {
parent:
rpc Msg();
+ delete();
state S1:
recv Msg goto S1;
-
+ recv delete;
};
--- a/ipc/ipdl/test/ipdl/error/undeclProtocol.ipdl
+++ b/ipc/ipdl/test/ipdl/error/undeclProtocol.ipdl
@@ -1,7 +1,6 @@
protocol undeclProtocol {
manages undeclared;
child:
undeclared();
- ~undeclared();
};
new file mode 100644
--- /dev/null
+++ b/ipc/ipdl/test/ipdl/error/unreachedDelete.ipdl
@@ -0,0 +1,5 @@
+protocol unreachedDelete {
+child: M1(); delete();
+
+state S1: send M1 goto S1;
+};
new file mode 100644
--- /dev/null
+++ b/ipc/ipdl/test/ipdl/error/unreachedDeleteMultiStart.ipdl
@@ -0,0 +1,10 @@
+protocol unreachedDeleteMultiStart {
+child:
+ M1(); M2(); delete();
+
+start state S1: send M1 goto S2;
+state S2: send delete;
+
+start state S3: send M2 goto S4;
+state S4: send M1 goto S3;
+};
new file mode 100644
--- /dev/null
+++ b/ipc/ipdl/test/ipdl/ok/Delete.ipdl
@@ -0,0 +1,8 @@
+include protocol "DeleteSub.ipdl";
+
+sync protocol Delete {
+ manages DeleteSub;
+
+child:
+ DeleteSub();
+};
new file mode 100644
--- /dev/null
+++ b/ipc/ipdl/test/ipdl/ok/DeleteSub.ipdl
@@ -0,0 +1,12 @@
+include protocol "Delete.ipdl";
+
+sync protocol DeleteSub {
+ manager Delete;
+
+parent:
+ sync __delete__(int x) returns (double d);
+
+state START:
+ recv __delete__;
+};
+
--- a/ipc/ipdl/test/ipdl/ok/actorparam_state.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/actorparam_state.ipdl
@@ -1,9 +1,10 @@
protocol actorparam_state {
child:
Msg(actorparam_state:S1 p);
+ __delete__();
state S1:
send Msg goto S1;
-
+ send __delete__;
};
--- a/ipc/ipdl/test/ipdl/ok/array_OfActors.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/array_OfActors.ipdl
@@ -2,10 +2,9 @@ include protocol "array_OfActorsSub.ipdl
protocol array_OfActors {
manages array_OfActorsSub;
child:
Msg(array_OfActorsSub[] p);
array_OfActorsSub();
- ~array_OfActorsSub();
};
--- a/ipc/ipdl/test/ipdl/ok/array_OfActorsSub.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/array_OfActorsSub.ipdl
@@ -1,7 +1,7 @@
include protocol "array_OfActors.ipdl";
protocol array_OfActorsSub {
manager array_OfActors;
- // empty
+child: __delete__();
};
--- a/ipc/ipdl/test/ipdl/ok/managedProtocol.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/managedProtocol.ipdl
@@ -1,6 +1,8 @@
include protocol "managerProtocol.ipdl";
protocol managedProtocol {
manager managerProtocol;
- // empty
+
+child:
+ __delete__();
};
--- a/ipc/ipdl/test/ipdl/ok/managerProtocol.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/managerProtocol.ipdl
@@ -2,11 +2,10 @@ include protocol "managedProtocol.ipdl";
// sanity check of managed/manager protocols
protocol managerProtocol {
manages managedProtocol;
parent:
managedProtocol(int i);
- ~managedProtocol(int i);
};
--- a/ipc/ipdl/test/ipdl/ok/multiStartState.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/multiStartState.ipdl
@@ -1,11 +1,11 @@
protocol multiStartState {
-child: Msg();
+child: Msg(); __delete__();
start state S1:
- send Msg goto S1;
+ send Msg goto S1; send __delete__;
start state S2:
- send Msg goto S2;
+ send Msg goto S2; send __delete__;
};
--- a/ipc/testshell/PTestShell.ipdl
+++ b/ipc/testshell/PTestShell.ipdl
@@ -43,18 +43,17 @@ namespace ipc {
protocol PTestShell
{
manager PContentProcess;
manages PTestShellCommand;
child:
+ __delete__();
+
ExecuteCommand(nsString aCommand);
PTestShellCommand(nsString aCommand);
-
-parent:
- ~PTestShellCommand(nsString aResponse);
};
} // namespace ipc
} // namespace mozilla
--- a/ipc/testshell/PTestShellCommand.ipdl
+++ b/ipc/testshell/PTestShellCommand.ipdl
@@ -38,12 +38,15 @@
include protocol "PTestShell.ipdl";
namespace mozilla {
namespace ipc {
protocol PTestShellCommand
{
manager PTestShell;
+
+parent:
+ __delete__(nsString aResponse);
};
} // namespace ipc
} // namespace mozilla
--- a/ipc/testshell/TestShellChild.cpp
+++ b/ipc/testshell/TestShellChild.cpp
@@ -58,18 +58,17 @@ TestShellChild::RecvExecuteCommand(const
PTestShellCommandChild*
TestShellChild::AllocPTestShellCommand(const nsString& aCommand)
{
return new PTestShellCommandChild();
}
bool
-TestShellChild::DeallocPTestShellCommand(PTestShellCommandChild* aCommand,
- const nsString& aResponse)
+TestShellChild::DeallocPTestShellCommand(PTestShellCommandChild* aCommand)
{
delete aCommand;
return true;
}
bool
TestShellChild::RecvPTestShellCommandConstructor(PTestShellCommandChild* aActor,
const nsString& aCommand)
@@ -79,10 +78,10 @@ TestShellChild::RecvPTestShellCommandCon
return false;
}
nsString response;
if (!mXPCShell->EvaluateString(aCommand, &response)) {
return false;
}
- return SendPTestShellCommandDestructor(aActor, response);
+ return PTestShellCommandChild::Send__delete__(aActor, response);
}
--- a/ipc/testshell/TestShellChild.h
+++ b/ipc/testshell/TestShellChild.h
@@ -59,18 +59,17 @@ public:
PTestShellCommandChild*
AllocPTestShellCommand(const nsString& aCommand);
bool
RecvPTestShellCommandConstructor(PTestShellCommandChild* aActor,
const nsString& aCommand);
bool
- DeallocPTestShellCommand(PTestShellCommandChild* aCommand,
- const nsString& aResponse);
+ DeallocPTestShellCommand(PTestShellCommandChild* aCommand);
void SetXPCShell(XPCShellEnvironment* aXPCShell) {
mXPCShell = aXPCShell;
}
private:
nsAutoPtr<XPCShellEnvironment> mXPCShell;
};
--- a/ipc/testshell/TestShellParent.cpp
+++ b/ipc/testshell/TestShellParent.cpp
@@ -44,31 +44,28 @@ using mozilla::ipc::PTestShellCommandPar
PTestShellCommandParent*
TestShellParent::AllocPTestShellCommand(const nsString& aCommand)
{
return new TestShellCommandParent();
}
bool
-TestShellParent::DeallocPTestShellCommand(PTestShellCommandParent* aActor,
- const nsString& aResponse)
+TestShellParent::DeallocPTestShellCommand(PTestShellCommandParent* aActor)
{
delete aActor;
return true;
}
bool
-TestShellParent::RecvPTestShellCommandDestructor(PTestShellCommandParent* aActor,
- const nsString& aResponse)
+TestShellParent::CommandDone(TestShellCommandParent* command,
+ const nsString& aResponse)
{
- TestShellCommandParent* command =
- reinterpret_cast<TestShellCommandParent*>(aActor);
-
- JSBool ok = command->RunCallback(aResponse);
+ // XXX what should happen if the callback fails?
+ /*JSBool ok = */command->RunCallback(aResponse);
command->ReleaseCallback();
return true;
}
JSBool
TestShellCommandParent::SetCallback(JSContext* aCx,
jsval aCallback)
--- a/ipc/testshell/TestShellParent.h
+++ b/ipc/testshell/TestShellParent.h
@@ -1,8 +1,11 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=8 et :
+ */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
@@ -42,44 +45,53 @@
#include "jsapi.h"
#include "nsAutoJSValHolder.h"
#include "nsStringGlue.h"
namespace mozilla {
namespace ipc {
+class TestShellCommandParent;
+
+
+class TestShellParent : public PTestShellParent
+{
+public:
+ PTestShellCommandParent*
+ AllocPTestShellCommand(const nsString& aCommand);
+
+ bool
+ DeallocPTestShellCommand(PTestShellCommandParent* aActor);
+
+ bool
+ CommandDone(TestShellCommandParent* aActor, const nsString& aResponse);
+};
+
+
class TestShellCommandParent : public PTestShellCommandParent
{
public:
TestShellCommandParent() : mCx(NULL) { }
JSBool SetCallback(JSContext* aCx,
jsval aCallback);
JSBool RunCallback(const nsString& aResponse);
void ReleaseCallback();
+protected:
+ bool Recv__delete__(const nsString& aResponse) {
+ return static_cast<TestShellParent*>(Manager())->CommandDone(
+ this, aResponse);
+ }
+
private:
JSContext* mCx;
nsAutoJSValHolder mCallback;
};
-class TestShellParent : public PTestShellParent
-{
-public:
- PTestShellCommandParent*
- AllocPTestShellCommand(const nsString& aCommand);
-
- bool
- DeallocPTestShellCommand(PTestShellCommandParent* aActor,
- const nsString& aResponse);
-
- bool
- RecvPTestShellCommandDestructor(PTestShellCommandParent* aActor,
- const nsString& aResponse);
-};
} /* namespace ipc */
} /* namespace mozilla */
#endif /* ipc_testshell_TestShellParent_h */
--- a/netwerk/ipc/PNecko.ipdl
+++ b/netwerk/ipc/PNecko.ipdl
@@ -47,15 +47,16 @@ namespace net {
//-------------------------------------------------------------------
protocol PNecko
{
manager PContentProcess;
manages PHttpChannel;
parent:
+ __delete__();
+
PHttpChannel();
- ~PHttpChannel();
};
} // namespace net
} // namespace mozilla
--- a/netwerk/protocol/http/src/PHttpChannel.ipdl
+++ b/netwerk/protocol/http/src/PHttpChannel.ipdl
@@ -45,15 +45,17 @@ namespace net {
//-------------------------------------------------------------------
protocol PHttpChannel
{
manager PNecko;
parent:
+ __delete__();
+
asyncOpen(nsCString uri);
};
} // namespace net
} // namespace mozilla