Bug 533038 - 3. Support reading preferences from arbitrary jars, r=dwitte a=blocking-beta6
authorMichael Wu <mwu@mozilla.com>
Wed, 08 Sep 2010 20:38:12 -0700
changeset 52250 b32655a792347a55bd5831f8250805d3b936cb2f
parent 52249 4958e6add3c936fe32cffccfe6b2377c766cc9e8
child 52251 3e6d29c4ab619e0806f581987f3afb1c631b705e
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersdwitte, blocking-beta6
bugs533038
milestone2.0b6pre
Bug 533038 - 3. Support reading preferences from arbitrary jars, r=dwitte a=blocking-beta6
modules/libpref/public/nsIPrefService.idl
modules/libpref/src/nsPrefService.cpp
modules/libpref/src/nsPrefService.h
--- a/modules/libpref/public/nsIPrefService.idl
+++ b/modules/libpref/public/nsIPrefService.idl
@@ -36,16 +36,17 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsISupports.idl"
 #include "nsIPrefBranch.idl"
 
 interface nsIFile;
+interface nsILocalFile;
 
 /**
  * The nsIPrefService interface is the main entry point into the back end
  * preferences management library. The preference service is directly
  * responsible for the management of the preferences files and also facilitates
  * access to the preference branch object which allows the direct manipulation
  * of the preferences themselves.
  *
@@ -100,17 +101,16 @@ interface nsIPrefService : nsISupports
    * @return NS_OK File was written.
    * @return Other File failed to write.
    *
    * @see readUserPrefs
    * @see nsIFile
    */
   void savePrefFile(in nsIFile aFile);
 
-
   /**
    * Call to get a Preferences "Branch" which accesses user preference data.
    * Using a Set method on this object will always create or set a user
    * preference value. When using a Get method a user set value will be
    * returned if one exists, otherwise a default value will be returned.
    *
    * @param aPrefRoot The preference "root" on which to base this "branch".
    *                  For example, if the root "browser.startup." is used, the
@@ -148,16 +148,33 @@ interface nsIPrefService : nsISupports
    * @return nsIPrefBranch The object representing the requested default branch.
    *
    * @see getBranch
    */
   nsIPrefBranch getDefaultBranch(in string aPrefRoot);
 
 };
 
+[scriptable, uuid(00162579-0687-478d-8a52-f49714d4c1be)]
+interface nsIPrefServiceInternal : nsISupports
+{
+  /**
+   * Called to read the preferences in the defaults/preferences/
+   * directory of a zip file
+   *
+   * @param aFile The zip file to be read.
+   *
+   * @return NS_OK The file was read and processed.
+   * @return Other The file failed to read or contained invalid data.
+   *
+   * @see readUserPrefs
+   */
+  void readExtensionPrefs(in nsILocalFile aFile);
+};
+
 %{C++
 
 #define NS_PREFSERVICE_CID                             \
   { /* {1cd91b88-1dd2-11b2-92e1-ed22ed298000} */       \
     0x1cd91b88,                                        \
     0x1dd2,                                            \
     0x11b2,                                            \
     { 0x92, 0xe1, 0xed, 0x22, 0xed, 0x29, 0x80, 0x00 } \
--- a/modules/libpref/src/nsPrefService.cpp
+++ b/modules/libpref/src/nsPrefService.cpp
@@ -43,18 +43,21 @@
 
 #include "nsPrefService.h"
 #include "nsAppDirectoryServiceDefs.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsICategoryManager.h"
 #include "nsCategoryManagerUtils.h"
 #include "nsNetUtil.h"
 #include "nsIFile.h"
+#include "nsIInputStream.h"
 #include "nsILocalFile.h"
 #include "nsIObserverService.h"
+#include "nsIStringEnumerator.h"
+#include "nsIZipReader.h"
 #include "nsPrefBranch.h"
 #include "nsXPIDLString.h"
 #include "nsCRT.h"
 #include "nsCOMArray.h"
 #include "nsXPCOMCID.h"
 #include "nsAutoPtr.h"
 
 #include "nsQuickSort.h"
@@ -69,16 +72,17 @@
 
 #ifdef MOZ_OMNIJAR
 #include "mozilla/Omnijar.h"
 #include "nsZipArchive.h"
 #endif
 
 // Definitions
 #define INITIAL_PREF_FILES 10
+static NS_DEFINE_CID(kZipReaderCID, NS_ZIPREADER_CID);
 
 // Prototypes
 static nsresult openPrefFile(nsIFile* aFile);
 static nsresult pref_InitInitialObjects(void);
 static nsresult pref_LoadPrefsInDirList(const char *listId);
 
 //-----------------------------------------------------------------------------
 
@@ -101,16 +105,17 @@ nsPrefService::~nsPrefService()
  */
 
 NS_IMPL_THREADSAFE_ADDREF(nsPrefService)
 NS_IMPL_THREADSAFE_RELEASE(nsPrefService)
 
 NS_INTERFACE_MAP_BEGIN(nsPrefService)
     NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIPrefService)
     NS_INTERFACE_MAP_ENTRY(nsIPrefService)
+    NS_INTERFACE_MAP_ENTRY(nsIPrefServiceInternal)
     NS_INTERFACE_MAP_ENTRY(nsIObserver)
     NS_INTERFACE_MAP_ENTRY(nsIPrefBranch)
     NS_INTERFACE_MAP_ENTRY(nsIPrefBranch2)
     NS_INTERFACE_MAP_ENTRY(nsIPrefBranchInternal)
     NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
 NS_INTERFACE_MAP_END
 
 
@@ -168,16 +173,21 @@ nsresult nsPrefService::Init()
 
   observerService->AddObserver(this, "load-extension-defaults", PR_TRUE);
 
   return(rv);
 }
 
 NS_IMETHODIMP nsPrefService::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *someData)
 {
+#ifdef MOZ_IPC
+  if (XRE_GetProcessType() == GeckoProcessType_Content)
+    return NS_ERROR_NOT_AVAILABLE;
+#endif
+
   nsresult rv = NS_OK;
 
   if (!nsCRT::strcmp(aTopic, "profile-before-change")) {
     if (!nsCRT::strcmp(someData, NS_LITERAL_STRING("shutdown-cleanse").get())) {
       if (mCurrentFile) {
         mCurrentFile->Remove(PR_FALSE);
         mCurrentFile = nsnull;
       }
@@ -258,16 +268,65 @@ NS_IMETHODIMP nsPrefService::SavePrefFil
     NS_ERROR("cannot save prefs from content process");
     return NS_ERROR_NOT_AVAILABLE;
   }
 #endif
 
   return SavePrefFileInternal(aFile);
 }
 
+/* part of nsIPrefServiceInternal */
+NS_IMETHODIMP nsPrefService::ReadExtensionPrefs(nsILocalFile *aFile)
+{
+  nsresult rv;
+  nsCOMPtr<nsIZipReader> reader = do_CreateInstance(kZipReaderCID, &rv);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = reader->Open(aFile);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCOMPtr<nsIUTF8StringEnumerator> files;
+  rv = reader->FindEntries("defaults/preferences/*.(J|j)(S|s)$",
+                           getter_AddRefs(files));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  char buffer[4096];
+
+  PRBool more;
+  while (NS_SUCCEEDED(rv = files->HasMore(&more)) && more) {
+    nsCAutoString entry;
+    rv = files->GetNext(entry);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    nsCOMPtr<nsIInputStream> stream;
+    rv = reader->GetInputStream(entry.get(), getter_AddRefs(stream));
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    PRUint32 avail, read;
+
+    PrefParseState ps;
+    PREF_InitParseState(&ps, PREF_ReaderCallback, NULL);
+    while (NS_SUCCEEDED(rv = stream->Available(&avail)) && avail) {
+      rv = stream->Read(buffer, 4096, &read);
+      if (NS_FAILED(rv)) {
+        NS_WARNING("Pref stream read failed");
+        break;
+      }
+
+      rv = PREF_ParseBuf(&ps, buffer, read);
+      if (NS_FAILED(rv)) {
+        NS_WARNING("Pref stream parse failed");
+        break;
+      }
+    }
+    PREF_FinalizeParseState(&ps);
+  }
+  return rv;
+}
+
 NS_IMETHODIMP nsPrefService::GetBranch(const char *aPrefRoot, nsIPrefBranch **_retval)
 {
   nsresult rv;
 
   if ((nsnull != aPrefRoot) && (*aPrefRoot != '\0')) {
     // TODO: - cache this stuff and allow consumers to share branches (hold weak references I think)
     nsPrefBranch* prefBranch = new nsPrefBranch(aPrefRoot, PR_FALSE);
     if (!prefBranch)
--- a/modules/libpref/src/nsPrefService.h
+++ b/modules/libpref/src/nsPrefService.h
@@ -45,23 +45,25 @@
 #include "nsIPrefBranchInternal.h"
 #include "nsIObserver.h"
 #include "nsCOMPtr.h"
 #include "nsWeakReference.h"
 
 class nsIFile;
 
 class nsPrefService : public nsIPrefService,
+                      public nsIPrefServiceInternal,
                       public nsIObserver,
                       public nsIPrefBranchInternal,
                       public nsSupportsWeakReference
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIPREFSERVICE
+  NS_DECL_NSIPREFSERVICEINTERNAL
   NS_FORWARD_NSIPREFBRANCH(mRootBranch->)
   NS_FORWARD_NSIPREFBRANCH2(mRootBranch->)
   NS_DECL_NSIOBSERVER
 
   nsPrefService();
   virtual ~nsPrefService();
 
   nsresult Init();