Bug 802288: Make BluetoothOppManager shutdown at xpcom-shutdown event; r=echou
authorKyle Machulis <kyle@nonpolynomial.com>
Thu, 25 Oct 2012 18:25:46 -0700
changeset 111602 71e97a4400eab0fc6e1b32e953bfe43b129a30d2
parent 111601 e58288ffbfa023ee4d5af1302f3282a0f4a11e01
child 111603 d21b8f2c4cb65dfe0cb10d12544320acce803b13
push id93
push usernmatsakis@mozilla.com
push dateWed, 31 Oct 2012 21:26:57 +0000
reviewersechou
bugs802288
milestone19.0a1
Bug 802288: Make BluetoothOppManager shutdown at xpcom-shutdown event; r=echou
dom/bluetooth/BluetoothOppManager.cpp
dom/bluetooth/BluetoothOppManager.h
--- a/dom/bluetooth/BluetoothOppManager.cpp
+++ b/dom/bluetooth/BluetoothOppManager.cpp
@@ -10,31 +10,92 @@
 #include "BluetoothReplyRunnable.h"
 #include "BluetoothService.h"
 #include "BluetoothServiceUuid.h"
 #include "BluetoothUtils.h"
 #include "ObexBase.h"
 
 #include "mozilla/dom/bluetooth/BluetoothTypes.h"
 #include "mozilla/RefPtr.h"
+#include "mozilla/Services.h"
+#include "mozilla/StaticPtr.h"
+#include "nsIObserver.h"
+#include "nsIObserverService.h"
 #include "nsIInputStream.h"
 
 USING_BLUETOOTH_NAMESPACE
+using namespace mozilla;
 using namespace mozilla::ipc;
 
+class BluetoothOppManagerObserver : public nsIObserver
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIOBSERVER
+
+  BluetoothOppManagerObserver()
+  {
+  }
+
+  bool Init()
+  {
+    nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
+    if (NS_FAILED(obs->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false))) {
+      NS_WARNING("Failed to add shutdown observer!");
+      return false;
+    }
+
+    return true;
+  }
+
+  bool Shutdown()
+  {
+    nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
+    if (!obs ||
+        (NS_FAILED(obs->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID)))) {
+      NS_WARNING("Can't unregister observers, or already unregistered!");
+      return false;
+    }
+    return true;
+  }
+
+  ~BluetoothOppManagerObserver()
+  {
+    Shutdown();
+  }
+};
+
+namespace {
 // Sending system message "bluetooth-opp-update-progress" every 50kb
 static const uint32_t kUpdateProgressBase = 50 * 1024;
-
-static mozilla::RefPtr<BluetoothOppManager> sInstance;
+StaticRefPtr<BluetoothOppManager> sInstance;
+StaticRefPtr<BluetoothOppManagerObserver> sOppObserver;
 static nsCOMPtr<nsIInputStream> stream = nullptr;
 static uint32_t sSentFileLength = 0;
 static nsString sFileName;
 static uint32_t sFileLength = 0;
 static nsString sContentType;
 static int sUpdateProgressCounter = 0;
+static bool sInShutdown = false;
+}
+
+NS_IMETHODIMP
+BluetoothOppManagerObserver::Observe(nsISupports* aSubject,
+                                     const char* aTopic,
+                                     const PRUnichar* aData)
+{
+  MOZ_ASSERT(sInstance);
+
+  if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
+    return sInstance->HandleShutdown();
+  }
+
+  MOZ_ASSERT(false, "BluetoothOppManager got unexpected topic!");
+  return NS_ERROR_UNEXPECTED;
+}
 
 class ReadFileTask : public nsRunnable
 {
 public:
   ReadFileTask(nsIDOMBlob* aBlob) : mBlob(aBlob)
   {
     MOZ_ASSERT(NS_IsMainThread());
   }
@@ -156,16 +217,26 @@ BluetoothOppManager::Connect(const nsASt
 }
 
 void
 BluetoothOppManager::Disconnect()
 {
   CloseSocket();
 }
 
+nsresult
+BluetoothOppManager::HandleShutdown()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  sInShutdown = true;
+  CloseSocket();
+  sInstance = nullptr;
+  return NS_OK;
+}
+
 bool
 BluetoothOppManager::Listen()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   CloseSocket();
 
   BluetoothService* bs = BluetoothService::Get();
--- a/dom/bluetooth/BluetoothOppManager.h
+++ b/dom/bluetooth/BluetoothOppManager.h
@@ -55,16 +55,17 @@ public:
 
   void SendConnectRequest();
   void SendPutHeaderRequest(const nsAString& aFileName, int aFileSize);
   void SendPutRequest(uint8_t* aFileBody, int aFileBodyLength,
                       bool aFinal);
   void SendDisconnectRequest();
   void SendAbortRequest();
 
+  nsresult HandleShutdown();
 private:
   BluetoothOppManager();
   void StartFileTransfer(const nsString& aDeviceAddress,
                          bool aReceived,
                          const nsString& aFileName,
                          uint32_t aFileLength,
                          const nsString& aContentType);
   void FileTransferComplete(const nsString& aDeviceAddress,