LCOV - code coverage report
Current view: top level - toolkit/profile - nsToolkitProfileService.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 135 461 29.3 %
Date: 2017-07-14 16:53:18 Functions: 33 64 51.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #include "mozilla/ArrayUtils.h"
       7             : #include "mozilla/UniquePtr.h"
       8             : 
       9             : #include <stdio.h>
      10             : #include <stdlib.h>
      11             : #include <prprf.h>
      12             : #include <prtime.h>
      13             : #include "nsProfileLock.h"
      14             : 
      15             : #ifdef XP_WIN
      16             : #include <windows.h>
      17             : #include <shlobj.h>
      18             : #endif
      19             : #ifdef XP_UNIX
      20             : #include <unistd.h>
      21             : #endif
      22             : 
      23             : #include "nsIToolkitProfileService.h"
      24             : #include "nsIToolkitProfile.h"
      25             : #include "nsIFactory.h"
      26             : #include "nsIFile.h"
      27             : #include "nsISimpleEnumerator.h"
      28             : 
      29             : #ifdef XP_MACOSX
      30             : #include <CoreFoundation/CoreFoundation.h>
      31             : #include "nsILocalFileMac.h"
      32             : #endif
      33             : 
      34             : #include "nsAppDirectoryServiceDefs.h"
      35             : #include "nsXULAppAPI.h"
      36             : 
      37             : #include "nsINIParser.h"
      38             : #include "nsXREDirProvider.h"
      39             : #include "nsAppRunner.h"
      40             : #include "nsString.h"
      41             : #include "nsReadableUtils.h"
      42             : #include "nsNativeCharsetUtils.h"
      43             : #include "mozilla/Attributes.h"
      44             : #include "mozilla/Sprintf.h"
      45             : 
      46             : using namespace mozilla;
      47             : 
      48             : class nsToolkitProfile final : public nsIToolkitProfile
      49             : {
      50             : public:
      51             :     NS_DECL_ISUPPORTS
      52             :     NS_DECL_NSITOOLKITPROFILE
      53             : 
      54             :     friend class nsToolkitProfileService;
      55             :     RefPtr<nsToolkitProfile> mNext;
      56             :     nsToolkitProfile          *mPrev;
      57             : 
      58             : private:
      59           0 :     ~nsToolkitProfile() { }
      60             : 
      61             :     nsToolkitProfile(const nsACString& aName,
      62             :                      nsIFile* aRootDir,
      63             :                      nsIFile* aLocalDir,
      64             :                      nsToolkitProfile* aPrev,
      65             :                      bool aForExternalApp);
      66             : 
      67             :     friend class nsToolkitProfileLock;
      68             : 
      69             :     nsCString                  mName;
      70             :     nsCOMPtr<nsIFile>          mRootDir;
      71             :     nsCOMPtr<nsIFile>          mLocalDir;
      72             :     nsIProfileLock*            mLock;
      73             :     bool                       mForExternalApp;
      74             : };
      75             : 
      76             : class nsToolkitProfileLock final : public nsIProfileLock
      77             : {
      78             : public:
      79             :     NS_DECL_ISUPPORTS
      80             :     NS_DECL_NSIPROFILELOCK
      81             : 
      82             :     nsresult Init(nsToolkitProfile* aProfile, nsIProfileUnlocker* *aUnlocker);
      83             :     nsresult Init(nsIFile* aDirectory, nsIFile* aLocalDirectory,
      84             :                   nsIProfileUnlocker* *aUnlocker);
      85             : 
      86           1 :     nsToolkitProfileLock() { }
      87             : 
      88             : private:
      89             :     ~nsToolkitProfileLock();
      90             : 
      91             :     RefPtr<nsToolkitProfile> mProfile;
      92             :     nsCOMPtr<nsIFile> mDirectory;
      93             :     nsCOMPtr<nsIFile> mLocalDirectory;
      94             : 
      95             :     nsProfileLock mLock;
      96             : };
      97             : 
      98           1 : class nsToolkitProfileFactory final : public nsIFactory
      99             : {
     100           0 :     ~nsToolkitProfileFactory() {}
     101             : public:
     102             :     NS_DECL_ISUPPORTS
     103             :     NS_DECL_NSIFACTORY
     104             : };
     105             : 
     106             : class nsToolkitProfileService final : public nsIToolkitProfileService
     107             : {
     108             : public:
     109             :     NS_DECL_ISUPPORTS
     110             :     NS_DECL_NSITOOLKITPROFILESERVICE
     111             : 
     112             : private:
     113             :     friend class nsToolkitProfile;
     114             :     friend class nsToolkitProfileFactory;
     115             :     friend nsresult NS_NewToolkitProfileService(nsIToolkitProfileService**);
     116             : 
     117           1 :     nsToolkitProfileService() :
     118             :         mDirty(false),
     119             :         mStartWithLast(true),
     120           1 :         mStartOffline(false)
     121             :     {
     122           1 :         gService = this;
     123           1 :     }
     124           0 :     ~nsToolkitProfileService()
     125           0 :     {
     126           0 :         gService = nullptr;
     127           0 :     }
     128             : 
     129             :     nsresult Init();
     130             : 
     131             :     nsresult CreateTimesInternal(nsIFile *profileDir);
     132             : 
     133             :     nsresult CreateProfileInternal(nsIFile* aRootDir,
     134             :                                    const nsACString& aName,
     135             :                                    const nsACString* aProfileName,
     136             :                                    const nsACString* aAppName,
     137             :                                    const nsACString* aVendorName,
     138             :                                    bool aForExternalApp,
     139             :                                    nsIToolkitProfile** aResult);
     140             : 
     141             :     RefPtr<nsToolkitProfile>  mFirst;
     142             :     nsCOMPtr<nsIToolkitProfile> mChosen;
     143             :     nsCOMPtr<nsIToolkitProfile> mDefault;
     144             :     nsCOMPtr<nsIFile>           mAppData;
     145             :     nsCOMPtr<nsIFile>           mTempData;
     146             :     nsCOMPtr<nsIFile>           mListFile;
     147             :     bool mDirty;
     148             :     bool mStartWithLast;
     149             :     bool mStartOffline;
     150             : 
     151             :     static nsToolkitProfileService *gService;
     152             : 
     153             :     class ProfileEnumerator final : public nsISimpleEnumerator
     154             :     {
     155             :     public:
     156             :         NS_DECL_ISUPPORTS
     157             :         NS_DECL_NSISIMPLEENUMERATOR
     158             : 
     159           1 :         explicit ProfileEnumerator(nsToolkitProfile *first)
     160           1 :           { mCurrent = first; }
     161             :     private:
     162           1 :         ~ProfileEnumerator() { }
     163             :         RefPtr<nsToolkitProfile> mCurrent;
     164             :     };
     165             : };
     166             : 
     167           1 : nsToolkitProfile::nsToolkitProfile(const nsACString& aName,
     168             :                                    nsIFile* aRootDir,
     169             :                                    nsIFile* aLocalDir,
     170             :                                    nsToolkitProfile* aPrev,
     171           1 :                                    bool aForExternalApp) :
     172             :     mPrev(aPrev),
     173             :     mName(aName),
     174             :     mRootDir(aRootDir),
     175             :     mLocalDir(aLocalDir),
     176             :     mLock(nullptr),
     177           1 :     mForExternalApp(aForExternalApp)
     178             : {
     179           1 :     NS_ASSERTION(aRootDir, "No file!");
     180             : 
     181           1 :     if (!aForExternalApp) {
     182           1 :         if (aPrev) {
     183           0 :             aPrev->mNext = this;
     184             :         } else {
     185           1 :             nsToolkitProfileService::gService->mFirst = this;
     186             :         }
     187             :     }
     188           1 : }
     189             : 
     190           9 : NS_IMPL_ISUPPORTS(nsToolkitProfile, nsIToolkitProfile)
     191             : 
     192             : NS_IMETHODIMP
     193           0 : nsToolkitProfile::GetRootDir(nsIFile* *aResult)
     194             : {
     195           0 :     NS_ADDREF(*aResult = mRootDir);
     196           0 :     return NS_OK;
     197             : }
     198             : 
     199             : NS_IMETHODIMP
     200           0 : nsToolkitProfile::GetLocalDir(nsIFile* *aResult)
     201             : {
     202           0 :     NS_ADDREF(*aResult = mLocalDir);
     203           0 :     return NS_OK;
     204             : }
     205             : 
     206             : NS_IMETHODIMP
     207           0 : nsToolkitProfile::GetName(nsACString& aResult)
     208             : {
     209           0 :     aResult = mName;
     210           0 :     return NS_OK;
     211             : }
     212             : 
     213             : NS_IMETHODIMP
     214           0 : nsToolkitProfile::SetName(const nsACString& aName)
     215             : {
     216           0 :     NS_ASSERTION(nsToolkitProfileService::gService,
     217             :                  "Where did my service go?");
     218           0 :     NS_ENSURE_TRUE(!mForExternalApp, NS_ERROR_NOT_IMPLEMENTED);
     219             : 
     220           0 :     mName = aName;
     221           0 :     nsToolkitProfileService::gService->mDirty = true;
     222             : 
     223           0 :     return NS_OK;
     224             : }
     225             : 
     226             : NS_IMETHODIMP
     227           0 : nsToolkitProfile::Remove(bool removeFiles)
     228             : {
     229           0 :     NS_ASSERTION(nsToolkitProfileService::gService,
     230             :                  "Whoa, my service is gone.");
     231             : 
     232           0 :     NS_ENSURE_TRUE(!mForExternalApp, NS_ERROR_NOT_IMPLEMENTED);
     233             : 
     234           0 :     if (mLock)
     235           0 :         return NS_ERROR_FILE_IS_LOCKED;
     236             : 
     237           0 :     if (!mPrev && !mNext && nsToolkitProfileService::gService->mFirst != this)
     238           0 :         return NS_ERROR_NOT_INITIALIZED;
     239             : 
     240           0 :     if (removeFiles) {
     241             :         bool equals;
     242           0 :         nsresult rv = mRootDir->Equals(mLocalDir, &equals);
     243           0 :         if (NS_FAILED(rv))
     244           0 :             return rv;
     245             : 
     246             :         // The root dir might contain the temp dir, so remove
     247             :         // the temp dir first.
     248           0 :         if (!equals)
     249           0 :             mLocalDir->Remove(true);
     250             : 
     251           0 :         mRootDir->Remove(true);
     252             :     }
     253             : 
     254           0 :     if (mPrev)
     255           0 :         mPrev->mNext = mNext;
     256             :     else
     257           0 :         nsToolkitProfileService::gService->mFirst = mNext;
     258             : 
     259           0 :     if (mNext)
     260           0 :         mNext->mPrev = mPrev;
     261             : 
     262           0 :     mPrev = nullptr;
     263           0 :     mNext = nullptr;
     264             : 
     265           0 :     if (nsToolkitProfileService::gService->mChosen == this)
     266           0 :         nsToolkitProfileService::gService->mChosen = nullptr;
     267             : 
     268           0 :     nsToolkitProfileService::gService->mDirty = true;
     269             : 
     270           0 :     return NS_OK;
     271             : }
     272             : 
     273             : NS_IMETHODIMP
     274           0 : nsToolkitProfile::Lock(nsIProfileUnlocker* *aUnlocker, nsIProfileLock* *aResult)
     275             : {
     276           0 :     if (mLock) {
     277           0 :         NS_ADDREF(*aResult = mLock);
     278           0 :         return NS_OK;
     279             :     }
     280             : 
     281           0 :     RefPtr<nsToolkitProfileLock> lock = new nsToolkitProfileLock();
     282           0 :     if (!lock) return NS_ERROR_OUT_OF_MEMORY;
     283             : 
     284           0 :     nsresult rv = lock->Init(this, aUnlocker);
     285           0 :     if (NS_FAILED(rv)) return rv;
     286             : 
     287           0 :     NS_ADDREF(*aResult = lock);
     288           0 :     return NS_OK;
     289             : }
     290             : 
     291           4 : NS_IMPL_ISUPPORTS(nsToolkitProfileLock, nsIProfileLock)
     292             : 
     293             : nsresult
     294           0 : nsToolkitProfileLock::Init(nsToolkitProfile* aProfile, nsIProfileUnlocker* *aUnlocker)
     295             : {
     296             :     nsresult rv;
     297           0 :     rv = Init(aProfile->mRootDir, aProfile->mLocalDir, aUnlocker);
     298           0 :     if (NS_SUCCEEDED(rv))
     299           0 :         mProfile = aProfile;
     300             : 
     301           0 :     return rv;
     302             : }
     303             : 
     304             : nsresult
     305           1 : nsToolkitProfileLock::Init(nsIFile* aDirectory, nsIFile* aLocalDirectory,
     306             :                            nsIProfileUnlocker* *aUnlocker)
     307             : {
     308             :     nsresult rv;
     309             : 
     310           1 :     rv = mLock.Lock(aDirectory, aUnlocker);
     311             : 
     312           1 :     if (NS_SUCCEEDED(rv)) {
     313           1 :         mDirectory = aDirectory;
     314           1 :         mLocalDirectory = aLocalDirectory;
     315             :     }
     316             : 
     317           1 :     return rv;
     318             : }
     319             : 
     320             : NS_IMETHODIMP
     321           1 : nsToolkitProfileLock::GetDirectory(nsIFile* *aResult)
     322             : {
     323           1 :     if (!mDirectory) {
     324           0 :         NS_ERROR("Not initialized, or unlocked!");
     325           0 :         return NS_ERROR_NOT_INITIALIZED;
     326             :     }
     327             : 
     328           1 :     NS_ADDREF(*aResult = mDirectory);
     329           1 :     return NS_OK;
     330             : }
     331             : 
     332             : NS_IMETHODIMP
     333           1 : nsToolkitProfileLock::GetLocalDirectory(nsIFile* *aResult)
     334             : {
     335           1 :     if (!mLocalDirectory) {
     336           0 :         NS_ERROR("Not initialized, or unlocked!");
     337           0 :         return NS_ERROR_NOT_INITIALIZED;
     338             :     }
     339             : 
     340           1 :     NS_ADDREF(*aResult = mLocalDirectory);
     341           1 :     return NS_OK;
     342             : }
     343             : 
     344             : NS_IMETHODIMP
     345           0 : nsToolkitProfileLock::Unlock()
     346             : {
     347           0 :     if (!mDirectory) {
     348           0 :         NS_ERROR("Unlocking a never-locked nsToolkitProfileLock!");
     349           0 :         return NS_ERROR_UNEXPECTED;
     350             :     }
     351             : 
     352           0 :     mLock.Unlock();
     353             : 
     354           0 :     if (mProfile) {
     355           0 :         mProfile->mLock = nullptr;
     356           0 :         mProfile = nullptr;
     357             :     }
     358           0 :     mDirectory = nullptr;
     359           0 :     mLocalDirectory = nullptr;
     360             : 
     361           0 :     return NS_OK;
     362             : }
     363             : 
     364             : NS_IMETHODIMP
     365           2 : nsToolkitProfileLock::GetReplacedLockTime(PRTime *aResult)
     366             : {
     367           2 :     mLock.GetReplacedLockTime(aResult);
     368           2 :     return NS_OK;
     369             : }
     370             : 
     371           0 : nsToolkitProfileLock::~nsToolkitProfileLock()
     372             : {
     373           0 :     if (mDirectory) {
     374           0 :         Unlock();
     375             :     }
     376           0 : }
     377             : 
     378             : nsToolkitProfileService*
     379             : nsToolkitProfileService::gService = nullptr;
     380             : 
     381          19 : NS_IMPL_ISUPPORTS(nsToolkitProfileService,
     382             :                   nsIToolkitProfileService)
     383             : 
     384             : nsresult
     385           1 : nsToolkitProfileService::Init()
     386             : {
     387           1 :     NS_ASSERTION(gDirServiceProvider, "No dirserviceprovider!");
     388             :     nsresult rv;
     389             : 
     390           1 :     rv = gDirServiceProvider->GetUserAppDataDirectory(getter_AddRefs(mAppData));
     391           1 :     NS_ENSURE_SUCCESS(rv, rv);
     392             : 
     393           1 :     rv = gDirServiceProvider->GetUserLocalDataDirectory(getter_AddRefs(mTempData));
     394           1 :     NS_ENSURE_SUCCESS(rv, rv);
     395             : 
     396           1 :     rv = mAppData->Clone(getter_AddRefs(mListFile));
     397           1 :     NS_ENSURE_SUCCESS(rv, rv);
     398             : 
     399           1 :     rv = mListFile->AppendNative(NS_LITERAL_CSTRING("profiles.ini"));
     400           1 :     NS_ENSURE_SUCCESS(rv, rv);
     401             : 
     402             :     bool exists;
     403           1 :     rv = mListFile->IsFile(&exists);
     404           1 :     if (NS_FAILED(rv) || !exists) {
     405           0 :         return NS_OK;
     406             :     }
     407             : 
     408             :     int64_t size;
     409           1 :     rv = mListFile->GetFileSize(&size);
     410           1 :     if (NS_FAILED(rv) || !size) {
     411           0 :         return NS_OK;
     412             :     }
     413             : 
     414           2 :     nsINIParser parser;
     415           1 :     rv = parser.Init(mListFile);
     416             :     // Init does not fail on parsing errors, only on OOM/really unexpected
     417             :     // conditions.
     418           1 :     if (NS_FAILED(rv))
     419           0 :         return rv;
     420             : 
     421           2 :     nsAutoCString buffer;
     422           1 :     rv = parser.GetString("General", "StartWithLastProfile", buffer);
     423           1 :     if (NS_SUCCEEDED(rv) && buffer.EqualsLiteral("0"))
     424           1 :         mStartWithLast = false;
     425             : 
     426           1 :     nsToolkitProfile* currentProfile = nullptr;
     427             : 
     428             : #ifdef MOZ_DEV_EDITION
     429             :     nsCOMPtr<nsIFile> ignoreSeparateProfile;
     430             :     rv = mAppData->Clone(getter_AddRefs(ignoreSeparateProfile));
     431             :     if (NS_FAILED(rv))
     432             :         return rv;
     433             : 
     434             :     rv = ignoreSeparateProfile->AppendNative(NS_LITERAL_CSTRING("ignore-dev-edition-profile"));
     435             :     if (NS_FAILED(rv))
     436             :         return rv;
     437             : 
     438             :     bool shouldIgnoreSeparateProfile;
     439             :     rv = ignoreSeparateProfile->Exists(&shouldIgnoreSeparateProfile);
     440             :     if (NS_FAILED(rv))
     441             :         return rv;
     442             : #endif
     443             : 
     444           1 :     unsigned int c = 0;
     445           1 :     bool foundAuroraDefault = false;
     446           2 :     for (c = 0; true; ++c) {
     447           3 :         nsAutoCString profileID("Profile");
     448           2 :         profileID.AppendInt(c);
     449             : 
     450           2 :         rv = parser.GetString(profileID.get(), "IsRelative", buffer);
     451           2 :         if (NS_FAILED(rv)) break;
     452             : 
     453           1 :         bool isRelative = buffer.EqualsLiteral("1");
     454             : 
     455           2 :         nsAutoCString filePath;
     456             : 
     457           1 :         rv = parser.GetString(profileID.get(), "Path", filePath);
     458           1 :         if (NS_FAILED(rv)) {
     459           0 :             NS_ERROR("Malformed profiles.ini: Path= not found");
     460           0 :             continue;
     461             :         }
     462             : 
     463           2 :         nsAutoCString name;
     464             : 
     465           1 :         rv = parser.GetString(profileID.get(), "Name", name);
     466           1 :         if (NS_FAILED(rv)) {
     467           0 :             NS_ERROR("Malformed profiles.ini: Name= not found");
     468           0 :             continue;
     469             :         }
     470             : 
     471           2 :         nsCOMPtr<nsIFile> rootDir;
     472           1 :         rv = NS_NewNativeLocalFile(EmptyCString(), true,
     473           2 :                                    getter_AddRefs(rootDir));
     474           1 :         NS_ENSURE_SUCCESS(rv, rv);
     475             : 
     476           1 :         if (isRelative) {
     477           1 :             rv = rootDir->SetRelativeDescriptor(mAppData, filePath);
     478             :         } else {
     479           0 :             rv = rootDir->SetPersistentDescriptor(filePath);
     480             :         }
     481           1 :         if (NS_FAILED(rv)) continue;
     482             : 
     483           2 :         nsCOMPtr<nsIFile> localDir;
     484           1 :         if (isRelative) {
     485           1 :             rv = NS_NewNativeLocalFile(EmptyCString(), true,
     486           2 :                                        getter_AddRefs(localDir));
     487           1 :             NS_ENSURE_SUCCESS(rv, rv);
     488             : 
     489           1 :             rv = localDir->SetRelativeDescriptor(mTempData, filePath);
     490             :         } else {
     491           0 :             localDir = rootDir;
     492             :         }
     493             : 
     494           1 :         currentProfile = new nsToolkitProfile(name,
     495             :                                               rootDir, localDir,
     496           2 :                                               currentProfile, false);
     497           1 :         NS_ENSURE_TRUE(currentProfile, NS_ERROR_OUT_OF_MEMORY);
     498             : 
     499           1 :         rv = parser.GetString(profileID.get(), "Default", buffer);
     500           1 :         if (NS_SUCCEEDED(rv) && buffer.EqualsLiteral("1") && !foundAuroraDefault) {
     501           0 :             mChosen = currentProfile;
     502           0 :             this->SetDefaultProfile(currentProfile);
     503             :         }
     504             : #ifdef MOZ_DEV_EDITION
     505             :         // Use the dev-edition-default profile if this is an Aurora build and
     506             :         // ignore-dev-edition-profile is not present.
     507             :         if (name.EqualsLiteral("dev-edition-default") && !shouldIgnoreSeparateProfile) {
     508             :             mChosen = currentProfile;
     509             :             foundAuroraDefault = true;
     510             :         }
     511             : #endif
     512           1 :     }
     513             : 
     514             : #ifdef MOZ_DEV_EDITION
     515             :     if (!foundAuroraDefault && !shouldIgnoreSeparateProfile) {
     516             :         // If a single profile exists, it may not be already marked as default.
     517             :         // Do it now to avoid problems when we create the dev-edition-default profile.
     518             :         if (!mChosen && mFirst && !mFirst->mNext)
     519             :             this->SetDefaultProfile(mFirst);
     520             : 
     521             :         // Create a default profile for aurora, if none was found.
     522             :         nsCOMPtr<nsIToolkitProfile> profile;
     523             :         rv = CreateProfile(nullptr,
     524             :                            NS_LITERAL_CSTRING("dev-edition-default"),
     525             :                            getter_AddRefs(profile));
     526             :         if (NS_FAILED(rv)) return rv;
     527             :         mChosen = profile;
     528             :         rv = Flush();
     529             :         if (NS_FAILED(rv)) return rv;
     530             :     }
     531             : #endif
     532             : 
     533           2 :     if (!mChosen && mFirst && !mFirst->mNext) // only one profile
     534           1 :         mChosen = mFirst;
     535           1 :     return NS_OK;
     536             : }
     537             : 
     538             : NS_IMETHODIMP
     539           0 : nsToolkitProfileService::SetStartWithLastProfile(bool aValue)
     540             : {
     541           0 :     if (mStartWithLast != aValue) {
     542           0 :         mStartWithLast = aValue;
     543           0 :         mDirty = true;
     544             :     }
     545           0 :     return NS_OK;
     546             : }
     547             : 
     548             : NS_IMETHODIMP
     549           0 : nsToolkitProfileService::GetStartWithLastProfile(bool *aResult)
     550             : {
     551           0 :     *aResult = mStartWithLast;
     552           0 :     return NS_OK;
     553             : }
     554             : 
     555             : NS_IMETHODIMP
     556           0 : nsToolkitProfileService::GetStartOffline(bool *aResult)
     557             : {
     558           0 :     *aResult = mStartOffline;
     559           0 :     return NS_OK;
     560             : }
     561             : 
     562             : NS_IMETHODIMP
     563           0 : nsToolkitProfileService::SetStartOffline(bool aValue)
     564             : {
     565           0 :     mStartOffline = aValue;
     566           0 :     return NS_OK;
     567             : }
     568             : 
     569             : NS_IMETHODIMP
     570           1 : nsToolkitProfileService::GetProfiles(nsISimpleEnumerator* *aResult)
     571             : {
     572           2 :     *aResult = new ProfileEnumerator(this->mFirst);
     573           1 :     if (!*aResult)
     574           0 :         return NS_ERROR_OUT_OF_MEMORY;
     575             : 
     576           1 :     NS_ADDREF(*aResult);
     577           1 :     return NS_OK;
     578             : }
     579             : 
     580           6 : NS_IMPL_ISUPPORTS(nsToolkitProfileService::ProfileEnumerator,
     581             :                   nsISimpleEnumerator)
     582             : 
     583             : NS_IMETHODIMP
     584           0 : nsToolkitProfileService::ProfileEnumerator::HasMoreElements(bool* aResult)
     585             : {
     586           0 :     *aResult = mCurrent ? true : false;
     587           0 :     return NS_OK;
     588             : }
     589             : 
     590             : NS_IMETHODIMP
     591           2 : nsToolkitProfileService::ProfileEnumerator::GetNext(nsISupports* *aResult)
     592             : {
     593           2 :     if (!mCurrent) return NS_ERROR_FAILURE;
     594             : 
     595           1 :     NS_ADDREF(*aResult = mCurrent);
     596             : 
     597           1 :     mCurrent = mCurrent->mNext;
     598           1 :     return NS_OK;
     599             : }
     600             : 
     601             : NS_IMETHODIMP
     602           0 : nsToolkitProfileService::GetSelectedProfile(nsIToolkitProfile* *aResult)
     603             : {
     604           0 :     if (!mChosen && mFirst && !mFirst->mNext) // only one profile
     605           0 :         mChosen = mFirst;
     606             : 
     607           0 :     if (!mChosen) return NS_ERROR_FAILURE;
     608             : 
     609           0 :     NS_ADDREF(*aResult = mChosen);
     610           0 :     return NS_OK;
     611             : }
     612             : 
     613             : NS_IMETHODIMP
     614           0 : nsToolkitProfileService::SetSelectedProfile(nsIToolkitProfile* aProfile)
     615             : {
     616           0 :     if (mChosen != aProfile) {
     617           0 :         mChosen = aProfile;
     618           0 :         mDirty = true;
     619             :     }
     620           0 :     return NS_OK;
     621             : }
     622             : 
     623             : NS_IMETHODIMP
     624           0 : nsToolkitProfileService::GetDefaultProfile(nsIToolkitProfile* *aResult)
     625             : {
     626           0 :     if (!mDefault) return NS_ERROR_FAILURE;
     627             : 
     628           0 :     NS_ADDREF(*aResult = mDefault);
     629           0 :     return NS_OK;
     630             : }
     631             : 
     632             : NS_IMETHODIMP
     633           0 : nsToolkitProfileService::SetDefaultProfile(nsIToolkitProfile* aProfile)
     634             : {
     635           0 :     if (mDefault != aProfile) {
     636           0 :         mDefault = aProfile;
     637           0 :         mDirty = true;
     638             :     }
     639           0 :     return NS_OK;
     640             : }
     641             : 
     642             : NS_IMETHODIMP
     643           0 : nsToolkitProfileService::GetProfileByName(const nsACString& aName,
     644             :                                           nsIToolkitProfile* *aResult)
     645             : {
     646           0 :     nsToolkitProfile* curP = mFirst;
     647           0 :     while (curP) {
     648           0 :         if (curP->mName.Equals(aName)) {
     649           0 :             NS_ADDREF(*aResult = curP);
     650           0 :             return NS_OK;
     651             :         }
     652           0 :         curP = curP->mNext;
     653             :     }
     654             : 
     655           0 :     return NS_ERROR_FAILURE;
     656             : }
     657             : 
     658             : NS_IMETHODIMP
     659           0 : nsToolkitProfileService::LockProfilePath(nsIFile* aDirectory,
     660             :                                          nsIFile* aLocalDirectory,
     661             :                                          nsIProfileLock* *aResult)
     662             : {
     663           0 :     return NS_LockProfilePath(aDirectory, aLocalDirectory, nullptr, aResult);
     664             : }
     665             : 
     666             : nsresult
     667           1 : NS_LockProfilePath(nsIFile* aPath, nsIFile* aTempPath,
     668             :                    nsIProfileUnlocker* *aUnlocker, nsIProfileLock* *aResult)
     669             : {
     670           2 :     RefPtr<nsToolkitProfileLock> lock = new nsToolkitProfileLock();
     671           1 :     if (!lock) return NS_ERROR_OUT_OF_MEMORY;
     672             : 
     673           1 :     nsresult rv = lock->Init(aPath, aTempPath, aUnlocker);
     674           1 :     if (NS_FAILED(rv)) return rv;
     675             : 
     676           1 :     lock.forget(aResult);
     677           1 :     return NS_OK;
     678             : }
     679             : 
     680             : static const char kTable[] =
     681             :     { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
     682             :       'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
     683             :       '1', '2', '3', '4', '5', '6', '7', '8', '9', '0' };
     684             : 
     685           0 : static void SaltProfileName(nsACString& aName)
     686             : {
     687           0 :     double fpTime = double(PR_Now());
     688             : 
     689             :     // use 1e-6, granularity of PR_Now() on the mac is seconds
     690           0 :     srand((unsigned int)(fpTime * 1e-6 + 0.5));
     691             : 
     692             :     char salt[9];
     693             : 
     694             :     int i;
     695           0 :     for (i = 0; i < 8; ++i)
     696           0 :         salt[i] = kTable[rand() % ArrayLength(kTable)];
     697             : 
     698           0 :     salt[8] = '.';
     699             : 
     700           0 :     aName.Insert(salt, 0, 9);
     701           0 : }
     702             : 
     703             : NS_IMETHODIMP
     704           0 : nsToolkitProfileService::CreateDefaultProfileForApp(const nsACString& aProfileName,
     705             :                                                     const nsACString& aAppName,
     706             :                                                     const nsACString& aVendorName,
     707             :                                                     nsIToolkitProfile** aResult)
     708             : {
     709           0 :     NS_ENSURE_STATE(!aProfileName.IsEmpty() || !aAppName.IsEmpty());
     710           0 :     nsCOMPtr<nsIFile> appData;
     711             :     nsresult rv =
     712           0 :         gDirServiceProvider->GetUserDataDirectory(getter_AddRefs(appData),
     713             :                                                   false,
     714             :                                                   &aProfileName,
     715             :                                                   &aAppName,
     716           0 :                                                   &aVendorName);
     717           0 :     NS_ENSURE_SUCCESS(rv, rv);
     718             : 
     719           0 :     nsCOMPtr<nsIFile> profilesini;
     720           0 :     appData->Clone(getter_AddRefs(profilesini));
     721           0 :     rv = profilesini->AppendNative(NS_LITERAL_CSTRING("profiles.ini"));
     722           0 :     NS_ENSURE_SUCCESS(rv, rv);
     723             : 
     724           0 :     bool exists = false;
     725           0 :     profilesini->Exists(&exists);
     726           0 :     NS_ENSURE_FALSE(exists, NS_ERROR_ALREADY_INITIALIZED);
     727             : 
     728           0 :     rv = CreateProfileInternal(nullptr,
     729           0 :                                NS_LITERAL_CSTRING("default"),
     730             :                                &aProfileName, &aAppName, &aVendorName,
     731           0 :                                true, aResult);
     732           0 :     NS_ENSURE_SUCCESS(rv, rv);
     733           0 :     NS_ENSURE_STATE(*aResult);
     734             : 
     735           0 :     nsCOMPtr<nsIFile> rootDir;
     736           0 :     (*aResult)->GetRootDir(getter_AddRefs(rootDir));
     737           0 :     NS_ENSURE_SUCCESS(rv, rv);
     738             : 
     739           0 :     nsAutoCString profileDir;
     740           0 :     rv = rootDir->GetRelativeDescriptor(appData, profileDir);
     741           0 :     NS_ENSURE_SUCCESS(rv, rv);
     742             : 
     743           0 :     nsCString ini;
     744           0 :     ini.SetCapacity(512);
     745           0 :     ini.AppendLiteral("[General]\n");
     746           0 :     ini.AppendLiteral("StartWithLastProfile=1\n\n");
     747             : 
     748           0 :     ini.AppendLiteral("[Profile0]\n");
     749           0 :     ini.AppendLiteral("Name=default\n");
     750           0 :     ini.AppendLiteral("IsRelative=1\n");
     751           0 :     ini.AppendLiteral("Path=");
     752           0 :     ini.Append(profileDir);
     753           0 :     ini.Append('\n');
     754           0 :     ini.AppendLiteral("Default=1\n\n");
     755             : 
     756             :     FILE* writeFile;
     757           0 :     rv = profilesini->OpenANSIFileDesc("w", &writeFile);
     758           0 :     NS_ENSURE_SUCCESS(rv, rv);
     759             : 
     760           0 :     if (fwrite(ini.get(), sizeof(char), ini.Length(), writeFile) !=
     761           0 :         ini.Length()) {
     762           0 :         rv = NS_ERROR_UNEXPECTED;
     763             :     }
     764           0 :     fclose(writeFile);
     765           0 :     return rv;
     766             : }
     767             : 
     768             : NS_IMETHODIMP
     769           0 : nsToolkitProfileService::CreateProfile(nsIFile* aRootDir,
     770             :                                        const nsACString& aName,
     771             :                                        nsIToolkitProfile** aResult)
     772             : {
     773             :     return CreateProfileInternal(aRootDir, aName,
     774           0 :                                  nullptr, nullptr, nullptr, false, aResult);
     775             : }
     776             : 
     777             : nsresult
     778           0 : nsToolkitProfileService::CreateProfileInternal(nsIFile* aRootDir,
     779             :                                                const nsACString& aName,
     780             :                                                const nsACString* aProfileName,
     781             :                                                const nsACString* aAppName,
     782             :                                                const nsACString* aVendorName,
     783             :                                                bool aForExternalApp,
     784             :                                                nsIToolkitProfile** aResult)
     785             : {
     786           0 :     nsresult rv = NS_ERROR_FAILURE;
     787             : 
     788           0 :     if (!aForExternalApp) {
     789           0 :         rv = GetProfileByName(aName, aResult);
     790           0 :         if (NS_SUCCEEDED(rv)) {
     791           0 :             return rv;
     792             :         }
     793             :     }
     794             : 
     795           0 :     nsCOMPtr<nsIFile> rootDir (aRootDir);
     796             : 
     797           0 :     nsAutoCString dirName;
     798           0 :     if (!rootDir) {
     799           0 :         rv = gDirServiceProvider->GetUserProfilesRootDir(getter_AddRefs(rootDir),
     800             :                                                          aProfileName, aAppName,
     801           0 :                                                          aVendorName);
     802           0 :         NS_ENSURE_SUCCESS(rv, rv);
     803             : 
     804           0 :         dirName = aName;
     805           0 :         SaltProfileName(dirName);
     806             : 
     807           0 :         if (NS_IsNativeUTF8()) {
     808           0 :             rootDir->AppendNative(dirName);
     809             :         } else {
     810           0 :             rootDir->Append(NS_ConvertUTF8toUTF16(dirName));
     811             :         }
     812             :     }
     813             : 
     814           0 :     nsCOMPtr<nsIFile> localDir;
     815             : 
     816             :     bool isRelative;
     817           0 :     rv = mAppData->Contains(rootDir, &isRelative);
     818           0 :     if (NS_SUCCEEDED(rv) && isRelative) {
     819           0 :         nsAutoCString path;
     820           0 :         rv = rootDir->GetRelativeDescriptor(mAppData, path);
     821           0 :         NS_ENSURE_SUCCESS(rv, rv);
     822             : 
     823           0 :         rv = NS_NewNativeLocalFile(EmptyCString(), true,
     824           0 :                                    getter_AddRefs(localDir));
     825           0 :         NS_ENSURE_SUCCESS(rv, rv);
     826             : 
     827           0 :         rv = localDir->SetRelativeDescriptor(mTempData, path);
     828             :     } else {
     829           0 :         localDir = rootDir;
     830             :     }
     831             : 
     832             :     bool exists;
     833           0 :     rv = rootDir->Exists(&exists);
     834           0 :     NS_ENSURE_SUCCESS(rv, rv);
     835             : 
     836           0 :     if (exists) {
     837           0 :         rv = rootDir->IsDirectory(&exists);
     838           0 :         NS_ENSURE_SUCCESS(rv, rv);
     839             : 
     840           0 :         if (!exists)
     841           0 :             return NS_ERROR_FILE_NOT_DIRECTORY;
     842             :     }
     843             :     else {
     844           0 :         nsCOMPtr<nsIFile> profileDirParent;
     845           0 :         nsAutoString profileDirName;
     846             : 
     847           0 :         rv = rootDir->GetParent(getter_AddRefs(profileDirParent));
     848           0 :         NS_ENSURE_SUCCESS(rv, rv);
     849             : 
     850           0 :         rv = rootDir->GetLeafName(profileDirName);
     851           0 :         NS_ENSURE_SUCCESS(rv, rv);
     852             : 
     853             :         // let's ensure that the profile directory exists.
     854           0 :         rv = rootDir->Create(nsIFile::DIRECTORY_TYPE, 0700);
     855           0 :         NS_ENSURE_SUCCESS(rv, rv);
     856           0 :         rv = rootDir->SetPermissions(0700);
     857             : #ifndef ANDROID
     858             :         // If the profile is on the sdcard, this will fail but its non-fatal
     859           0 :         NS_ENSURE_SUCCESS(rv, rv);
     860             : #endif
     861             :     }
     862             : 
     863           0 :     rv = localDir->Exists(&exists);
     864           0 :     NS_ENSURE_SUCCESS(rv, rv);
     865             : 
     866           0 :     if (!exists) {
     867           0 :         rv = localDir->Create(nsIFile::DIRECTORY_TYPE, 0700);
     868           0 :         NS_ENSURE_SUCCESS(rv, rv);
     869             :     }
     870             : 
     871             :     // We created a new profile dir. Let's store a creation timestamp.
     872             :     // Note that this code path does not apply if the profile dir was
     873             :     // created prior to launching.
     874           0 :     rv = CreateTimesInternal(rootDir);
     875           0 :     NS_ENSURE_SUCCESS(rv, rv);
     876             : 
     877           0 :     nsToolkitProfile* last = aForExternalApp ? nullptr : mFirst.get();
     878           0 :     if (last) {
     879           0 :         while (last->mNext)
     880           0 :             last = last->mNext;
     881             :     }
     882             : 
     883             :     nsCOMPtr<nsIToolkitProfile> profile =
     884           0 :         new nsToolkitProfile(aName, rootDir, localDir, last, aForExternalApp);
     885           0 :     if (!profile) return NS_ERROR_OUT_OF_MEMORY;
     886             : 
     887           0 :     profile.forget(aResult);
     888           0 :     return NS_OK;
     889             : }
     890             : 
     891             : nsresult
     892           0 : nsToolkitProfileService::CreateTimesInternal(nsIFile* aProfileDir)
     893             : {
     894           0 :     nsresult rv = NS_ERROR_FAILURE;
     895           0 :     nsCOMPtr<nsIFile> creationLog;
     896           0 :     rv = aProfileDir->Clone(getter_AddRefs(creationLog));
     897           0 :     NS_ENSURE_SUCCESS(rv, rv);
     898             : 
     899           0 :     rv = creationLog->AppendNative(NS_LITERAL_CSTRING("times.json"));
     900           0 :     NS_ENSURE_SUCCESS(rv, rv);
     901             : 
     902           0 :     bool exists = false;
     903           0 :     creationLog->Exists(&exists);
     904           0 :     if (exists) {
     905           0 :       return NS_OK;
     906             :     }
     907             : 
     908           0 :     rv = creationLog->Create(nsIFile::NORMAL_FILE_TYPE, 0700);
     909           0 :     NS_ENSURE_SUCCESS(rv, rv);
     910             : 
     911             :     // We don't care about microsecond resolution.
     912           0 :     int64_t msec = PR_Now() / PR_USEC_PER_MSEC;
     913             : 
     914             :     // Write it out.
     915             :     PRFileDesc *writeFile;
     916           0 :     rv = creationLog->OpenNSPRFileDesc(PR_WRONLY, 0700, &writeFile);
     917           0 :     NS_ENSURE_SUCCESS(rv, rv);
     918             : 
     919           0 :     PR_fprintf(writeFile, "{\n\"created\": %lld\n}\n", msec);
     920           0 :     PR_Close(writeFile);
     921           0 :     return NS_OK;
     922             : }
     923             : 
     924             : NS_IMETHODIMP
     925           0 : nsToolkitProfileService::GetProfileCount(uint32_t *aResult)
     926             : {
     927           0 :     if (!mFirst)
     928           0 :         *aResult = 0;
     929           0 :     else if (! mFirst->mNext)
     930           0 :         *aResult = 1;
     931             :     else
     932           0 :         *aResult = 2;
     933             : 
     934           0 :     return NS_OK;
     935             : }
     936             : 
     937             : NS_IMETHODIMP
     938           0 : nsToolkitProfileService::Flush()
     939             : {
     940             :     // Errors during writing might cause unhappy semi-written files.
     941             :     // To avoid this, write the entire thing to a buffer, then write
     942             :     // that buffer to disk.
     943             : 
     944             :     nsresult rv;
     945           0 :     uint32_t pCount = 0;
     946             :     nsToolkitProfile *cur;
     947             : 
     948           0 :     for (cur = mFirst; cur != nullptr; cur = cur->mNext)
     949           0 :         ++pCount;
     950             : 
     951             :     uint32_t length;
     952           0 :     const int bufsize = 100+MAXPATHLEN*pCount;
     953           0 :     auto buffer = MakeUnique<char[]>(bufsize);
     954             : 
     955           0 :     char *pos = buffer.get();
     956           0 :     char *end = pos + bufsize;
     957             : 
     958           0 :     pos += snprintf(pos, end - pos,
     959             :                     "[General]\n"
     960             :                     "StartWithLastProfile=%s\n\n",
     961           0 :                     mStartWithLast ? "1" : "0");
     962             : 
     963           0 :     nsAutoCString path;
     964           0 :     cur = mFirst;
     965           0 :     pCount = 0;
     966             : 
     967           0 :     while (cur) {
     968             :         // if the profile dir is relative to appdir...
     969             :         bool isRelative;
     970           0 :         rv = mAppData->Contains(cur->mRootDir, &isRelative);
     971           0 :         if (NS_SUCCEEDED(rv) && isRelative) {
     972             :             // we use a relative descriptor
     973           0 :             rv = cur->mRootDir->GetRelativeDescriptor(mAppData, path);
     974             :         } else {
     975             :             // otherwise, a persistent descriptor
     976           0 :             rv = cur->mRootDir->GetPersistentDescriptor(path);
     977           0 :             NS_ENSURE_SUCCESS(rv, rv);
     978             :         }
     979             : 
     980           0 :         pos += snprintf(pos, end - pos,
     981             :                         "[Profile%u]\n"
     982             :                         "Name=%s\n"
     983             :                         "IsRelative=%s\n"
     984             :                         "Path=%s\n",
     985             :                         pCount, cur->mName.get(),
     986           0 :                         isRelative ? "1" : "0", path.get());
     987             : 
     988           0 :         nsCOMPtr<nsIToolkitProfile> profile;
     989           0 :         rv = this->GetDefaultProfile(getter_AddRefs(profile));
     990           0 :         if (NS_SUCCEEDED(rv) && profile == cur) {
     991           0 :             pos += snprintf(pos, end - pos, "Default=1\n");
     992             :         }
     993             : 
     994           0 :         pos += snprintf(pos, end - pos, "\n");
     995             : 
     996           0 :         cur = cur->mNext;
     997           0 :         ++pCount;
     998             :     }
     999             : 
    1000             :     FILE* writeFile;
    1001           0 :     rv = mListFile->OpenANSIFileDesc("w", &writeFile);
    1002           0 :     NS_ENSURE_SUCCESS(rv, rv);
    1003             : 
    1004           0 :     length = pos - buffer.get();
    1005             : 
    1006           0 :     if (fwrite(buffer.get(), sizeof(char), length, writeFile) != length) {
    1007           0 :         fclose(writeFile);
    1008           0 :         return NS_ERROR_UNEXPECTED;
    1009             :     }
    1010             : 
    1011           0 :     fclose(writeFile);
    1012           0 :     return NS_OK;
    1013             : }
    1014             : 
    1015          12 : NS_IMPL_ISUPPORTS(nsToolkitProfileFactory, nsIFactory)
    1016             : 
    1017             : NS_IMETHODIMP
    1018           1 : nsToolkitProfileFactory::CreateInstance(nsISupports* aOuter, const nsID& aIID,
    1019             :                                         void** aResult)
    1020             : {
    1021           1 :     if (aOuter)
    1022           0 :         return NS_ERROR_NO_AGGREGATION;
    1023             : 
    1024             :     nsCOMPtr<nsIToolkitProfileService> profileService =
    1025           2 :         nsToolkitProfileService::gService;
    1026           1 :     if (!profileService) {
    1027           0 :         nsresult rv = NS_NewToolkitProfileService(getter_AddRefs(profileService));
    1028           0 :         if (NS_FAILED(rv))
    1029           0 :             return rv;
    1030             :     }
    1031           1 :     return profileService->QueryInterface(aIID, aResult);
    1032             : }
    1033             : 
    1034             : NS_IMETHODIMP
    1035           0 : nsToolkitProfileFactory::LockFactory(bool aVal)
    1036             : {
    1037           0 :     return NS_OK;
    1038             : }
    1039             : 
    1040             : nsresult
    1041           1 : NS_NewToolkitProfileFactory(nsIFactory* *aResult)
    1042             : {
    1043           1 :     *aResult = new nsToolkitProfileFactory();
    1044           1 :     if (!*aResult)
    1045           0 :         return NS_ERROR_OUT_OF_MEMORY;
    1046             : 
    1047           1 :     NS_ADDREF(*aResult);
    1048           1 :     return NS_OK;
    1049             : }
    1050             : 
    1051             : nsresult
    1052           1 : NS_NewToolkitProfileService(nsIToolkitProfileService* *aResult)
    1053             : {
    1054           1 :     nsToolkitProfileService* profileService = new nsToolkitProfileService();
    1055           1 :     if (!profileService)
    1056           0 :         return NS_ERROR_OUT_OF_MEMORY;
    1057           1 :     nsresult rv = profileService->Init();
    1058           1 :     if (NS_FAILED(rv)) {
    1059           0 :         NS_ERROR("nsToolkitProfileService::Init failed!");
    1060           0 :         delete profileService;
    1061           0 :         return rv;
    1062             :     }
    1063             : 
    1064           1 :     NS_ADDREF(*aResult = profileService);
    1065           1 :     return NS_OK;
    1066             : }
    1067             : 
    1068             : nsresult
    1069           3 : XRE_GetFileFromPath(const char *aPath, nsIFile* *aResult)
    1070             : {
    1071             : #if defined(XP_MACOSX)
    1072             :     int32_t pathLen = strlen(aPath);
    1073             :     if (pathLen > MAXPATHLEN)
    1074             :         return NS_ERROR_INVALID_ARG;
    1075             : 
    1076             :     CFURLRef fullPath =
    1077             :         CFURLCreateFromFileSystemRepresentation(nullptr, (const UInt8 *) aPath,
    1078             :                                                 pathLen, true);
    1079             :     if (!fullPath)
    1080             :         return NS_ERROR_FAILURE;
    1081             : 
    1082             :     nsCOMPtr<nsIFile> lf;
    1083             :     nsresult rv = NS_NewNativeLocalFile(EmptyCString(), true,
    1084             :                                         getter_AddRefs(lf));
    1085             :     if (NS_SUCCEEDED(rv)) {
    1086             :         nsCOMPtr<nsILocalFileMac> lfMac = do_QueryInterface(lf, &rv);
    1087             :         if (NS_SUCCEEDED(rv)) {
    1088             :             rv = lfMac->InitWithCFURL(fullPath);
    1089             :             if (NS_SUCCEEDED(rv)) {
    1090             :                 lf.forget(aResult);
    1091             :             }
    1092             :         }
    1093             :     }
    1094             :     CFRelease(fullPath);
    1095             :     return rv;
    1096             : 
    1097             : #elif defined(XP_UNIX)
    1098             :     char fullPath[MAXPATHLEN];
    1099             : 
    1100           3 :     if (!realpath(aPath, fullPath))
    1101           0 :         return NS_ERROR_FAILURE;
    1102             : 
    1103           6 :     return NS_NewNativeLocalFile(nsDependentCString(fullPath), true,
    1104           3 :                                  aResult);
    1105             : #elif defined(XP_WIN)
    1106             :     WCHAR fullPath[MAXPATHLEN];
    1107             : 
    1108             :     if (!_wfullpath(fullPath, NS_ConvertUTF8toUTF16(aPath).get(), MAXPATHLEN))
    1109             :         return NS_ERROR_FAILURE;
    1110             : 
    1111             :     return NS_NewLocalFile(nsDependentString(fullPath), true,
    1112             :                            aResult);
    1113             : 
    1114             : #else
    1115             : #error Platform-specific logic needed here.
    1116             : #endif
    1117             : }

Generated by: LCOV version 1.13