Bug 523356 - Remote event listeners for Electrolysis, r=bsmedberg
authorOlli Pettay <Olli.Pettay@helsinki.fi>
Tue, 17 Nov 2009 16:22:23 +0200
changeset 36088 ddf8790d3c4ae3570e08e37738f32ed95f8d9305
parent 36087 2ffe92d3cfde1155df2de246b9b3cf9f7bfec0c6
child 36089 684053bbb68e8514d8b6fcd841569b5c21bb0d09
push idunknown
push userunknown
push dateunknown
reviewersbsmedberg
bugs523356
milestone1.9.3a1pre
Bug 523356 - Remote event listeners for Electrolysis, r=bsmedberg
content/base/public/nsIFrameLoader.idl
content/base/src/nsFrameLoader.cpp
content/base/src/nsXMLHttpRequest.h
content/events/public/nsIPrivateDOMEvent.h
content/events/src/Makefile.in
content/events/src/nsDOMEvent.cpp
content/events/src/nsDOMEvent.h
content/events/src/nsDOMNotifyPaintEvent.cpp
content/events/src/nsDOMNotifyPaintEvent.h
content/events/src/nsDOMScrollAreaEvent.cpp
content/events/src/nsDOMScrollAreaEvent.h
content/events/src/nsDOMUIEvent.cpp
content/events/src/nsDOMUIEvent.h
dom/ipc/Makefile.in
dom/ipc/PIFrameEmbedding.ipdl
dom/ipc/TabChild.cpp
dom/ipc/TabChild.h
dom/ipc/TabMessageUtils.cpp
dom/ipc/TabMessageUtils.h
dom/ipc/TabParent.cpp
dom/ipc/TabParent.h
dom/ipc/test.xul
security/manager/ssl/src/nsSmartCardEvent.cpp
security/manager/ssl/src/nsSmartCardEvent.h
--- a/content/base/public/nsIFrameLoader.idl
+++ b/content/base/public/nsIFrameLoader.idl
@@ -95,16 +95,20 @@ interface nsIFrameLoader : nsISupports
   void sendCrossProcessMouseEvent(in AString aType,
                                   in float aX,
                                   in float aY,
                                   in long aButton,
                                   in long aClickCount,
                                   in long aModifiers,
                                   [optional] in boolean aIgnoreRootScrollFrame);
 
+  /**
+   * Activate event forwarding from client (remote frame) to parent.
+   */
+  void activateFrameEvent(in AString aType, in boolean capture);
 };
 
 native alreadyAddRefed_nsFrameLoader(already_AddRefed<nsFrameLoader>);
 
 [scriptable, uuid(8f3b12a0-35ae-4e0d-9152-8e0d7e49d446)]
 interface nsIFrameLoaderOwner : nsISupports
 {
   /**
--- a/content/base/src/nsFrameLoader.cpp
+++ b/content/base/src/nsFrameLoader.cpp
@@ -1488,8 +1488,21 @@ nsFrameLoader::SendCrossProcessMouseEven
                                   aClickCount, aModifiers,
                                   aIgnoreRootScrollFrame);
     return NS_OK;
   }
 #endif
   return NS_ERROR_FAILURE;
 }
 
+NS_IMETHODIMP
+nsFrameLoader::ActivateFrameEvent(const nsAString& aType,
+                                  PRBool aCapture)
+{
+#ifdef MOZ_IPC
+  if (mChildProcess) {
+    mChildProcess->SendactivateFrameEvent(nsString(aType), aCapture);
+    return NS_OK;
+  }
+#endif
+  return NS_ERROR_FAILURE;
+}
+
--- a/content/base/src/nsXMLHttpRequest.h
+++ b/content/base/src/nsXMLHttpRequest.h
@@ -481,16 +481,25 @@ public:
   NS_IMETHOD_(nsEvent*) GetInternalNSEvent()
   {
     return mInner->GetInternalNSEvent();
   }
   NS_IMETHOD SetTrusted(PRBool aTrusted)
   {
     return mInner->SetTrusted(aTrusted);
   }
+  virtual void Serialize(IPC::Message* aMsg,
+                         PRBool aSerializeInterfaceType)
+  {
+    mInner->Serialize(aMsg, aSerializeInterfaceType);
+  }
+  virtual PRBool Deserialize(const IPC::Message* aMsg, void** aIter)
+  {
+    return mInner->Deserialize(aMsg, aIter);
+  }
 
 protected:
   // Use nsDOMProgressEvent so that we can forward
   // most of the method calls easily.
   nsRefPtr<nsDOMProgressEvent> mInner;
   PRUint64 mCurProgress;
   PRUint64 mMaxProgress;
 };
--- a/content/events/public/nsIPrivateDOMEvent.h
+++ b/content/events/public/nsIPrivateDOMEvent.h
@@ -36,36 +36,42 @@
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsIPrivateDOMEvent_h__
 #define nsIPrivateDOMEvent_h__
 
 #include "nsISupports.h"
 
 #define NS_IPRIVATEDOMEVENT_IID \
-{ 0x1da4c501, 0xe87e, 0x49b4, \
-  { 0xb0, 0x49, 0xdf, 0x9f, 0xc3, 0x6b, 0x56, 0xd4 } }
+{ 0x26f5f0e9, 0x2960, 0x4405, \
+  { 0xa1, 0x7e, 0xd8, 0x9f, 0xb0, 0xd9, 0x4c, 0x71 } }
 
 class nsIDOMEventTarget;
 class nsIDOMEvent;
 class nsEvent;
 class nsCommandEvent;
 class nsPresContext;
 class nsInvalidateRequestList;
+namespace IPC {
+class Message;
+}
 
 class nsIPrivateDOMEvent : public nsISupports
 {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_IPRIVATEDOMEVENT_IID)
 
   NS_IMETHOD DuplicatePrivateData() = 0;
   NS_IMETHOD SetTarget(nsIDOMEventTarget* aTarget) = 0;
   NS_IMETHOD_(PRBool) IsDispatchStopped() = 0;
   NS_IMETHOD_(nsEvent*) GetInternalNSEvent() = 0;
   NS_IMETHOD SetTrusted(PRBool aTrusted) = 0;
+  virtual void Serialize(IPC::Message* aMsg,
+                         PRBool aSerializeInterfaceType) = 0;
+  virtual PRBool Deserialize(const IPC::Message* aMsg, void** aIter) = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIPrivateDOMEvent, NS_IPRIVATEDOMEVENT_IID)
 
 nsresult
 NS_NewDOMEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, nsEvent *aEvent);
 nsresult
 NS_NewDOMDataContainerEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, nsEvent *aEvent);
--- a/content/events/src/Makefile.in
+++ b/content/events/src/Makefile.in
@@ -81,19 +81,21 @@ CPPSRCS		= \
 		nsDOMSimpleGestureEvent.cpp \
 		nsDOMEventTargetHelper.cpp \
 		nsDOMScrollAreaEvent.cpp \
 		$(NULL)
 
 # we don't want the shared lib, but we want to force the creation of a static lib.
 FORCE_STATIC_LIB = 1
 
+include $(topsrcdir)/config/config.mk
+include $(topsrcdir)/ipc/chromium/chromium-config.mk
 include $(topsrcdir)/config/rules.mk
 
-LOCAL_INCLUDES	= \
+LOCAL_INCLUDES	+= \
              -I$(srcdir)/../../base/src \
              -I$(srcdir)/../../html/base/src \
              -I$(srcdir)/../../xul/content/src \
              -I$(srcdir)/../../xml/content/src \
              -I$(srcdir)/../../../dom/base \
              -I$(srcdir)/../../../layout/generic \
              -I$(srcdir)/../../../layout/xul/base/src \
              -I$(srcdir)/../../../layout/xul/base/src/tree/src \
--- a/content/events/src/nsDOMEvent.cpp
+++ b/content/events/src/nsDOMEvent.cpp
@@ -32,16 +32,20 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * 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 ***** */
 
+#ifdef MOZ_IPC
+#include "base/basictypes.h"
+#include "IPC/IPCMessageUtils.h"
+#endif
 #include "nsCOMPtr.h"
 #include "nsDOMEvent.h"
 #include "nsEventStateManager.h"
 #include "nsIFrame.h"
 #include "nsIContent.h"
 #include "nsIPresShell.h"
 #include "nsIDocument.h"
 #include "nsIPrivateCompositionEvent.h"
@@ -1528,16 +1532,71 @@ nsDOMEvent::ReportWrongPropertyAccessWar
 NS_IMETHODIMP
 nsDOMEvent::GetPreventDefault(PRBool* aReturn)
 {
   NS_ENSURE_ARG_POINTER(aReturn);
   *aReturn = mEvent && (mEvent->flags & NS_EVENT_FLAG_NO_DEFAULT);
   return NS_OK;
 }
 
+void
+nsDOMEvent::Serialize(IPC::Message* aMsg, PRBool aSerializeInterfaceType)
+{
+#ifdef MOZ_IPC
+  if (aSerializeInterfaceType) {
+    IPC::WriteParam(aMsg, NS_LITERAL_STRING("event"));
+  }
+
+  nsString type;
+  GetType(type);
+  IPC::WriteParam(aMsg, type);
+
+  PRBool bubbles = PR_FALSE;
+  GetBubbles(&bubbles);
+  IPC::WriteParam(aMsg, bubbles);
+
+  PRBool cancelable = PR_FALSE;
+  GetCancelable(&cancelable);
+  IPC::WriteParam(aMsg, cancelable);
+
+  PRBool trusted = PR_FALSE;
+  GetIsTrusted(&trusted);
+  IPC::WriteParam(aMsg, trusted);
+
+  // No timestamp serialization for now!
+#endif
+}
+
+PRBool
+nsDOMEvent::Deserialize(const IPC::Message* aMsg, void** aIter)
+{
+#ifdef MOZ_IPC
+  nsString type;
+  NS_ENSURE_TRUE(IPC::ReadParam(aMsg, aIter, &type), PR_FALSE);
+
+  PRBool bubbles = PR_FALSE;
+  NS_ENSURE_TRUE(IPC::ReadParam(aMsg, aIter, &bubbles), PR_FALSE);
+
+  PRBool cancelable = PR_FALSE;
+  NS_ENSURE_TRUE(IPC::ReadParam(aMsg, aIter, &cancelable), PR_FALSE);
+
+  PRBool trusted = PR_FALSE;
+  NS_ENSURE_TRUE(IPC::ReadParam(aMsg, aIter, &trusted), PR_FALSE);
+
+  nsresult rv = InitEvent(type, bubbles, cancelable);
+  NS_ENSURE_SUCCESS(rv, PR_FALSE);
+  SetTrusted(trusted);
+
+  return PR_TRUE;
+#else
+  return PR_FALSE;
+#endif
+}
+
+
 nsresult NS_NewDOMEvent(nsIDOMEvent** aInstancePtrResult,
                         nsPresContext* aPresContext,
                         nsEvent *aEvent) 
 {
   nsDOMEvent* it = new nsDOMEvent(aPresContext, aEvent);
   if (nsnull == it) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
--- a/content/events/src/nsDOMEvent.h
+++ b/content/events/src/nsDOMEvent.h
@@ -188,16 +188,19 @@ public:
 
   // nsIPrivateDOMEvent interface
   NS_IMETHOD    DuplicatePrivateData();
   NS_IMETHOD    SetTarget(nsIDOMEventTarget* aTarget);
   NS_IMETHOD_(PRBool)    IsDispatchStopped();
   NS_IMETHOD_(nsEvent*)    GetInternalNSEvent();
   NS_IMETHOD    SetTrusted(PRBool aTrusted);
 
+  virtual void Serialize(IPC::Message* aMsg, PRBool aSerializeInterfaceType);
+  virtual PRBool Deserialize(const IPC::Message* aMsg, void** aIter);
+
   static PopupControlState GetEventPopupControlState(nsEvent *aEvent);
 
   static void PopupAllowedEventsChanged();
 
   static void Shutdown();
 
   static const char* GetEventName(PRUint32 aEventType);
 protected:
--- a/content/events/src/nsDOMNotifyPaintEvent.cpp
+++ b/content/events/src/nsDOMNotifyPaintEvent.cpp
@@ -31,16 +31,20 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * 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 ***** */
 
+#ifdef MOZ_IPC
+#include "base/basictypes.h"
+#include "IPC/IPCMessageUtils.h"
+#endif
 #include "nsDOMNotifyPaintEvent.h"
 #include "nsContentUtils.h"
 #include "nsClientRect.h"
 #include "nsPaintRequest.h"
 #include "nsIFrame.h"
 
 nsDOMNotifyPaintEvent::nsDOMNotifyPaintEvent(nsPresContext* aPresContext,
                                              nsEvent* aEvent,
@@ -137,16 +141,60 @@ nsDOMNotifyPaintEvent::GetPaintRequests(
     r->SetRequest(mInvalidateRequests[i]);
     requests->Append(r);
   }
 
   requests.forget(aResult);
   return NS_OK;
 }
 
+#ifdef MOZ_IPC
+void
+nsDOMNotifyPaintEvent::Serialize(IPC::Message* aMsg,
+                                 PRBool aSerializeInterfaceType)
+{
+  if (aSerializeInterfaceType) {
+    IPC::WriteParam(aMsg, NS_LITERAL_STRING("notifypaintevent"));
+  }
+
+  nsDOMEvent::Serialize(aMsg, PR_FALSE);
+
+  PRUint32 length = mInvalidateRequests.Length();
+  IPC::WriteParam(aMsg, length);
+  for (PRUint32 i = 0; i < length; ++i) {
+    IPC::WriteParam(aMsg, mInvalidateRequests[i].mRect.x);
+    IPC::WriteParam(aMsg, mInvalidateRequests[i].mRect.y);
+    IPC::WriteParam(aMsg, mInvalidateRequests[i].mRect.width);
+    IPC::WriteParam(aMsg, mInvalidateRequests[i].mRect.height);
+    IPC::WriteParam(aMsg, mInvalidateRequests[i].mFlags);
+  }
+}
+
+PRBool
+nsDOMNotifyPaintEvent::Deserialize(const IPC::Message* aMsg, void** aIter)
+{
+  NS_ENSURE_TRUE(nsDOMEvent::Deserialize(aMsg, aIter), PR_FALSE);
+
+  PRUint32 length = 0;
+  NS_ENSURE_TRUE(IPC::ReadParam(aMsg, aIter, &length), PR_FALSE);
+  mInvalidateRequests.SetCapacity(length);
+  for (PRUint32 i = 0; i < length; ++i) {
+    nsInvalidateRequestList::Request req;
+    NS_ENSURE_TRUE(IPC::ReadParam(aMsg, aIter, &req.mRect.x), PR_FALSE);
+    NS_ENSURE_TRUE(IPC::ReadParam(aMsg, aIter, &req.mRect.y), PR_FALSE);
+    NS_ENSURE_TRUE(IPC::ReadParam(aMsg, aIter, &req.mRect.width), PR_FALSE);
+    NS_ENSURE_TRUE(IPC::ReadParam(aMsg, aIter, &req.mRect.height), PR_FALSE);
+    NS_ENSURE_TRUE(IPC::ReadParam(aMsg, aIter, &req.mFlags), PR_FALSE);
+    mInvalidateRequests.AppendElement(req);
+  }
+
+  return PR_TRUE;
+}
+#endif
+
 nsresult NS_NewDOMNotifyPaintEvent(nsIDOMEvent** aInstancePtrResult,
                                    nsPresContext* aPresContext,
                                    nsEvent *aEvent,
                                    PRUint32 aEventType,
                                    nsInvalidateRequestList* aInvalidateRequests) 
 {
   nsDOMNotifyPaintEvent* it =
     new nsDOMNotifyPaintEvent(aPresContext, aEvent, aEventType,
--- a/content/events/src/nsDOMNotifyPaintEvent.h
+++ b/content/events/src/nsDOMNotifyPaintEvent.h
@@ -56,15 +56,19 @@ public:
 
   NS_DECL_ISUPPORTS_INHERITED
 
   NS_DECL_NSIDOMNOTIFYPAINTEVENT
 
   // Forward to base class
   NS_FORWARD_TO_NSDOMEVENT
 
+#ifdef MOZ_IPC
+  virtual void Serialize(IPC::Message* aMsg, PRBool aSerializeInterfaceType);
+  virtual PRBool Deserialize(const IPC::Message* aMsg, void** aIter);
+#endif
 private:
   nsRegion GetRegion();
 
   nsTArray<nsInvalidateRequestList::Request> mInvalidateRequests;
 };
 
 #endif // nsDOMNotifyPaintEvent_h_
--- a/content/events/src/nsDOMScrollAreaEvent.cpp
+++ b/content/events/src/nsDOMScrollAreaEvent.cpp
@@ -30,16 +30,20 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * 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 ***** */
 
+#ifdef MOZ_IPC
+#include "base/basictypes.h"
+#include "IPC/IPCMessageUtils.h"
+#endif
 #include "nsDOMScrollAreaEvent.h"
 #include "nsGUIEvent.h"
 #include "nsClientRect.h"
 
 nsDOMScrollAreaEvent::nsDOMScrollAreaEvent(nsPresContext *aPresContext,
                                            nsScrollAreaEvent *aEvent)
   : nsDOMUIEvent(aPresContext, aEvent)
 {
@@ -101,16 +105,74 @@ nsDOMScrollAreaEvent::InitScrollAreaEven
   nsresult rv = nsDOMUIEvent::InitUIEvent(aEventType, aCanBubble, aCancelable, aView, aDetail);
   NS_ENSURE_SUCCESS(rv, rv);
 
   mClientArea.SetRect(aX, aY, aWidth, aHeight);
 
   return NS_OK;
 }
 
+#ifdef MOZ_IPC
+void
+nsDOMScrollAreaEvent::Serialize(IPC::Message* aMsg,
+                                PRBool aSerializeInterfaceType)
+{
+  if (aSerializeInterfaceType) {
+    IPC::WriteParam(aMsg, NS_LITERAL_STRING("scrollareaevent"));
+  }
+
+  nsDOMUIEvent::Serialize(aMsg, PR_FALSE);
+
+  NS_ASSERTION(sizeof(PRInt32) == sizeof(float),
+               "PRInt32 and float should be the same size!");
+
+  float x = 0.0f;
+  GetX(&x);
+  IPC::WriteParam(aMsg, reinterpret_cast<PRInt32&>(x));
+
+  float y = 0.0f;
+  GetY(&y);
+  IPC::WriteParam(aMsg, reinterpret_cast<PRInt32&>(y));
+
+  float width = 0.0f;
+  GetWidth(&width);
+  IPC::WriteParam(aMsg, reinterpret_cast<PRInt32&>(width));
+
+  float height = 0.0f;
+  GetHeight(&height);
+  IPC::WriteParam(aMsg, reinterpret_cast<PRInt32&>(height));
+}
+
+PRBool
+nsDOMScrollAreaEvent::Deserialize(const IPC::Message* aMsg, void** aIter)
+{
+  NS_ENSURE_TRUE(nsDOMUIEvent::Deserialize(aMsg, aIter), PR_FALSE);
+
+  PRInt32 x_;
+  NS_ENSURE_TRUE(IPC::ReadParam(aMsg, aIter, &x_), PR_FALSE);
+  float x = reinterpret_cast<float&>(x_);
+
+  PRInt32 y_;
+  NS_ENSURE_TRUE(IPC::ReadParam(aMsg, aIter, &y_), PR_FALSE);
+  float y = reinterpret_cast<float&>(y_);
+
+  PRInt32 width_;
+  NS_ENSURE_TRUE(IPC::ReadParam(aMsg, aIter, &width_), PR_FALSE);
+  float width = reinterpret_cast<float&>(width_);
+
+  PRInt32 height_;
+  NS_ENSURE_TRUE(IPC::ReadParam(aMsg, aIter, &height_), PR_FALSE);
+  float height = reinterpret_cast<float&>(height_);
+
+  mClientArea.SetRect(x, y, width, height);
+
+  return PR_TRUE;
+}
+#endif
+
 nsresult
 NS_NewDOMScrollAreaEvent(nsIDOMEvent **aInstancePtrResult,
                          nsPresContext *aPresContext,
                          nsScrollAreaEvent *aEvent)
 {
   nsDOMScrollAreaEvent *ev = new nsDOMScrollAreaEvent(aPresContext, aEvent);
 
   if (!ev) {
--- a/content/events/src/nsDOMScrollAreaEvent.h
+++ b/content/events/src/nsDOMScrollAreaEvent.h
@@ -53,13 +53,17 @@ public:
   virtual ~nsDOMScrollAreaEvent();
 
   NS_DECL_ISUPPORTS_INHERITED
 
   NS_DECL_NSIDOMSCROLLAREAEVENT
 
   NS_FORWARD_TO_NSDOMUIEVENT
 
+#ifdef MOZ_IPC
+  virtual void Serialize(IPC::Message* aMsg, PRBool aSerializeInterfaceType);
+  virtual PRBool Deserialize(const IPC::Message* aMsg, void** aIter);
+#endif
 protected:
   nsClientRect mClientArea;
 };
 
 #endif // nsDOMScrollAreaEvent_h__
--- a/content/events/src/nsDOMUIEvent.cpp
+++ b/content/events/src/nsDOMUIEvent.cpp
@@ -32,16 +32,20 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * 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 ***** */
 
+#ifdef MOZ_IPC
+#include "base/basictypes.h"
+#include "IPC/IPCMessageUtils.h"
+#endif
 #include "nsCOMPtr.h"
 #include "nsDOMUIEvent.h"
 #include "nsIPresShell.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIDOMWindowInternal.h"
 #include "nsIDOMNode.h"
 #include "nsIContent.h"
 #include "nsContentUtils.h"
@@ -390,16 +394,40 @@ nsDOMUIEvent::DuplicatePrivateData()
   nsIntPoint screenPoint = GetScreenPoint();
   nsresult rv = nsDOMEvent::DuplicatePrivateData();
   if (NS_SUCCEEDED(rv)) {
     mEvent->refPoint = screenPoint;
   }
   return rv;
 }
 
+#ifdef MOZ_IPC
+void
+nsDOMUIEvent::Serialize(IPC::Message* aMsg, PRBool aSerializeInterfaceType)
+{
+  if (aSerializeInterfaceType) {
+    IPC::WriteParam(aMsg, NS_LITERAL_STRING("uievent"));
+  }
+
+  nsDOMEvent::Serialize(aMsg, PR_FALSE);
+
+  PRInt32 detail = 0;
+  GetDetail(&detail);
+  IPC::WriteParam(aMsg, detail);
+}
+
+PRBool
+nsDOMUIEvent::Deserialize(const IPC::Message* aMsg, void** aIter)
+{
+  NS_ENSURE_TRUE(nsDOMEvent::Deserialize(aMsg, aIter), PR_FALSE);
+  NS_ENSURE_TRUE(IPC::ReadParam(aMsg, aIter, &mDetail), PR_FALSE);
+  return PR_TRUE;
+}
+#endif
+
 nsresult NS_NewDOMUIEvent(nsIDOMEvent** aInstancePtrResult,
                           nsPresContext* aPresContext,
                           nsGUIEvent *aEvent) 
 {
   nsDOMUIEvent* it = new nsDOMUIEvent(aPresContext, aEvent);
   if (nsnull == it) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
--- a/content/events/src/nsDOMUIEvent.h
+++ b/content/events/src/nsDOMUIEvent.h
@@ -59,17 +59,20 @@ public:
   // nsIDOMUIEvent Interface
   NS_DECL_NSIDOMUIEVENT
 
   // nsIDOMNSUIEvent Interface
   NS_DECL_NSIDOMNSUIEVENT
 
   // nsIPrivateDOMEvent interface
   NS_IMETHOD DuplicatePrivateData();
-  
+#ifdef MOZ_IPC
+  virtual void Serialize(IPC::Message* aMsg, PRBool aSerializeInterfaceType);
+  virtual PRBool Deserialize(const IPC::Message* aMsg, void** aIter);
+#endif
   // nsIPrivateCompositionEvent interface
   NS_IMETHOD GetCompositionReply(nsTextEventReply** aReply);
   
   // Forward to nsDOMEvent
   NS_FORWARD_TO_NSDOMEVENT
 
   NS_FORWARD_NSIDOMNSEVENT(nsDOMEvent::)
 protected:
--- a/dom/ipc/Makefile.in
+++ b/dom/ipc/Makefile.in
@@ -42,16 +42,18 @@ VPATH = @srcdir@
 include $(DEPTH)/config/autoconf.mk
 
 MODULE = dom
 LIBRARY_NAME = domipc_s
 LIBXUL_LIBRARY = 1
 FORCE_STATIC_LIB = 1
 EXPORT_LIBRARY = 1
 
+EXPORTS = TabMessageUtils.h
+
 EXPORTS_NAMESPACES = mozilla mozilla/dom
 
 EXPORTS_mozilla = \
   TabTypes.h \
   $(NULL)
 
 EXPORTS_mozilla/dom = \
   ContentProcessChild.h \
@@ -60,15 +62,16 @@ EXPORTS_mozilla/dom = \
   $(NULL)
 
 CPPSRCS = \
   ContentProcessThread.cpp \
   ContentProcessParent.cpp \
   ContentProcessChild.cpp \
   TabParent.cpp \
   TabChild.cpp \
+  TabMessageUtils.cpp \
   $(NULL)
 
 include $(topsrcdir)/config/config.mk
 include $(topsrcdir)/ipc/chromium/chromium-config.mk
 include $(topsrcdir)/config/rules.mk
 
 DEFINES += -DBIN_SUFFIX='"$(BIN_SUFFIX)"'
--- a/dom/ipc/PIFrameEmbedding.ipdl
+++ b/dom/ipc/PIFrameEmbedding.ipdl
@@ -36,36 +36,39 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** 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;
 
 parent:
     /**
      * When child sends this message, parent should move focus to
      * the next or previous focusable element.
      */
     moveFocus(bool forward);
 
+    sendEvent(RemoteDOMEvent aEvent);
 child:
     createWidget(MagicWindowHandle parentWidget);
     destroyWidget();
 
     loadURL(nsCString uri);
 
     move(PRUint32 x,
          PRUint32 y,
@@ -83,16 +86,21 @@ child:
     sendMouseEvent(nsString aType,
                    PRInt32 aX, //XXX should be float, but ipdl doesn't seem to support that.
                    PRInt32 aY, //XXX - " -
                    PRInt32 aButton,
                    PRInt32 aClickCount,
                    PRInt32 aModifiers,
                    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
@@ -47,24 +47,38 @@
 #include "nsThreadUtils.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "mozilla/ipc/DocumentRendererChild.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsPIDOMWindow.h"
 #include "nsIDOMWindowUtils.h"
 #include "nsISupportsImpl.h"
 #include "nsIWebBrowserFocus.h"
+#include "nsIDOMEvent.h"
+#include "nsIPrivateDOMEvent.h"
 
 #ifdef MOZ_WIDGET_GTK2
 #include <gdk/gdkx.h>
 #include <gtk/gtk.h>
 #endif
 
 using namespace mozilla::dom;
 
+NS_IMPL_ISUPPORTS1(ContentListener, nsIDOMEventListener)
+
+NS_IMETHODIMP
+ContentListener::HandleEvent(nsIDOMEvent* aEvent)
+{
+  RemoteDOMEvent remoteEvent;
+  remoteEvent.mEvent = do_QueryInterface(aEvent);
+  NS_ENSURE_STATE(remoteEvent.mEvent);
+  mTabChild->SendsendEvent(remoteEvent);
+  return NS_OK;
+}
+
 TabChild::TabChild()
 {
     printf("creating %d!\n", NS_IsMainThread());
 }
 
 nsresult
 TabChild::Init()
 {
@@ -385,8 +399,22 @@ TabChild::RecvPDocumentRendererConstruct
     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);
 }
+
+bool
+TabChild::RecvactivateFrameEvent(const nsString& aType, const bool& capture)
+{
+  nsCOMPtr<nsPIDOMWindow> window = do_GetInterface(mWebNav);
+  NS_ENSURE_TRUE(window, true);
+  nsCOMPtr<nsIDOMEventTarget> chromeHandler =
+    do_QueryInterface(window->GetChromeEventHandler());
+  NS_ENSURE_TRUE(chromeHandler, true);
+  nsRefPtr<ContentListener> listener = new ContentListener(this);
+  NS_ENSURE_TRUE(listener, true);
+  chromeHandler->AddEventListener(aType, listener, capture);
+  return true;
+}
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -41,20 +41,34 @@
 
 #include "mozilla/dom/PIFrameEmbeddingChild.h"
 #include "nsIWebNavigation.h"
 #include "nsCOMPtr.h"
 #include "nsAutoPtr.h"
 #include "nsIWebBrowserChrome2.h"
 #include "nsIEmbeddingSiteWindow2.h"
 #include "nsIWebBrowserChromeFocus.h"
+#include "nsIDOMEventListener.h"
+#include "nsIDOMEventTarget.h"
 
 namespace mozilla {
 namespace dom {
 
+class TabChild;
+
+class ContentListener : public nsIDOMEventListener
+{
+public:
+  ContentListener(TabChild* aTabChild) : mTabChild(aTabChild) {}
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIDOMEVENTLISTENER
+protected:
+  TabChild* mTabChild;
+};
+
 class TabChild : public PIFrameEmbeddingChild,
                  public nsIWebBrowserChrome2,
                  public nsIEmbeddingSiteWindow2,
                  public nsIWebBrowserChromeFocus
 {
 public:
     TabChild();
     virtual ~TabChild();
@@ -77,16 +91,17 @@ public:
     virtual bool Recvactivate();
     virtual bool RecvsendMouseEvent(const nsString& aType,
                                     const PRInt32&  aX,
                                     const PRInt32&  aY,
                                     const PRInt32&  aButton,
                                     const PRInt32&  aClickCount,
                                     const PRInt32&  aModifiers,
                                     const bool&     aIgnoreRootScrollFrame);
+    virtual bool RecvactivateFrameEvent(const nsString& aType, const bool& capture);
     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);
new file mode 100644
--- /dev/null
+++ b/dom/ipc/TabMessageUtils.cpp
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** 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/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is 
+ * Mozilla Corporation
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *  Olli Pettay <Olli.Pettay@helsinki.fi>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * 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 ***** */
+
+#include "TabMessageUtils.h"
+#include "nsCOMPtr.h"
+#include "nsIDOMEvent.h"
+
+#ifdef CreateEvent
+#undef CreateEvent
+#endif
+
+#include "nsEventDispatcher.h"
+
+namespace mozilla {
+namespace dom {
+
+bool
+ReadRemoteEvent(const IPC::Message* aMsg, void** aIter,
+                RemoteDOMEvent* aResult)
+{
+  aResult->mEvent = nsnull;
+  nsString type;
+  NS_ENSURE_TRUE(ReadParam(aMsg, aIter, &type), false);
+
+  nsCOMPtr<nsIDOMEvent> event;
+  nsEventDispatcher::CreateEvent(nsnull, nsnull, type, getter_AddRefs(event));
+  aResult->mEvent = do_QueryInterface(event);
+  NS_ENSURE_TRUE(aResult->mEvent, false);
+
+  return aResult->mEvent->Deserialize(aMsg, aIter);
+}
+
+}
+}
new file mode 100644
--- /dev/null
+++ b/dom/ipc/TabMessageUtils.h
@@ -0,0 +1,85 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** 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/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is 
+ * Mozilla Corporation
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *  Olli Pettay <Olli.Pettay@helsinki.fi>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * 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 ***** */
+
+#ifndef TABMESSAGE_UTILS_H
+#define TABMESSAGE_UTILS_H
+
+#include "IPC/IPCMessageUtils.h"
+#include "nsIPrivateDOMEvent.h"
+#include "nsCOMPtr.h"
+
+namespace mozilla {
+namespace dom {
+struct RemoteDOMEvent
+{
+  nsCOMPtr<nsIPrivateDOMEvent> mEvent;
+};
+
+bool ReadRemoteEvent(const IPC::Message* aMsg, void** aIter,
+                     mozilla::dom::RemoteDOMEvent* aResult);
+
+}
+}
+
+namespace IPC {
+
+template<>
+struct ParamTraits<mozilla::dom::RemoteDOMEvent>
+{
+  typedef mozilla::dom::RemoteDOMEvent paramType;
+
+  static void Write(Message* aMsg, const paramType& aParam)
+  {
+    aParam.mEvent->Serialize(aMsg, PR_TRUE);
+  }
+
+  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  {
+    return mozilla::dom::ReadRemoteEvent(aMsg, aIter, aResult);
+  }
+
+  static void Log(const paramType& aParam, std::wstring* aLog)
+  {
+  }
+};
+
+
+}
+
+
+#endif
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -41,16 +41,20 @@
 #include "mozilla/ipc/GeckoThread.h"
 #include "mozilla/ipc/DocumentRendererParent.h"
 
 #include "nsIURI.h"
 #include "nsFocusManager.h"
 #include "nsCOMPtr.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIDOMElement.h"
+#include "nsEventDispatcher.h"
+#include "nsIDOMEventTarget.h"
+#include "nsIDOMEvent.h"
+#include "nsIPrivateDOMEvent.h"
 
 using mozilla::ipc::BrowserProcessSubThread;
 using mozilla::ipc::DocumentRendererParent;
 
 namespace mozilla {
 namespace dom {
 
 TabParent::TabParent()
@@ -70,16 +74,30 @@ TabParent::RecvmoveFocus(const bool& aFo
     PRUint32 type = aForward ? nsIFocusManager::MOVEFOCUS_FORWARD
                              : nsIFocusManager::MOVEFOCUS_BACKWARD;
     fm->MoveFocus(nsnull, mFrameElement, type, nsIFocusManager::FLAG_BYKEY, 
                   getter_AddRefs(dummy));
   }
   return true;
 }
 
+bool
+TabParent::RecvsendEvent(const RemoteDOMEvent& aEvent)
+{
+  nsCOMPtr<nsIDOMEvent> event = do_QueryInterface(aEvent.mEvent);
+  NS_ENSURE_TRUE(event, true);
+
+  nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(mFrameElement);
+  NS_ENSURE_TRUE(target, true);
+
+  PRBool dummy;
+  target->DispatchEvent(event, &dummy);
+  return true;
+}
+
 void
 TabParent::LoadURL(nsIURI* aURI)
 {
     nsCString spec;
     aURI->GetSpec(spec);
 
     SendloadURL(spec);
 }
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -52,16 +52,17 @@ namespace dom {
 class TabParent : public PIFrameEmbeddingParent
 {
 public:
     TabParent();
     virtual ~TabParent();
     void SetOwnerElement(nsIDOMElement* aElement) { mFrameElement = aElement; }
 
     virtual bool RecvmoveFocus(const bool& aForward);
+    virtual bool RecvsendEvent(const RemoteDOMEvent& aEvent);
 
     void LoadURL(nsIURI* aURI);
     void Move(PRUint32 x, PRUint32 y, PRUint32 width, PRUint32 height);
     void Activate();
     void SendMouseEvent(const nsAString& aType, float aX, float aY,
                         PRInt32 aButton, PRInt32 aClickCount,
                         PRInt32 aModifiers, PRBool aIgnoreRootScrollFrame);
 
--- a/dom/ipc/test.xul
+++ b/dom/ipc/test.xul
@@ -1,18 +1,62 @@
 <?xml version="1.0"?>
 <?xml-stylesheet href="chrome://global/skin" type="text/css"?>
 <window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
         width="800" height="800" orient="vertical">
   <script>
+
+    function dumpClientRect(r) {
+      dump(r.left + "," + r.top + "," + r.right + "," +
+           r.bottom + "," + r.width + "," + r.height + "\n");
+    }
+
+    function handleMozAfterPaint(e) {
+      return;
+      dump(e.type + "\n")
+      var rects = e.clientRects;
+      var i;
+      dump("\tclientRects:\n");
+      for (i = 0; i &lt; rects.length; ++i) {
+        var r = rects.item(i);
+        dump("\t\t");
+        dumpClientRect(rects.item(i));
+      }
+
+      dump("\tboundingClientRect\n\t\t");
+      dumpClientRect(e.boundingClientRect);
+
+      var paintRequests = e.paintRequests;
+      dump("\tpaintRequests\n");
+      for (i = 0; i &lt; paintRequests.length; ++i) {
+        var pr = paintRequests.item(i);
+        dump("\t\t");
+        dumpClientRect(pr.clientRect);
+        if (pr.reason)
+          dump("\t\t" + pr.reason + "\n");
+      }
+    }
+
+    function handleMozScrolledAreaChanged(e) {
+      return;
+      dump(e.type + "\n");
+      dump("\t" + e.x + "," + e.y + "," + e.width + "," + e.height + "\n");
+    }
+
     function restart() {
       var y = document.getElementById('page');
       var p = y.parentNode;
       p.removeChild(y);
       p.appendChild(y);
+
+      var fl = y.QueryInterface(Components.interfaces.nsIFrameLoaderOwner).frameLoader;
+      fl.activateFrameEvent("MozAfterPaint", true);
+      fl.activateFrameEvent("MozScrolledAreaChanged", true);
+      y.addEventListener("MozAfterPaint", handleMozAfterPaint, true);
+      y.addEventListener("MozScrolledAreaChanged", handleMozScrolledAreaChanged, true);
     }
     
     function loadURL(url) {
       document.getElementById('page').setAttribute('src', url);
     }
 
     function randomClick() {
        // First focus the remote frame, then dispatch click. This way remote frame gets focus before
--- a/security/manager/ssl/src/nsSmartCardEvent.cpp
+++ b/security/manager/ssl/src/nsSmartCardEvent.cpp
@@ -123,16 +123,30 @@ NS_IMETHODIMP_(nsEvent*) nsSmartCardEven
 }
 
 NS_IMETHODIMP nsSmartCardEvent::SetTrusted(PRBool aResult)
 {
   NS_ASSERTION(mPrivate, "SmartCardEvent called without Init");
   return mPrivate->SetTrusted(aResult);
 }
 
+void
+nsSmartCardEvent::Serialize(IPC::Message* aMsg,
+                            PRBool aSerializeInterfaceType)
+{
+  NS_ASSERTION(mPrivate, "SmartCardEvent called without Init");
+  mPrivate->Serialize(aMsg, aSerializeInterfaceType);
+}
+
+PRBool
+nsSmartCardEvent::Deserialize(const IPC::Message* aMsg, void** aIter)
+{
+  NS_ASSERTION(mPrivate, "SmartCardEvent called without Init");
+  return mPrivate->Deserialize(aMsg, aIter);
+}
 
 // IDOMNSEvent maps
 NS_IMETHODIMP nsSmartCardEvent::GetOriginalTarget(nsIDOMEventTarget * *aOriginalTarget)
 {
   NS_ASSERTION(mNSEvent, "SmartCardEvent called without Init");
   return mNSEvent->GetOriginalTarget(aOriginalTarget);
 }
 
--- a/security/manager/ssl/src/nsSmartCardEvent.h
+++ b/security/manager/ssl/src/nsSmartCardEvent.h
@@ -61,16 +61,19 @@ public:
   NS_DECL_NSIDOMNSEVENT
 
   //NS_DECL_NSIPRIVATEDOMEEVENT
   NS_IMETHOD DuplicatePrivateData();
   NS_IMETHOD SetTarget(nsIDOMEventTarget *aTarget);
   NS_IMETHOD_(nsEvent*) GetInternalNSEvent();
   NS_IMETHOD_(PRBool ) IsDispatchStopped();
   NS_IMETHOD SetTrusted(PRBool aResult);
+  virtual void Serialize(IPC::Message* aMsg,
+                         PRBool aSerializeInterfaceType);
+  virtual PRBool Deserialize(const IPC::Message* aMsg, void** aIter);
 
   NS_DECL_NSIDOMEVENT
 
 protected:
   nsCOMPtr<nsIDOMEvent> mInner;
   nsCOMPtr<nsIPrivateDOMEvent> mPrivate;
   nsCOMPtr<nsIDOMNSEvent> mNSEvent;
   nsString mTokenName;