Bug 827311 - Remote file update notifications. r=bent a=blocking-basecamp
authorDoug Turner <dougt@dougt.org>
Wed, 09 Jan 2013 07:03:28 -0800
changeset 118062 4cc28f611f29cb25cfde3a72e27285b5d21aae19
parent 118061 c00c601dd9c75da96bfca383aff93d54395fb417
child 118063 0ee278d8174d90e487d4c37efad79fdaf4dc8404
push id182
push useramarchesini@mozilla.com
push dateWed, 09 Jan 2013 17:11:14 +0000
reviewersbent, blocking-basecamp
bugs827311
milestone18.0
Bug 827311 - Remote file update notifications. r=bent a=blocking-basecamp
dom/bluetooth/BluetoothOppManager.cpp
dom/camera/GonkCameraControl.cpp
dom/devicestorage/DeviceStorage.h
dom/devicestorage/nsDeviceStorage.cpp
dom/ipc/ContentChild.cpp
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
dom/ipc/PContent.ipdl
--- a/dom/bluetooth/BluetoothOppManager.cpp
+++ b/dom/bluetooth/BluetoothOppManager.cpp
@@ -1274,17 +1274,17 @@ BluetoothOppManager::OnDisconnect()
       if (!mSuccessFlag) {
         DeleteReceivedFile();
       } else if (mDsFile) {
         nsString data;
         CopyASCIItoUTF16("modified", data);
 
         nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
         if (obs) {
-          obs->NotifyObservers(mDsFile, "file-watcher-update", data.get());
+          obs->NotifyObservers(mDsFile, "file-watcher-notify", data.get());
         }
       }
     }
 
     if (!mSuccessFlag) {
       FileTransferComplete();
     }
 
--- a/dom/camera/GonkCameraControl.cpp
+++ b/dom/camera/GonkCameraControl.cpp
@@ -908,17 +908,17 @@ public:
 
   NS_IMETHOD Run()
   {
     MOZ_ASSERT(NS_IsMainThread());
 
     nsString data;
     CopyASCIItoUTF16(mType, data);
     nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
-    obs->NotifyObservers(mFile, "file-watcher-update", data.get());
+    obs->NotifyObservers(mFile, "file-watcher-notify", data.get());
     return NS_OK;
   }
 
 private:
   nsRefPtr<DeviceStorageFile> mFile;
   nsCString mType;
 };
 
--- a/dom/devicestorage/DeviceStorage.h
+++ b/dom/devicestorage/DeviceStorage.h
@@ -5,16 +5,17 @@
 #ifndef DeviceStorage_h
 #define DeviceStorage_h
 
 #include "nsIDOMDeviceStorage.h"
 #include "nsIFile.h"
 #include "nsIPrincipal.h"
 #include "nsIObserver.h"
 #include "nsDOMEventTargetHelper.h"
+#include "mozilla/StaticPtr.h"
 
 class nsIInputStream;
 
 class DeviceStorageFile MOZ_FINAL
   : public nsISupports {
 public:
   nsCOMPtr<nsIFile> mFile;
   nsString mPath;
@@ -40,16 +41,28 @@ public:
 
   static void DirectoryDiskUsage(nsIFile* aFile, uint64_t* aSoFar, const nsAString& aStorageType);
 
 private:
   void NormalizeFilePath();
   void AppendRelativePath();
 };
 
+class FileUpdateDispatcher MOZ_FINAL
+  : public nsIObserver
+{
+ public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIOBSERVER
+
+  static FileUpdateDispatcher* GetSingleton();
+ private:
+  static mozilla::StaticRefPtr<FileUpdateDispatcher> sSingleton;
+};
+
 class nsDOMDeviceStorage MOZ_FINAL
   : public nsIDOMDeviceStorage
   , public nsDOMEventTargetHelper
   , public nsIObserver
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIDOMDEVICESTORAGE
--- a/dom/devicestorage/nsDeviceStorage.cpp
+++ b/dom/devicestorage/nsDeviceStorage.cpp
@@ -217,16 +217,66 @@ DeviceStorageTypeChecker::GetAccessForRe
       aAccessResult.AssignLiteral("create");
       break;
     default:
       aAccessResult.AssignLiteral("undefined");
   }
   return NS_OK;
 }
 
+
+NS_IMPL_ISUPPORTS1(FileUpdateDispatcher, nsIObserver)
+
+mozilla::StaticRefPtr<FileUpdateDispatcher> FileUpdateDispatcher::sSingleton;
+
+FileUpdateDispatcher*
+FileUpdateDispatcher::GetSingleton()
+{
+  if (sSingleton) {
+    return sSingleton;
+  }
+
+  sSingleton = new FileUpdateDispatcher();
+  nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
+  obs->AddObserver(sSingleton, "file-watcher-notify", false);
+  ClearOnShutdown(&sSingleton);
+
+  return sSingleton;
+}
+
+NS_IMETHODIMP
+FileUpdateDispatcher::Observe(nsISupports *aSubject,
+                              const char *aTopic,
+                              const PRUnichar *aData)
+{
+  if (XRE_GetProcessType() != GeckoProcessType_Default) {
+
+    DeviceStorageFile* file = static_cast<DeviceStorageFile*>(aSubject);
+    if (!file || !file->mFile) {
+      NS_WARNING("Device storage file looks invalid!");
+      return NS_OK;
+    }
+
+    nsString fullpath;
+    nsresult rv = file->mFile->GetPath(fullpath);
+    if (NS_FAILED(rv)) {
+      NS_WARNING("Could not get path from the nsIFile!");
+      return NS_OK;
+    }
+
+    ContentChild::GetSingleton()->SendFilePathUpdateNotify(file->mStorageType,
+                                                           fullpath,
+                                                           NS_ConvertUTF16toUTF8(aData));
+  } else {
+    nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
+    obs->NotifyObservers(aSubject, "file-watcher-update", aData);
+  }
+  return NS_OK;
+}
+
 class IOEventComplete : public nsRunnable
 {
 public:
   IOEventComplete(DeviceStorageFile *aFile, const char *aType)
     : mFile(aFile)
     , mType(aType)
   {
   }
@@ -234,17 +284,18 @@ public:
   ~IOEventComplete() {}
 
   NS_IMETHOD Run()
   {
     NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
     nsString data;
     CopyASCIItoUTF16(mType, data);
     nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
-    obs->NotifyObservers(mFile, "file-watcher-update", data.get());
+
+    obs->NotifyObservers(mFile, "file-watcher-notify", data.get());
     return NS_OK;
   }
 
 private:
   nsRefPtr<DeviceStorageFile> mFile;
   nsCString mType;
 };
 
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -332,16 +332,19 @@ ContentChild::InitXPCOM()
 
     mConsoleListener = new ConsoleListener(this);
     if (NS_FAILED(svc->RegisterListener(mConsoleListener)))
         NS_WARNING("Couldn't register console listener for child process");
 
     bool isOffline;
     SendGetXPCOMProcessAttributes(&isOffline);
     RecvSetOffline(isOffline);
+
+    DebugOnly<FileUpdateDispatcher*> observer = FileUpdateDispatcher::GetSingleton();
+    NS_ASSERTION(observer, "FileUpdateDispatcher is null");
 }
 
 PMemoryReportRequestChild*
 ContentChild::AllocPMemoryReportRequest()
 {
     return new MemoryReportRequestChild();
 }
 
@@ -1019,17 +1022,17 @@ ContentChild::RecvScreenSizeChanged(cons
 
 bool
 ContentChild::RecvFlushMemory(const nsString& reason)
 {
     nsCOMPtr<nsIObserverService> os =
         mozilla::services::GetObserverService();
     if (os)
         os->NotifyObservers(nullptr, "memory-pressure", reason.get());
-  return true;
+    return true;
 }
 
 bool
 ContentChild::RecvActivateA11y()
 {
 #ifdef ACCESSIBILITY
     // Start accessibility in content process if it's running in chrome
     // process.
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -506,16 +506,19 @@ ContentParent::Init()
 
 #ifdef ACCESSIBILITY
     // If accessibility is running in chrome process then start it in content
     // process.
     if (nsIPresShell::IsAccessibilityActive()) {
         unused << SendActivateA11y();
     }
 #endif
+
+    DebugOnly<FileUpdateDispatcher*> observer = FileUpdateDispatcher::GetSingleton();
+    NS_ASSERTION(observer, "FileUpdateDispatcher is null");
 }
 
 void
 ContentParent::SetManifestFromPreallocated(const nsAString& aAppManifestURL)
 {
     MOZ_ASSERT(mAppManifestURL == MAGIC_PREALLOCATED_APP_MANIFEST_URL);
     // Clients should think of mAppManifestURL as const ... we're
     // bending the rules here just for the preallocation hack.
@@ -1993,16 +1996,35 @@ ContentParent::RecvAsyncMessage(const ns
 
     ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()),
                         aMsg, false, &cloneData, nullptr, nullptr);
   }
   return true;
 }
 
 bool
+ContentParent::RecvFilePathUpdateNotify(const nsString& aType, const nsString& aFilePath, const nsCString& aReason)
+{
+    nsCOMPtr<nsIFile> file;
+    nsresult rv = NS_NewLocalFile(aFilePath, false, getter_AddRefs(file));
+    if (NS_FAILED(rv)) {
+        // ignore
+        return true;
+    }
+    nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(aType, file);
+
+    nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
+    if (!obs) {
+        return false;
+    }
+    obs->NotifyObservers(dsf, "file-watcher-update", NS_ConvertASCIItoUTF16(aReason).get());
+    return true;
+}
+
+bool
 ContentParent::RecvAddGeolocationListener(const IPC::Principal& aPrincipal)
 {
 #ifdef MOZ_PERMISSIONS
   if (Preferences::GetBool("geo.testing.ignore_ipc_principal", false) == false) {
     nsIPrincipal* principal = aPrincipal;
     if (principal == nullptr) {
       KillHard();
       return true;
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -302,16 +302,20 @@ private:
     virtual bool RecvLoadURIExternal(const URIParams& uri);
 
     virtual bool RecvSyncMessage(const nsString& aMsg,
                                  const ClonedMessageData& aData,
                                  InfallibleTArray<nsString>* aRetvals);
     virtual bool RecvAsyncMessage(const nsString& aMsg,
                                   const ClonedMessageData& aData);
 
+    virtual bool RecvFilePathUpdateNotify(const nsString& aType,
+                                          const nsString& aFilePath,
+                                          const nsCString& aReason);
+
     virtual bool RecvAddGeolocationListener(const IPC::Principal& aPrincipal);
     virtual bool RecvRemoveGeolocationListener();
     virtual bool RecvSetGeolocationHigherAccuracy(const bool& aEnable);
 
     virtual bool RecvConsoleMessage(const nsString& aMessage);
     virtual bool RecvScriptError(const nsString& aMessage,
                                  const nsString& aSourceName,
                                  const nsString& aSourceLine,
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -442,14 +442,17 @@ parent:
         returns (bool value);
 
     sync AudioChannelRegisterType(AudioChannelType aType);
     sync AudioChannelUnregisterType(AudioChannelType aType,
                                     bool aElementHidden);
 
     async AudioChannelChangedNotification();
 
+    async FilePathUpdateNotify(nsString aType,
+                               nsString aFilepath,
+                               nsCString aReason);
 both:
      AsyncMessage(nsString aMessage, ClonedMessageData aData);
 };
 
 }
 }