Bug 860075 - Avoid duplicate BT signal observer registration from child process. r=echou, r=gyeh, a=tef+
authorJohn Lin <jolin@mozilla.com>
Fri, 19 Apr 2013 08:25:34 -0400
changeset 119137 9ef08dac0122c08cb3e8cf62965cb279d6382242
parent 119136 b72ffc9ec1745490a997fea1713b9b48bc1dca48
child 119138 c3761490ffac6df2c2e2b3a341842f7b89d1bfca
push id693
push userryanvm@gmail.com
push dateFri, 19 Apr 2013 12:25:43 +0000
reviewersechou, gyeh, tef
bugs860075
milestone18.0
Bug 860075 - Avoid duplicate BT signal observer registration from child process. r=echou, r=gyeh, a=tef+
dom/bluetooth/BluetoothService.cpp
dom/bluetooth/ipc/BluetoothServiceChildProcess.cpp
dom/bluetooth/ipc/BluetoothServiceChildProcess.h
--- a/dom/bluetooth/BluetoothService.cpp
+++ b/dom/bluetooth/BluetoothService.cpp
@@ -363,31 +363,40 @@ BluetoothService::UnregisterBluetoothSig
                                                    BluetoothSignalObserver* aHandler)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aHandler);
 
   BluetoothSignalObserverList* ol;
   if (mBluetoothSignalObserverTable.Get(aNodeName, &ol)) {
     ol->RemoveObserver(aHandler);
+    // We shouldn't have duplicate instances in the ObserverList, but there's
+    // no appropriate way to do duplication check while registering, so
+    // assertions are added here.
+    MOZ_ASSERT(!ol->RemoveObserver(aHandler));
     if (ol->Length() == 0) {
       mBluetoothSignalObserverTable.Remove(aNodeName);
     }
   }
   else {
     NS_WARNING("Node was never registered!");
   }
 }
 
 PLDHashOperator
 RemoveAllSignalHandlers(const nsAString& aKey,
                         nsAutoPtr<BluetoothSignalObserverList>& aData,
                         void* aUserArg)
 {
-  aData->RemoveObserver(static_cast<BluetoothSignalObserver*>(aUserArg));
+  BluetoothSignalObserver* handler = static_cast<BluetoothSignalObserver*>(aUserArg);
+  aData->RemoveObserver(handler);
+  // We shouldn't have duplicate instances in the ObserverList, but there's
+  // no appropriate way to do duplication check while registering, so
+  // assertions are added here.
+  MOZ_ASSERT(!aData->RemoveObserver(handler));
   return aData->Length() ? PL_DHASH_NEXT : PL_DHASH_REMOVE;
 }
 
 void
 BluetoothService::UnregisterAllSignalHandlers(BluetoothSignalObserver* aHandler)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aHandler);
--- a/dom/bluetooth/ipc/BluetoothServiceChildProcess.cpp
+++ b/dom/bluetooth/ipc/BluetoothServiceChildProcess.cpp
@@ -72,31 +72,31 @@ BluetoothServiceChildProcess::NoteDeadAc
   gBluetoothChild = nullptr;
 }
 
 void
 BluetoothServiceChildProcess::RegisterBluetoothSignalHandler(
                                               const nsAString& aNodeName,
                                               BluetoothSignalObserver* aHandler)
 {
-  if (gBluetoothChild) {
+  if (gBluetoothChild && !IsSignalRegistered(aNodeName)) {
     gBluetoothChild->SendRegisterSignalHandler(nsString(aNodeName));
   }
   BluetoothService::RegisterBluetoothSignalHandler(aNodeName, aHandler);
 }
 
 void
 BluetoothServiceChildProcess::UnregisterBluetoothSignalHandler(
                                               const nsAString& aNodeName,
                                               BluetoothSignalObserver* aHandler)
 {
-  if (gBluetoothChild) {
+  BluetoothService::UnregisterBluetoothSignalHandler(aNodeName, aHandler);
+  if (gBluetoothChild && !IsSignalRegistered(aNodeName)) {
     gBluetoothChild->SendUnregisterSignalHandler(nsString(aNodeName));
   }
-  BluetoothService::UnregisterBluetoothSignalHandler(aNodeName, aHandler);
 }
 
 nsresult
 BluetoothServiceChildProcess::GetDefaultAdapterPathInternal(
                                               BluetoothReplyRunnable* aRunnable)
 {
   SendRequest(aRunnable, DefaultAdapterPathRequest());
   return NS_OK;
--- a/dom/bluetooth/ipc/BluetoothServiceChildProcess.h
+++ b/dom/bluetooth/ipc/BluetoothServiceChildProcess.h
@@ -180,13 +180,18 @@ private:
 
   // Should never be called from the child
   virtual nsresult
   GetDevicePropertiesInternal(const BluetoothSignal& aSignal) MOZ_OVERRIDE;
 
   // This method should never be called from the child.
   virtual nsresult
   PrepareAdapterInternal(const nsAString& aPath) MOZ_OVERRIDE;
+
+  bool
+  IsSignalRegistered(const nsAString& aNodeName) {
+    return !!mBluetoothSignalObserverTable.Get(aNodeName);
+  }
 };
 
 END_BLUETOOTH_NAMESPACE
 
 #endif // mozilla_dom_bluetooth_ipc_bluetoothservicechildprocess_h__