Bug 806625 - Check if TabParent is destroyed before sending IPC message. r=cjones
authorPatrick Wang <kk1fff@patrickz.net>
Fri, 09 Nov 2012 22:09:24 -0800
changeset 113333 3d61038df8830adbcb892d8a9de3ab35f4637f84
parent 113332 2ea5d36b35a15f440c86bf825b1c3737234f4e59
child 113334 62fc36842e4417b2c999d40910bfdaf8e12410f7
push id23869
push useremorley@mozilla.com
push dateThu, 15 Nov 2012 16:18:16 +0000
treeherdermozilla-central@a37525d304d9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscjones
bugs806625
milestone19.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 806625 - Check if TabParent is destroyed before sending IPC message. r=cjones
dom/ipc/TabParent.cpp
dom/ipc/TabParent.h
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -81,16 +81,17 @@ TabParent::TabParent(const TabContext& a
   , mIMEComposing(false)
   , mIMECompositionEnding(false)
   , mIMECompositionStart(0)
   , mIMESeqno(0)
   , mEventCaptureDepth(0)
   , mDimensions(0, 0)
   , mDPI(0)
   , mShown(false)
+  , mIsDestroyed(false)
 {
 }
 
 TabParent::~TabParent()
 {
 }
 
 void
@@ -98,30 +99,35 @@ TabParent::SetOwnerElement(nsIDOMElement
 {
   mFrameElement = aElement;
   TryCacheDPI();
 }
 
 void
 TabParent::Destroy()
 {
+  if (mIsDestroyed) {
+    return;
+  }
+
   // If this fails, it's most likely due to a content-process crash,
   // and auto-cleanup will kick in.  Otherwise, the child side will
   // destroy itself and send back __delete__().
   unused << SendDestroy();
 
   const InfallibleTArray<PIndexedDBParent*>& idbParents =
     ManagedPIndexedDBParent();
   for (uint32_t i = 0; i < idbParents.Length(); ++i) {
     static_cast<IndexedDBParent*>(idbParents[i])->Disconnect();
   }
 
   if (RenderFrameParent* frame = GetRenderFrame()) {
     frame->Destroy();
   }
+  mIsDestroyed = true;
 }
 
 bool
 TabParent::Recv__delete__()
 {
   ContentParent* cp = static_cast<ContentParent*>(Manager());
   cp->NotifyTabDestroyed(this);
   return true;
@@ -209,16 +215,19 @@ TabParent::AnswerCreateWindow(PBrowserPa
 
     *retval = frameLoader->GetRemoteBrowser();
     return true;
 }
 
 void
 TabParent::LoadURL(nsIURI* aURI)
 {
+    if (mIsDestroyed) {
+      return;
+    }
     if (!mShown) {
       nsAutoCString spec;
       if (aURI) {
         aURI->GetSpec(spec);
       }
       NS_WARNING(nsPrintfCString("TabParent::LoadURL(%s) called before "
                                  "Show(). Ignoring LoadURL.\n", spec.get()).get());
       return;
@@ -231,60 +240,77 @@ TabParent::LoadURL(nsIURI* aURI)
 }
 
 void
 TabParent::Show(const nsIntSize& size)
 {
     // sigh
     mShown = true;
     mDimensions = size;
-    unused << SendShow(size);
+    if (!mIsDestroyed) {
+      unused << SendShow(size);
+    }
 }
 
 void
 TabParent::UpdateDimensions(const nsRect& rect, const nsIntSize& size)
 {
+  if (mIsDestroyed) {
+    return;
+  }
   unused << SendUpdateDimensions(rect, size);
   if (RenderFrameParent* rfp = GetRenderFrame()) {
     rfp->NotifyDimensionsChanged(size.width, size.height);
   }
   mDimensions = size;
 }
 
 void
 TabParent::UpdateFrame(const FrameMetrics& aFrameMetrics)
 {
-  unused << SendUpdateFrame(aFrameMetrics);
+  if (!mIsDestroyed) {
+    unused << SendUpdateFrame(aFrameMetrics);
+  }
 }
 
 void TabParent::HandleDoubleTap(const nsIntPoint& aPoint)
 {
-  unused << SendHandleDoubleTap(aPoint);
+  if (!mIsDestroyed) {
+    unused << SendHandleDoubleTap(aPoint);
+  }
 }
 
 void TabParent::HandleSingleTap(const nsIntPoint& aPoint)
 {
-  unused << SendHandleSingleTap(aPoint);
+  if (!mIsDestroyed) {
+    unused << SendHandleSingleTap(aPoint);
+  }
 }
 
 void TabParent::HandleLongTap(const nsIntPoint& aPoint)
 {
-  unused << SendHandleLongTap(aPoint);
+  if (!mIsDestroyed) {
+    unused << SendHandleLongTap(aPoint);
+  }
 }
 
 void
 TabParent::Activate()
 {
+  if (!mIsDestroyed) {
     unused << SendActivate();
+  }
 }
 
 void
 TabParent::Deactivate()
 {
-  unused << SendDeactivate();
+  if (!mIsDestroyed) {
+    unused << SendDeactivate();
+  }
 }
 
 NS_IMETHODIMP
 TabParent::Init(nsIDOMWindow *window)
 {
   return NS_OK;
 }
 
@@ -335,55 +361,71 @@ TabParent::DeallocPContentPermissionRequ
   return true;
 }
 
 void
 TabParent::SendMouseEvent(const nsAString& aType, float aX, float aY,
                           int32_t aButton, int32_t aClickCount,
                           int32_t aModifiers, bool aIgnoreRootScrollFrame)
 {
-  unused << PBrowserParent::SendMouseEvent(nsString(aType), aX, aY,
-                                           aButton, aClickCount,
-                                           aModifiers, aIgnoreRootScrollFrame);
+  if (!mIsDestroyed) {
+    unused << PBrowserParent::SendMouseEvent(nsString(aType), aX, aY,
+                                             aButton, aClickCount,
+                                             aModifiers, aIgnoreRootScrollFrame);
+  }
 }
 
 void
 TabParent::SendKeyEvent(const nsAString& aType,
                         int32_t aKeyCode,
                         int32_t aCharCode,
                         int32_t aModifiers,
                         bool aPreventDefault)
 {
-  unused << PBrowserParent::SendKeyEvent(nsString(aType), aKeyCode, aCharCode,
-                                         aModifiers, aPreventDefault);
+  if (!mIsDestroyed) {
+    unused << PBrowserParent::SendKeyEvent(nsString(aType), aKeyCode, aCharCode,
+                                           aModifiers, aPreventDefault);
+  }
 }
 
 bool TabParent::SendRealMouseEvent(nsMouseEvent& event)
 {
+  if (mIsDestroyed) {
+    return false;
+  }
   nsMouseEvent e(event);
   MaybeForwardEventToRenderFrame(event, &e);
   return PBrowserParent::SendRealMouseEvent(e);
 }
 
 bool TabParent::SendMouseWheelEvent(WheelEvent& event)
 {
+  if (mIsDestroyed) {
+    return false;
+  }
   WheelEvent e(event);
   MaybeForwardEventToRenderFrame(event, &e);
   return PBrowserParent::SendMouseWheelEvent(event);
 }
 
 bool TabParent::SendRealKeyEvent(nsKeyEvent& event)
 {
+  if (mIsDestroyed) {
+    return false;
+  }
   nsKeyEvent e(event);
   MaybeForwardEventToRenderFrame(event, &e);
   return PBrowserParent::SendRealKeyEvent(e);
 }
 
 bool TabParent::SendRealTouchEvent(nsTouchEvent& event)
 {
+  if (mIsDestroyed) {
+    return false;
+  }
   if (event.message == NS_TOUCH_START) {
     MOZ_ASSERT((!sEventCapturer && mEventCaptureDepth == 0) ||
                (sEventCapturer == this && mEventCaptureDepth > 0));
     // We want to capture all remaining touch events in this series
     // for fast-path dispatch.
     sEventCapturer = this;
     ++mEventCaptureDepth;
   }
@@ -642,16 +684,19 @@ TabParent::HandleQueryContentEvent(nsQue
     break;
   }
   return true;
 }
 
 bool
 TabParent::SendCompositionEvent(nsCompositionEvent& event)
 {
+  if (mIsDestroyed) {
+    return false;
+  }
   mIMEComposing = event.message != NS_COMPOSITION_END;
   mIMECompositionStart = NS_MIN(mIMESelectionAnchor, mIMESelectionFocus);
   if (mIMECompositionEnding)
     return true;
   event.seqno = ++mIMESeqno;
   return PBrowserParent::SendCompositionEvent(event);
 }
 
@@ -660,16 +705,19 @@ TabParent::SendCompositionEvent(nsCompos
  * NS_TEXT_TEXT event to finalize or clear the composition, respectively
  *
  * Because the event will not reach content in time, we intercept it
  * here and pass the text as the EndIMEComposition return value
  */
 bool
 TabParent::SendTextEvent(nsTextEvent& event)
 {
+  if (mIsDestroyed) {
+    return false;
+  }
   if (mIMECompositionEnding) {
     mIMECompositionText = event.theText;
     return true;
   }
 
   // We must be able to simulate the selection because
   // we might not receive selection updates in time
   if (!mIMEComposing) {
@@ -680,16 +728,19 @@ TabParent::SendTextEvent(nsTextEvent& ev
 
   event.seqno = ++mIMESeqno;
   return PBrowserParent::SendTextEvent(event);
 }
 
 bool
 TabParent::SendSelectionEvent(nsSelectionEvent& event)
 {
+  if (mIsDestroyed) {
+    return false;
+  }
   mIMESelectionAnchor = event.mOffset + (event.mReversed ? event.mLength : 0);
   mIMESelectionFocus = event.mOffset + (!event.mReversed ? event.mLength : 0);
   event.seqno = ++mIMESeqno;
   return PBrowserParent::SendSelectionEvent(event);
 }
 
 /*static*/ TabParent*
 TabParent::GetFrom(nsFrameLoader* aFrameLoader)
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -291,14 +291,17 @@ private:
     // notify it of input events targeting us.
     bool UseAsyncPanZoom();
     // If we have a render frame currently, notify it that we're about
     // to dispatch |aEvent| to our child.  If there's a relevant
     // transform in place, |aOutEvent| is the transformed |aEvent| to
     // dispatch to content.
     void MaybeForwardEventToRenderFrame(const nsInputEvent& aEvent,
                                         nsInputEvent* aOutEvent);
+    // When true, the TabParent is invalid and we should not send IPC messages
+    // anymore.
+    bool mIsDestroyed;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif