Bug 786419 - Part 3 - Have the JS TCP sockets check if the app is offline r=jduell
authorValentin Gosu <valentin.gosu@gmail.com>
Sat, 23 Aug 2014 02:15:36 +0300
changeset 209170 e99c308964f8442e99618ab60be41426081382bc
parent 209169 9474c394d41be2504d3748491d3ab4a7c51b1cf7
child 209171 39d37ed686c38121ce6cdf7ed7be2c0519c8a20b
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersjduell
bugs786419
milestone35.0a1
Bug 786419 - Part 3 - Have the JS TCP sockets check if the app is offline r=jduell
dom/network/TCPSocketParent.cpp
dom/network/TCPSocketParent.h
--- a/dom/network/TCPSocketParent.cpp
+++ b/dom/network/TCPSocketParent.cpp
@@ -63,24 +63,64 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(TCPSocketParentBase)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(TCPSocketParentBase)
 
 TCPSocketParentBase::TCPSocketParentBase()
 : mIPCOpen(false)
 {
+  mObserver = new mozilla::net::OfflineObserver(this);
   mozilla::HoldJSObjects(this);
 }
 
 TCPSocketParentBase::~TCPSocketParentBase()
 {
+  if (mObserver) {
+    mObserver->RemoveObserver();
+  }
   mozilla::DropJSObjects(this);
 }
 
+nsresult
+TCPSocketParent::OfflineNotification(nsISupports *aSubject)
+{
+  nsCOMPtr<nsIAppOfflineInfo> info(do_QueryInterface(aSubject));
+  if (!info) {
+    return NS_OK;
+  }
+
+  uint32_t targetAppId = nsIScriptSecurityManager::UNKNOWN_APP_ID;
+  info->GetAppId(&targetAppId);
+
+  // Obtain App ID
+  uint32_t appId = nsIScriptSecurityManager::UNKNOWN_APP_ID;
+  const PContentParent *content = Manager()->Manager();
+  const InfallibleTArray<PBrowserParent*>& browsers = content->ManagedPBrowserParent();
+  if (browsers.Length() > 0) {
+    TabParent *tab = static_cast<TabParent*>(browsers[0]);
+    appId = tab->OwnAppId();
+  }
+
+  if (appId != targetAppId) {
+    return NS_OK;
+  }
+
+  // If the app is offline, close the socket
+  if (mSocket && NS_IsAppOffline(appId)) {
+    mSocket->Close();
+    mSocket = nullptr;
+    mIntermediaryObj = nullptr;
+    mIntermediary = nullptr;
+  }
+
+  return NS_OK;
+}
+
+
 void
 TCPSocketParentBase::ReleaseIPDLReference()
 {
   MOZ_ASSERT(mIPCOpen);
   mIPCOpen = false;
   this->Release();
 }
 
@@ -110,24 +150,30 @@ TCPSocketParent::RecvOpen(const nsString
   // tests without this loophole.
   if (net::UsingNeckoIPCSecurity() &&
       !AssertAppProcessPermission(Manager()->Manager(), "tcp-socket")) {
     FireInteralError(this, __LINE__);
     return true;
   }
 
   // Obtain App ID
-  uint32_t appId = nsIScriptSecurityManager::NO_APP_ID;
+  uint32_t appId = nsIScriptSecurityManager::UNKNOWN_APP_ID;
   const PContentParent *content = Manager()->Manager();
   const InfallibleTArray<PBrowserParent*>& browsers = content->ManagedPBrowserParent();
   if (browsers.Length() > 0) {
     TabParent *tab = static_cast<TabParent*>(browsers[0]);
     appId = tab->OwnAppId();
   }
 
+  if (NS_IsAppOffline(appId)) {
+    NS_ERROR("Can't open socket because app is offline");
+    FireInteralError(this, __LINE__);
+    return true;
+  }
+
   nsresult rv;
   mIntermediary = do_CreateInstance("@mozilla.org/tcp-socket-intermediary;1", &rv);
   if (NS_FAILED(rv)) {
     FireInteralError(this, __LINE__);
     return true;
   }
 
   rv = mIntermediary->Open(this, aHost, aPort, aUseSSL, aBinaryType, appId,
--- a/dom/network/TCPSocketParent.h
+++ b/dom/network/TCPSocketParent.h
@@ -6,41 +6,44 @@
 #define mozilla_dom_TCPSocketParent_h
 
 #include "mozilla/net/PTCPSocketParent.h"
 #include "nsITCPSocketParent.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsCOMPtr.h"
 #include "nsIDOMTCPSocket.h"
 #include "js/TypeDecls.h"
+#include "mozilla/net/OfflineObserver.h"
 
 #define TCPSOCKETPARENT_CID \
   { 0x4e7246c6, 0xa8b3, 0x426d, { 0x9c, 0x17, 0x76, 0xda, 0xb1, 0xe1, 0xe1, 0x4a } }
 
 namespace mozilla {
 namespace dom {
 
 class PBrowserParent;
 
 class TCPSocketParentBase : public nsITCPSocketParent
+                          , public mozilla::net::DisconnectableParent
 {
 public:
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(TCPSocketParentBase)
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
   void AddIPDLReference();
   void ReleaseIPDLReference();
 
 protected:
   TCPSocketParentBase();
   virtual ~TCPSocketParentBase();
 
   JS::Heap<JSObject*> mIntermediaryObj;
   nsCOMPtr<nsITCPSocketIntermediary> mIntermediary;
   nsCOMPtr<nsIDOMTCPSocket> mSocket;
+  nsRefPtr<mozilla::net::OfflineObserver> mObserver;
   bool mIPCOpen;
 };
 
 class TCPSocketParent : public mozilla::net::PTCPSocketParent
                       , public TCPSocketParentBase
 {
 public:
   NS_DECL_NSITCPSOCKETPARENT
@@ -53,16 +56,17 @@ public:
 
   virtual bool RecvStartTLS() MOZ_OVERRIDE;
   virtual bool RecvSuspend() MOZ_OVERRIDE;
   virtual bool RecvResume() MOZ_OVERRIDE;
   virtual bool RecvClose() MOZ_OVERRIDE;
   virtual bool RecvData(const SendableData& aData,
                         const uint32_t& aTrackingNumber) MOZ_OVERRIDE;
   virtual bool RecvRequestDelete() MOZ_OVERRIDE;
+  virtual nsresult OfflineNotification(nsISupports *) MOZ_OVERRIDE;
 
 private:
   virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
 };
 
 } // namespace dom
 } // namespace mozilla