Bug 837932 - Update dir svc media paths for Win7 and up - media dirs should point to Library default save locations. r=bsmedberg
authorJim Mathies <jmathies@mozilla.com>
Mon, 11 Feb 2013 13:03:54 -0600
changeset 121532 0d714dcba97926e367d655d152568dc132997fe8
parent 121531 99e8b116dd0973ee7ef888eabb0a01ca4ea3b840
child 121533 50df17d70386a66712e708873de7cdea130b6410
push id24296
push useremorley@mozilla.com
push dateTue, 12 Feb 2013 14:43:19 +0000
treeherdermozilla-central@860d7a47b675 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbsmedberg
bugs837932
milestone21.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 837932 - Update dir svc media paths for Win7 and up - media dirs should point to Library default save locations. r=bsmedberg
xpcom/io/SpecialSystemDirectory.cpp
xpcom/io/SpecialSystemDirectory.h
xpcom/io/nsDirectoryService.cpp
xpcom/io/nsDirectoryServiceAtomList.h
xpcom/io/nsDirectoryServiceDefs.h
--- a/xpcom/io/SpecialSystemDirectory.cpp
+++ b/xpcom/io/SpecialSystemDirectory.cpp
@@ -1,25 +1,29 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "SpecialSystemDirectory.h"
 #include "nsString.h"
 #include "nsDependentString.h"
+#include "nsAutoPtr.h"
 
 #if defined(XP_WIN)
 
 #include <windows.h>
 #include <shlobj.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
 #include <direct.h>
+#include <shlobj.h>
+#include <knownfolders.h>
+#include <guiddef.h>
 
 #elif defined(XP_OS2)
 
 #define MAX_PATH _MAX_PATH
 #define INCL_WINWORKPLACE
 #define INCL_DOSMISC
 #define INCL_DOSMODULEMGR
 #define INCL_DOSPROCESS
@@ -96,19 +100,18 @@ static nsresult GetKnownFolder(GUID* gui
     nsresult rv = NS_NewLocalFile(nsDependentString(path),
                                   true,
                                   aFile);
 
     CoTaskMemFree(path);
     return rv;
 }
 
-//----------------------------------------------------------------------------------------
-static nsresult GetWindowsFolder(int folder, nsIFile** aFile)
-//----------------------------------------------------------------------------------------
+static nsresult
+GetWindowsFolder(int folder, nsIFile** aFile)
 {
     WCHAR path_orig[MAX_PATH + 3];
     WCHAR *path = path_orig+1;
     HRESULT result = SHGetSpecialFolderPathW(NULL, path, folder, true);
 
     if (!SUCCEEDED(result))
         return NS_ERROR_FAILURE;
 
@@ -118,16 +121,75 @@ static nsresult GetWindowsFolder(int fol
     {
         path[len]   = L'\\';
         path[++len] = L'\0';
     }
 
     return NS_NewLocalFile(nsDependentString(path, len), true, aFile);
 }
 
+__inline HRESULT
+SHLoadLibraryFromKnownFolder(REFKNOWNFOLDERID aFolderId, DWORD aMode,
+                             REFIID riid, void **ppv)
+{
+    *ppv = NULL;
+    IShellLibrary *plib;
+    HRESULT hr = CoCreateInstance(CLSID_ShellLibrary, NULL,
+                                  CLSCTX_INPROC_SERVER,
+                                  IID_PPV_ARGS(&plib));
+    if (SUCCEEDED(hr)) {
+        hr = plib->LoadLibraryFromKnownFolder(aFolderId, aMode);
+        if (SUCCEEDED(hr)) {
+            hr = plib->QueryInterface(riid, ppv);
+        }
+        plib->Release();
+    }
+    return hr;
+}
+
+/*
+ * Check to see if we're on Win7 and up, and if so, returns the default
+ * save-to location for the Windows Library passed in through aFolderId.
+ * Otherwise falls back on pre-win7 GetWindowsFolder.
+ */
+static nsresult
+GetLibrarySaveToPath(int aFallbackFolderId, REFKNOWNFOLDERID aFolderId,
+                     nsIFile** aFile)
+{
+    // Skip off checking for library support if the os is Vista or lower.
+    DWORD dwVersion = GetVersion();
+    if ((DWORD)(LOBYTE(LOWORD(dwVersion))) < 6 ||
+        ((DWORD)(LOBYTE(LOWORD(dwVersion))) == 6 &&
+         (DWORD)(HIBYTE(LOWORD(dwVersion))) == 0))
+      return GetWindowsFolder(aFallbackFolderId, aFile);
+
+    nsRefPtr<IShellLibrary> shellLib;
+    nsRefPtr<IShellItem> savePath;
+    HRESULT hr =
+        SHLoadLibraryFromKnownFolder(aFolderId, STGM_READ,
+                                     IID_IShellLibrary, getter_AddRefs(shellLib));
+
+    if (shellLib &&
+        SUCCEEDED(shellLib->GetDefaultSaveFolder(DSFT_DETECT, IID_IShellItem,
+                                                 getter_AddRefs(savePath)))) {
+        PRUnichar* str = nullptr;
+        if (SUCCEEDED(savePath->GetDisplayName(SIGDN_FILESYSPATH, &str))) {
+            nsAutoString path;
+            path.Assign(str);
+            path.AppendLiteral("\\");
+            nsresult rv =
+                NS_NewLocalFile(path, false, aFile);
+            CoTaskMemFree(str);
+            return rv;
+        }
+    }
+
+    return GetWindowsFolder(aFallbackFolderId, aFile);
+}
+
 /**
  * Provides a fallback for getting the path to APPDATA or LOCALAPPDATA by
  * querying the registry when the call to SHGetSpecialFolderPathW is unable to
  * provide these paths (Bug 513958).
  */
 static nsresult GetRegWindowsAppDataFolder(bool aLocal, nsIFile** aFile)
 {
     HKEY key;
@@ -742,27 +804,39 @@ GetSpecialSystemDirectory(SystemDirector
         }
         case Win_LocalAppdata:
         {
             nsresult rv = GetWindowsFolder(CSIDL_LOCAL_APPDATA, aFile);
             if (NS_FAILED(rv))
                 rv = GetRegWindowsAppDataFolder(true, aFile);
             return rv;
         }
+        case Win_Documents:
+        {
+            return GetLibrarySaveToPath(CSIDL_MYDOCUMENTS,
+                                        FOLDERID_DocumentsLibrary,
+                                        aFile);
+        }
         case Win_Pictures:
         {
-            return GetWindowsFolder(CSIDL_MYPICTURES, aFile);
+            return GetLibrarySaveToPath(CSIDL_MYPICTURES,
+                                        FOLDERID_PicturesLibrary,
+                                        aFile);
         }
         case Win_Music:
         {
-            return GetWindowsFolder(CSIDL_MYMUSIC, aFile);
+            return GetLibrarySaveToPath(CSIDL_MYMUSIC,
+                                        FOLDERID_MusicLibrary,
+                                        aFile);
         }
         case Win_Videos:
         {
-            return GetWindowsFolder(CSIDL_MYVIDEO, aFile);
+            return GetLibrarySaveToPath(CSIDL_MYVIDEO,
+                                        FOLDERID_VideosLibrary,
+                                        aFile);
         }
 #endif  // XP_WIN
 
 #if defined(XP_UNIX)
         case Unix_LocalDirectory:
             return NS_NewNativeLocalFile(nsDependentCString("/usr/local/netscape/"),
                                          true,
                                          aFile);
--- a/xpcom/io/SpecialSystemDirectory.h
+++ b/xpcom/io/SpecialSystemDirectory.h
@@ -69,20 +69,21 @@ enum SystemDirectories {
   Win_Common_Desktopdirectory = 224,   
   Win_Appdata               =   225,   
   Win_Printhood             =   226,   
   Win_Cookies               =   227, 
   Win_LocalAppdata          =   228,
   Win_ProgramFiles          =   229,
   Win_Downloads             =   230,
   Win_Common_AppData        =   231,
-  Win_Pictures              =   232,
-  Win_Music                 =   233,
-  Win_Videos                =   234,
-  
+  Win_Documents             =   232,
+  Win_Pictures              =   233,
+  Win_Music                 =   234,
+  Win_Videos                =   235,
+
   Unix_LocalDirectory       =   301,   
   Unix_LibDirectory         =   302,   
   Unix_HomeDirectory        =   303,
   Unix_XDG_Desktop          =   304,
   Unix_XDG_Documents        =   305,
   Unix_XDG_Download         =   306,
   Unix_XDG_Music            =   307,
   Unix_XDG_Pictures         =   308,
--- a/xpcom/io/nsDirectoryService.cpp
+++ b/xpcom/io/nsDirectoryService.cpp
@@ -818,16 +818,20 @@ nsDirectoryService::GetFile(const char *
     else if (inAtom == nsDirectoryService::sWinCookiesDirectory)
     {
         rv = GetSpecialSystemDirectory(Win_Cookies, getter_AddRefs(localFile)); 
     }
     else if (inAtom == nsDirectoryService::sDefaultDownloadDirectory)
     {
         rv = GetSpecialSystemDirectory(Win_Downloads, getter_AddRefs(localFile));
     }
+    else if (inAtom == nsDirectoryService::sDocs)
+    {
+        rv = GetSpecialSystemDirectory(Win_Documents, getter_AddRefs(localFile));
+    }
     else if (inAtom == nsDirectoryService::sPictures)
     {
         rv = GetSpecialSystemDirectory(Win_Pictures, getter_AddRefs(localFile));
     }
     else if (inAtom == nsDirectoryService::sMusic)
     {
         rv = GetSpecialSystemDirectory(Win_Music, getter_AddRefs(localFile));
     }
--- a/xpcom/io/nsDirectoryServiceAtomList.h
+++ b/xpcom/io/nsDirectoryServiceAtomList.h
@@ -68,16 +68,17 @@ DIR_ATOM(sCommon_Programs, NS_WIN_COMMON
 DIR_ATOM(sCommon_Startup, NS_WIN_COMMON_STARTUP_DIR)
 DIR_ATOM(sCommon_Desktopdirectory, NS_WIN_COMMON_DESKTOP_DIRECTORY)
 DIR_ATOM(sCommon_AppData, NS_WIN_COMMON_APPDATA_DIR)
 DIR_ATOM(sAppdata, NS_WIN_APPDATA_DIR)
 DIR_ATOM(sLocalAppdata, NS_WIN_LOCAL_APPDATA_DIR)
 DIR_ATOM(sPrinthood, NS_WIN_PRINTHOOD)
 DIR_ATOM(sWinCookiesDirectory, NS_WIN_COOKIES_DIR)
 DIR_ATOM(sDefaultDownloadDirectory, NS_WIN_DEFAULT_DOWNLOAD_DIR)
+DIR_ATOM(sDocs, NS_WIN_DOCUMENTS_DIR)
 DIR_ATOM(sPictures, NS_WIN_PICTURES_DIR)
 DIR_ATOM(sMusic, NS_WIN_MUSIC_DIR)
 DIR_ATOM(sVideos, NS_WIN_VIDEOS_DIR)
 #elif defined (XP_UNIX)
 DIR_ATOM(sLocalDirectory, NS_UNIX_LOCAL_DIR)
 DIR_ATOM(sLibDirectory, NS_UNIX_LIB_DIR)
 DIR_ATOM(sDefaultDownloadDirectory, NS_UNIX_DEFAULT_DOWNLOAD_DIR)
 DIR_ATOM(sXDGDesktop, NS_UNIX_XDG_DESKTOP_DIR)
--- a/xpcom/io/nsDirectoryServiceDefs.h
+++ b/xpcom/io/nsDirectoryServiceDefs.h
@@ -117,16 +117,21 @@
     #define NS_WIN_COMMON_STARTUP_DIR           "CmStrt"
     #define NS_WIN_COMMON_DESKTOP_DIRECTORY     "CmDeskP"
     #define NS_WIN_COMMON_APPDATA_DIR           "CmAppData"
     #define NS_WIN_APPDATA_DIR                  "AppData"
     #define NS_WIN_LOCAL_APPDATA_DIR            "LocalAppData"
     #define NS_WIN_PRINTHOOD                    "PrntHd"
     #define NS_WIN_COOKIES_DIR                  "CookD"
     #define NS_WIN_DEFAULT_DOWNLOAD_DIR         "DfltDwnld"
+    // On Win7 and up these ids will return the default save-to location for
+    // Windows Libraries associated with the specific content type. For other
+    // os they return the local user folder. Note these can return network file
+    // paths which can jank the ui thread so be careful how you access them.
+    #define NS_WIN_DOCUMENTS_DIR                "Docs"
     #define NS_WIN_PICTURES_DIR                 "Pict"
     #define NS_WIN_MUSIC_DIR                    "Music"
     #define NS_WIN_VIDEOS_DIR                   "Vids"
 #elif defined (XP_UNIX)
     #define NS_UNIX_LOCAL_DIR                   "Locl"
     #define NS_UNIX_LIB_DIR                     "LibD"
     #define NS_UNIX_HOME_DIR                    NS_OS_HOME_DIR
     #define NS_UNIX_XDG_DESKTOP_DIR             "XDGDesk"