toolkit/profile/nsToolkitProfileService.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/toolkit/profile/nsToolkitProfileService.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,1061 @@
     1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#include "mozilla/ArrayUtils.h"
    1.10 +
    1.11 +#include <stdio.h>
    1.12 +#include <stdlib.h>
    1.13 +#include <prprf.h>
    1.14 +#include <prtime.h>
    1.15 +#include "nsProfileLock.h"
    1.16 +
    1.17 +#ifdef XP_WIN
    1.18 +#include <windows.h>
    1.19 +#include <shlobj.h>
    1.20 +#endif
    1.21 +#ifdef XP_UNIX
    1.22 +#include <unistd.h>
    1.23 +#endif
    1.24 +
    1.25 +#include "nsIToolkitProfileService.h"
    1.26 +#include "nsIToolkitProfile.h"
    1.27 +#include "nsIFactory.h"
    1.28 +#include "nsIFile.h"
    1.29 +#include "nsISimpleEnumerator.h"
    1.30 +
    1.31 +#ifdef XP_MACOSX
    1.32 +#include <CoreFoundation/CoreFoundation.h>
    1.33 +#include "nsILocalFileMac.h"
    1.34 +#endif
    1.35 +
    1.36 +#include "nsAppDirectoryServiceDefs.h"
    1.37 +#include "nsXULAppAPI.h"
    1.38 +
    1.39 +#include "nsINIParser.h"
    1.40 +#include "nsXREDirProvider.h"
    1.41 +#include "nsAppRunner.h"
    1.42 +#include "nsString.h"
    1.43 +#include "nsReadableUtils.h"
    1.44 +#include "nsNativeCharsetUtils.h"
    1.45 +#include "mozilla/Attributes.h"
    1.46 +
    1.47 +using namespace mozilla;
    1.48 +
    1.49 +class nsToolkitProfile MOZ_FINAL : public nsIToolkitProfile
    1.50 +{
    1.51 +public:
    1.52 +    NS_DECL_ISUPPORTS
    1.53 +    NS_DECL_NSITOOLKITPROFILE
    1.54 +
    1.55 +    friend class nsToolkitProfileService;
    1.56 +    nsRefPtr<nsToolkitProfile> mNext;
    1.57 +    nsToolkitProfile          *mPrev;
    1.58 +
    1.59 +    ~nsToolkitProfile() { }
    1.60 +
    1.61 +private:
    1.62 +    nsToolkitProfile(const nsACString& aName,
    1.63 +                     nsIFile* aRootDir,
    1.64 +                     nsIFile* aLocalDir,
    1.65 +                     nsToolkitProfile* aPrev,
    1.66 +                     bool aForExternalApp);
    1.67 +
    1.68 +    friend class nsToolkitProfileLock;
    1.69 +
    1.70 +    nsCString                  mName;
    1.71 +    nsCOMPtr<nsIFile>          mRootDir;
    1.72 +    nsCOMPtr<nsIFile>          mLocalDir;
    1.73 +    nsIProfileLock*            mLock;
    1.74 +    bool                       mForExternalApp;
    1.75 +};
    1.76 +
    1.77 +class nsToolkitProfileLock MOZ_FINAL : public nsIProfileLock
    1.78 +{
    1.79 +public:
    1.80 +    NS_DECL_ISUPPORTS
    1.81 +    NS_DECL_NSIPROFILELOCK
    1.82 +
    1.83 +    nsresult Init(nsToolkitProfile* aProfile, nsIProfileUnlocker* *aUnlocker);
    1.84 +    nsresult Init(nsIFile* aDirectory, nsIFile* aLocalDirectory,
    1.85 +                  nsIProfileUnlocker* *aUnlocker);
    1.86 +
    1.87 +    nsToolkitProfileLock() { }
    1.88 +    ~nsToolkitProfileLock();
    1.89 +
    1.90 +private:
    1.91 +    nsRefPtr<nsToolkitProfile> mProfile;
    1.92 +    nsCOMPtr<nsIFile> mDirectory;
    1.93 +    nsCOMPtr<nsIFile> mLocalDirectory;
    1.94 +
    1.95 +    nsProfileLock mLock;
    1.96 +};
    1.97 +
    1.98 +class nsToolkitProfileFactory MOZ_FINAL : public nsIFactory
    1.99 +{
   1.100 +public:
   1.101 +    NS_DECL_ISUPPORTS
   1.102 +    NS_DECL_NSIFACTORY
   1.103 +};
   1.104 +
   1.105 +class nsToolkitProfileService MOZ_FINAL : public nsIToolkitProfileService
   1.106 +{
   1.107 +public:
   1.108 +    NS_DECL_ISUPPORTS
   1.109 +    NS_DECL_NSITOOLKITPROFILESERVICE
   1.110 +
   1.111 +private:
   1.112 +    friend class nsToolkitProfile;
   1.113 +    friend class nsToolkitProfileFactory;
   1.114 +    friend nsresult NS_NewToolkitProfileService(nsIToolkitProfileService**);
   1.115 +
   1.116 +    nsToolkitProfileService() :
   1.117 +        mDirty(false),
   1.118 +        mStartWithLast(true),
   1.119 +        mStartOffline(false)
   1.120 +    {
   1.121 +        gService = this;
   1.122 +    }
   1.123 +    ~nsToolkitProfileService()
   1.124 +    {
   1.125 +        gService = nullptr;
   1.126 +    }
   1.127 +
   1.128 +    NS_HIDDEN_(nsresult) Init();
   1.129 +
   1.130 +    nsresult CreateTimesInternal(nsIFile *profileDir);
   1.131 +
   1.132 +    nsresult CreateProfileInternal(nsIFile* aRootDir,
   1.133 +                                   const nsACString& aName,
   1.134 +                                   const nsACString* aProfileName,
   1.135 +                                   const nsACString* aAppName,
   1.136 +                                   const nsACString* aVendorName,
   1.137 +                                   /*in*/ nsIFile** aProfileDefaultsDir,
   1.138 +                                   bool aForExternalApp,
   1.139 +                                   nsIToolkitProfile** aResult);
   1.140 +
   1.141 +    nsRefPtr<nsToolkitProfile>  mFirst;
   1.142 +    nsCOMPtr<nsIToolkitProfile> mChosen;
   1.143 +    nsCOMPtr<nsIFile>           mAppData;
   1.144 +    nsCOMPtr<nsIFile>           mTempData;
   1.145 +    nsCOMPtr<nsIFile>           mListFile;
   1.146 +    bool mDirty;
   1.147 +    bool mStartWithLast;
   1.148 +    bool mStartOffline;
   1.149 +
   1.150 +    static nsToolkitProfileService *gService;
   1.151 +
   1.152 +    class ProfileEnumerator MOZ_FINAL : public nsISimpleEnumerator
   1.153 +    {
   1.154 +    public:
   1.155 +        NS_DECL_ISUPPORTS
   1.156 +        NS_DECL_NSISIMPLEENUMERATOR
   1.157 +
   1.158 +        ProfileEnumerator(nsToolkitProfile *first)
   1.159 +          { mCurrent = first; }
   1.160 +    private:
   1.161 +        ~ProfileEnumerator() { }
   1.162 +        nsRefPtr<nsToolkitProfile> mCurrent;
   1.163 +    };
   1.164 +};
   1.165 +
   1.166 +nsToolkitProfile::nsToolkitProfile(const nsACString& aName,
   1.167 +                                   nsIFile* aRootDir,
   1.168 +                                   nsIFile* aLocalDir,
   1.169 +                                   nsToolkitProfile* aPrev,
   1.170 +                                   bool aForExternalApp) :
   1.171 +    mPrev(aPrev),
   1.172 +    mName(aName),
   1.173 +    mRootDir(aRootDir),
   1.174 +    mLocalDir(aLocalDir),
   1.175 +    mLock(nullptr),
   1.176 +    mForExternalApp(aForExternalApp)
   1.177 +{
   1.178 +    NS_ASSERTION(aRootDir, "No file!");
   1.179 +
   1.180 +    if (!aForExternalApp) {
   1.181 +        if (aPrev) {
   1.182 +            aPrev->mNext = this;
   1.183 +        } else {
   1.184 +            nsToolkitProfileService::gService->mFirst = this;
   1.185 +        }
   1.186 +    }
   1.187 +}
   1.188 +
   1.189 +NS_IMPL_ISUPPORTS(nsToolkitProfile, nsIToolkitProfile)
   1.190 +
   1.191 +NS_IMETHODIMP
   1.192 +nsToolkitProfile::GetRootDir(nsIFile* *aResult)
   1.193 +{
   1.194 +    NS_ADDREF(*aResult = mRootDir);
   1.195 +    return NS_OK;
   1.196 +}
   1.197 +
   1.198 +NS_IMETHODIMP
   1.199 +nsToolkitProfile::GetLocalDir(nsIFile* *aResult)
   1.200 +{
   1.201 +    NS_ADDREF(*aResult = mLocalDir);
   1.202 +    return NS_OK;
   1.203 +}
   1.204 +
   1.205 +NS_IMETHODIMP
   1.206 +nsToolkitProfile::GetName(nsACString& aResult)
   1.207 +{
   1.208 +    aResult = mName;
   1.209 +    return NS_OK;
   1.210 +}
   1.211 +
   1.212 +NS_IMETHODIMP
   1.213 +nsToolkitProfile::SetName(const nsACString& aName)
   1.214 +{
   1.215 +    NS_ASSERTION(nsToolkitProfileService::gService,
   1.216 +                 "Where did my service go?");
   1.217 +    NS_ENSURE_TRUE(!mForExternalApp, NS_ERROR_NOT_IMPLEMENTED);
   1.218 +
   1.219 +    mName = aName;
   1.220 +    nsToolkitProfileService::gService->mDirty = true;
   1.221 +
   1.222 +    return NS_OK;
   1.223 +}
   1.224 +
   1.225 +NS_IMETHODIMP
   1.226 +nsToolkitProfile::Remove(bool removeFiles)
   1.227 +{
   1.228 +    NS_ASSERTION(nsToolkitProfileService::gService,
   1.229 +                 "Whoa, my service is gone.");
   1.230 +
   1.231 +    NS_ENSURE_TRUE(!mForExternalApp, NS_ERROR_NOT_IMPLEMENTED);
   1.232 +
   1.233 +    if (mLock)
   1.234 +        return NS_ERROR_FILE_IS_LOCKED;
   1.235 +
   1.236 +    if (!mPrev && !mNext && nsToolkitProfileService::gService->mFirst != this)
   1.237 +        return NS_ERROR_NOT_INITIALIZED;
   1.238 +
   1.239 +    if (removeFiles) {
   1.240 +        bool equals;
   1.241 +        nsresult rv = mRootDir->Equals(mLocalDir, &equals);
   1.242 +        if (NS_FAILED(rv))
   1.243 +            return rv;
   1.244 +
   1.245 +        // The root dir might contain the temp dir, so remove
   1.246 +        // the temp dir first.
   1.247 +        if (!equals)
   1.248 +            mLocalDir->Remove(true);
   1.249 +
   1.250 +        mRootDir->Remove(true);
   1.251 +    }
   1.252 +
   1.253 +    if (mPrev)
   1.254 +        mPrev->mNext = mNext;
   1.255 +    else
   1.256 +        nsToolkitProfileService::gService->mFirst = mNext;
   1.257 +
   1.258 +    if (mNext)
   1.259 +        mNext->mPrev = mPrev;
   1.260 +
   1.261 +    mPrev = nullptr;
   1.262 +    mNext = nullptr;
   1.263 +
   1.264 +    if (nsToolkitProfileService::gService->mChosen == this)
   1.265 +        nsToolkitProfileService::gService->mChosen = nullptr;
   1.266 +
   1.267 +    nsToolkitProfileService::gService->mDirty = true;
   1.268 +
   1.269 +    return NS_OK;
   1.270 +}
   1.271 +
   1.272 +NS_IMETHODIMP
   1.273 +nsToolkitProfile::Lock(nsIProfileUnlocker* *aUnlocker, nsIProfileLock* *aResult)
   1.274 +{
   1.275 +    if (mLock) {
   1.276 +        NS_ADDREF(*aResult = mLock);
   1.277 +        return NS_OK;
   1.278 +    }
   1.279 +
   1.280 +    nsRefPtr<nsToolkitProfileLock> lock = new nsToolkitProfileLock();
   1.281 +    if (!lock) return NS_ERROR_OUT_OF_MEMORY;
   1.282 +
   1.283 +    nsresult rv = lock->Init(this, aUnlocker);
   1.284 +    if (NS_FAILED(rv)) return rv;
   1.285 +
   1.286 +    NS_ADDREF(*aResult = lock);
   1.287 +    return NS_OK;
   1.288 +}
   1.289 +
   1.290 +NS_IMPL_ISUPPORTS(nsToolkitProfileLock, nsIProfileLock)
   1.291 +
   1.292 +nsresult
   1.293 +nsToolkitProfileLock::Init(nsToolkitProfile* aProfile, nsIProfileUnlocker* *aUnlocker)
   1.294 +{
   1.295 +    nsresult rv;
   1.296 +    rv = Init(aProfile->mRootDir, aProfile->mLocalDir, aUnlocker);
   1.297 +    if (NS_SUCCEEDED(rv))
   1.298 +        mProfile = aProfile;
   1.299 +
   1.300 +    return rv;
   1.301 +}
   1.302 +
   1.303 +nsresult
   1.304 +nsToolkitProfileLock::Init(nsIFile* aDirectory, nsIFile* aLocalDirectory,
   1.305 +                           nsIProfileUnlocker* *aUnlocker)
   1.306 +{
   1.307 +    nsresult rv;
   1.308 +
   1.309 +    rv = mLock.Lock(aDirectory, aUnlocker);
   1.310 +
   1.311 +    if (NS_SUCCEEDED(rv)) {
   1.312 +        mDirectory = aDirectory;
   1.313 +        mLocalDirectory = aLocalDirectory;
   1.314 +    }
   1.315 +
   1.316 +    return rv;
   1.317 +}
   1.318 +
   1.319 +NS_IMETHODIMP
   1.320 +nsToolkitProfileLock::GetDirectory(nsIFile* *aResult)
   1.321 +{
   1.322 +    if (!mDirectory) {
   1.323 +        NS_ERROR("Not initialized, or unlocked!");
   1.324 +        return NS_ERROR_NOT_INITIALIZED;
   1.325 +    }
   1.326 +
   1.327 +    NS_ADDREF(*aResult = mDirectory);
   1.328 +    return NS_OK;
   1.329 +}
   1.330 +
   1.331 +NS_IMETHODIMP
   1.332 +nsToolkitProfileLock::GetLocalDirectory(nsIFile* *aResult)
   1.333 +{
   1.334 +    if (!mLocalDirectory) {
   1.335 +        NS_ERROR("Not initialized, or unlocked!");
   1.336 +        return NS_ERROR_NOT_INITIALIZED;
   1.337 +    }
   1.338 +
   1.339 +    NS_ADDREF(*aResult = mLocalDirectory);
   1.340 +    return NS_OK;
   1.341 +}
   1.342 +
   1.343 +NS_IMETHODIMP
   1.344 +nsToolkitProfileLock::Unlock()
   1.345 +{
   1.346 +    if (!mDirectory) {
   1.347 +        NS_ERROR("Unlocking a never-locked nsToolkitProfileLock!");
   1.348 +        return NS_ERROR_UNEXPECTED;
   1.349 +    }
   1.350 +
   1.351 +    mLock.Unlock();
   1.352 +
   1.353 +    if (mProfile) {
   1.354 +        mProfile->mLock = nullptr;
   1.355 +        mProfile = nullptr;
   1.356 +    }
   1.357 +    mDirectory = nullptr;
   1.358 +    mLocalDirectory = nullptr;
   1.359 +
   1.360 +    return NS_OK;
   1.361 +}
   1.362 +
   1.363 +NS_IMETHODIMP
   1.364 +nsToolkitProfileLock::GetReplacedLockTime(PRTime *aResult)
   1.365 +{
   1.366 +    mLock.GetReplacedLockTime(aResult);
   1.367 +    return NS_OK;
   1.368 +}
   1.369 +
   1.370 +nsToolkitProfileLock::~nsToolkitProfileLock()
   1.371 +{
   1.372 +    if (mDirectory) {
   1.373 +        Unlock();
   1.374 +    }
   1.375 +}
   1.376 +
   1.377 +nsToolkitProfileService*
   1.378 +nsToolkitProfileService::gService = nullptr;
   1.379 +
   1.380 +NS_IMPL_ISUPPORTS(nsToolkitProfileService,
   1.381 +                  nsIToolkitProfileService)
   1.382 +
   1.383 +nsresult
   1.384 +nsToolkitProfileService::Init()
   1.385 +{
   1.386 +    NS_ASSERTION(gDirServiceProvider, "No dirserviceprovider!");
   1.387 +    nsresult rv;
   1.388 +
   1.389 +    rv = gDirServiceProvider->GetUserAppDataDirectory(getter_AddRefs(mAppData));
   1.390 +    NS_ENSURE_SUCCESS(rv, rv);
   1.391 +
   1.392 +    rv = gDirServiceProvider->GetUserLocalDataDirectory(getter_AddRefs(mTempData));
   1.393 +    NS_ENSURE_SUCCESS(rv, rv);
   1.394 +
   1.395 +    rv = mAppData->Clone(getter_AddRefs(mListFile));
   1.396 +    NS_ENSURE_SUCCESS(rv, rv);
   1.397 +
   1.398 +    rv = mListFile->AppendNative(NS_LITERAL_CSTRING("profiles.ini"));
   1.399 +    NS_ENSURE_SUCCESS(rv, rv);
   1.400 +
   1.401 +    bool exists;
   1.402 +    rv = mListFile->IsFile(&exists);
   1.403 +    if (NS_FAILED(rv) || !exists) {
   1.404 +        return NS_OK;
   1.405 +    }
   1.406 +
   1.407 +    int64_t size;
   1.408 +    rv = mListFile->GetFileSize(&size);
   1.409 +    if (NS_FAILED(rv) || !size) {
   1.410 +        return NS_OK;
   1.411 +    }
   1.412 +
   1.413 +    nsINIParser parser;
   1.414 +    rv = parser.Init(mListFile);
   1.415 +    // Init does not fail on parsing errors, only on OOM/really unexpected
   1.416 +    // conditions.
   1.417 +    if (NS_FAILED(rv))
   1.418 +        return rv;
   1.419 +
   1.420 +    nsAutoCString buffer;
   1.421 +    rv = parser.GetString("General", "StartWithLastProfile", buffer);
   1.422 +    if (NS_SUCCEEDED(rv) && buffer.EqualsLiteral("0"))
   1.423 +        mStartWithLast = false;
   1.424 +
   1.425 +    nsToolkitProfile* currentProfile = nullptr;
   1.426 +
   1.427 +    unsigned int c = 0;
   1.428 +    for (c = 0; true; ++c) {
   1.429 +        nsAutoCString profileID("Profile");
   1.430 +        profileID.AppendInt(c);
   1.431 +
   1.432 +        rv = parser.GetString(profileID.get(), "IsRelative", buffer);
   1.433 +        if (NS_FAILED(rv)) break;
   1.434 +
   1.435 +        bool isRelative = buffer.EqualsLiteral("1");
   1.436 +
   1.437 +        nsAutoCString filePath;
   1.438 +
   1.439 +        rv = parser.GetString(profileID.get(), "Path", filePath);
   1.440 +        if (NS_FAILED(rv)) {
   1.441 +            NS_ERROR("Malformed profiles.ini: Path= not found");
   1.442 +            continue;
   1.443 +        }
   1.444 +
   1.445 +        rv = parser.GetString(profileID.get(), "Name", buffer);
   1.446 +        if (NS_FAILED(rv)) {
   1.447 +            NS_ERROR("Malformed profiles.ini: Name= not found");
   1.448 +            continue;
   1.449 +        }
   1.450 +
   1.451 +        nsCOMPtr<nsIFile> rootDir;
   1.452 +        rv = NS_NewNativeLocalFile(EmptyCString(), true,
   1.453 +                                   getter_AddRefs(rootDir));
   1.454 +        NS_ENSURE_SUCCESS(rv, rv);
   1.455 +
   1.456 +        if (isRelative) {
   1.457 +            rv = rootDir->SetRelativeDescriptor(mAppData, filePath);
   1.458 +        } else {
   1.459 +            rv = rootDir->SetPersistentDescriptor(filePath);
   1.460 +        }
   1.461 +        if (NS_FAILED(rv)) continue;
   1.462 +
   1.463 +        nsCOMPtr<nsIFile> localDir;
   1.464 +        if (isRelative) {
   1.465 +            rv = NS_NewNativeLocalFile(EmptyCString(), true,
   1.466 +                                       getter_AddRefs(localDir));
   1.467 +            NS_ENSURE_SUCCESS(rv, rv);
   1.468 +
   1.469 +            rv = localDir->SetRelativeDescriptor(mTempData, filePath);
   1.470 +        } else {
   1.471 +            localDir = rootDir;
   1.472 +        }
   1.473 +
   1.474 +        currentProfile = new nsToolkitProfile(buffer,
   1.475 +                                              rootDir, localDir,
   1.476 +                                              currentProfile, false);
   1.477 +        NS_ENSURE_TRUE(currentProfile, NS_ERROR_OUT_OF_MEMORY);
   1.478 +
   1.479 +        rv = parser.GetString(profileID.get(), "Default", buffer);
   1.480 +        if (NS_SUCCEEDED(rv) && buffer.EqualsLiteral("1"))
   1.481 +            mChosen = currentProfile;
   1.482 +    }
   1.483 +    if (!mChosen && mFirst && !mFirst->mNext) // only one profile
   1.484 +        mChosen = mFirst;
   1.485 +    return NS_OK;
   1.486 +}
   1.487 +
   1.488 +NS_IMETHODIMP
   1.489 +nsToolkitProfileService::SetStartWithLastProfile(bool aValue)
   1.490 +{
   1.491 +    if (mStartWithLast != aValue) {
   1.492 +        mStartWithLast = aValue;
   1.493 +        mDirty = true;
   1.494 +    }
   1.495 +    return NS_OK;
   1.496 +}
   1.497 +
   1.498 +NS_IMETHODIMP
   1.499 +nsToolkitProfileService::GetStartWithLastProfile(bool *aResult)
   1.500 +{
   1.501 +    *aResult = mStartWithLast;
   1.502 +    return NS_OK;
   1.503 +}
   1.504 +
   1.505 +NS_IMETHODIMP
   1.506 +nsToolkitProfileService::GetStartOffline(bool *aResult)
   1.507 +{
   1.508 +    *aResult = mStartOffline;
   1.509 +    return NS_OK;
   1.510 +}
   1.511 +
   1.512 +NS_IMETHODIMP
   1.513 +nsToolkitProfileService::SetStartOffline(bool aValue)
   1.514 +{
   1.515 +    mStartOffline = aValue;
   1.516 +    return NS_OK;
   1.517 +}
   1.518 +
   1.519 +NS_IMETHODIMP
   1.520 +nsToolkitProfileService::GetProfiles(nsISimpleEnumerator* *aResult)
   1.521 +{
   1.522 +    *aResult = new ProfileEnumerator(this->mFirst);
   1.523 +    if (!*aResult)
   1.524 +        return NS_ERROR_OUT_OF_MEMORY;
   1.525 +
   1.526 +    NS_ADDREF(*aResult);
   1.527 +    return NS_OK;
   1.528 +}
   1.529 +
   1.530 +NS_IMPL_ISUPPORTS(nsToolkitProfileService::ProfileEnumerator,
   1.531 +                  nsISimpleEnumerator)
   1.532 +
   1.533 +NS_IMETHODIMP
   1.534 +nsToolkitProfileService::ProfileEnumerator::HasMoreElements(bool* aResult)
   1.535 +{
   1.536 +    *aResult = mCurrent ? true : false;
   1.537 +    return NS_OK;
   1.538 +}
   1.539 +
   1.540 +NS_IMETHODIMP
   1.541 +nsToolkitProfileService::ProfileEnumerator::GetNext(nsISupports* *aResult)
   1.542 +{
   1.543 +    if (!mCurrent) return NS_ERROR_FAILURE;
   1.544 +
   1.545 +    NS_ADDREF(*aResult = mCurrent);
   1.546 +
   1.547 +    mCurrent = mCurrent->mNext;
   1.548 +    return NS_OK;
   1.549 +}
   1.550 +
   1.551 +NS_IMETHODIMP
   1.552 +nsToolkitProfileService::GetSelectedProfile(nsIToolkitProfile* *aResult)
   1.553 +{
   1.554 +    if (!mChosen && mFirst && !mFirst->mNext) // only one profile
   1.555 +        mChosen = mFirst;
   1.556 +
   1.557 +    if (!mChosen) return NS_ERROR_FAILURE;
   1.558 +
   1.559 +    NS_ADDREF(*aResult = mChosen);
   1.560 +    return NS_OK;
   1.561 +}
   1.562 +
   1.563 +NS_IMETHODIMP
   1.564 +nsToolkitProfileService::SetSelectedProfile(nsIToolkitProfile* aProfile)
   1.565 +{
   1.566 +    if (mChosen != aProfile) {
   1.567 +        mChosen = aProfile;
   1.568 +        mDirty = true;
   1.569 +    }
   1.570 +    return NS_OK;
   1.571 +}
   1.572 +
   1.573 +NS_IMETHODIMP
   1.574 +nsToolkitProfileService::GetProfileByName(const nsACString& aName,
   1.575 +                                          nsIToolkitProfile* *aResult)
   1.576 +{
   1.577 +    nsToolkitProfile* curP = mFirst;
   1.578 +    while (curP) {
   1.579 +        if (curP->mName.Equals(aName)) {
   1.580 +            NS_ADDREF(*aResult = curP);
   1.581 +            return NS_OK;
   1.582 +        }
   1.583 +        curP = curP->mNext;
   1.584 +    }
   1.585 +
   1.586 +    return NS_ERROR_FAILURE;
   1.587 +}
   1.588 +
   1.589 +NS_IMETHODIMP
   1.590 +nsToolkitProfileService::LockProfilePath(nsIFile* aDirectory,
   1.591 +                                         nsIFile* aLocalDirectory,
   1.592 +                                         nsIProfileLock* *aResult)
   1.593 +{
   1.594 +    return NS_LockProfilePath(aDirectory, aLocalDirectory, nullptr, aResult);
   1.595 +}
   1.596 +
   1.597 +nsresult
   1.598 +NS_LockProfilePath(nsIFile* aPath, nsIFile* aTempPath,
   1.599 +                   nsIProfileUnlocker* *aUnlocker, nsIProfileLock* *aResult)
   1.600 +{
   1.601 +    nsRefPtr<nsToolkitProfileLock> lock = new nsToolkitProfileLock();
   1.602 +    if (!lock) return NS_ERROR_OUT_OF_MEMORY;
   1.603 +
   1.604 +    nsresult rv = lock->Init(aPath, aTempPath, aUnlocker);
   1.605 +    if (NS_FAILED(rv)) return rv;
   1.606 +
   1.607 +    NS_ADDREF(*aResult = lock);
   1.608 +    return NS_OK;
   1.609 +}
   1.610 +
   1.611 +static const char kTable[] =
   1.612 +    { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
   1.613 +      'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
   1.614 +      '1', '2', '3', '4', '5', '6', '7', '8', '9', '0' };
   1.615 +
   1.616 +static void SaltProfileName(nsACString& aName)
   1.617 +{
   1.618 +    double fpTime = double(PR_Now());
   1.619 +
   1.620 +    // use 1e-6, granularity of PR_Now() on the mac is seconds
   1.621 +    srand((unsigned int)(fpTime * 1e-6 + 0.5));
   1.622 +
   1.623 +    char salt[9];
   1.624 +
   1.625 +    int i;
   1.626 +    for (i = 0; i < 8; ++i)
   1.627 +        salt[i] = kTable[rand() % ArrayLength(kTable)];
   1.628 +
   1.629 +    salt[8] = '.';
   1.630 +
   1.631 +    aName.Insert(salt, 0, 9);
   1.632 +}
   1.633 +
   1.634 +NS_IMETHODIMP
   1.635 +nsToolkitProfileService::CreateDefaultProfileForApp(const nsACString& aProfileName,
   1.636 +                                                    const nsACString& aAppName,
   1.637 +                                                    const nsACString& aVendorName,
   1.638 +                                                    nsIFile* aProfileDefaultsDir,
   1.639 +                                                    nsIToolkitProfile** aResult)
   1.640 +{
   1.641 +    NS_ENSURE_STATE(!aProfileName.IsEmpty() || !aAppName.IsEmpty());
   1.642 +    nsCOMPtr<nsIFile> appData;
   1.643 +    nsresult rv =
   1.644 +        gDirServiceProvider->GetUserDataDirectory(getter_AddRefs(appData),
   1.645 +                                                  false,
   1.646 +                                                  &aProfileName,
   1.647 +                                                  &aAppName,
   1.648 +                                                  &aVendorName);
   1.649 +    NS_ENSURE_SUCCESS(rv, rv);
   1.650 +
   1.651 +    nsCOMPtr<nsIFile> profilesini;
   1.652 +    appData->Clone(getter_AddRefs(profilesini));
   1.653 +    rv = profilesini->AppendNative(NS_LITERAL_CSTRING("profiles.ini"));
   1.654 +    NS_ENSURE_SUCCESS(rv, rv);
   1.655 +
   1.656 +    bool exists = false;
   1.657 +    profilesini->Exists(&exists);
   1.658 +    NS_ENSURE_FALSE(exists, NS_ERROR_ALREADY_INITIALIZED);
   1.659 +
   1.660 +    nsIFile* profileDefaultsDir = aProfileDefaultsDir;
   1.661 +    rv = CreateProfileInternal(nullptr,
   1.662 +                               NS_LITERAL_CSTRING("default"),
   1.663 +                               &aProfileName, &aAppName, &aVendorName,
   1.664 +                               &profileDefaultsDir, true, aResult);
   1.665 +    NS_ENSURE_SUCCESS(rv, rv);
   1.666 +    NS_ENSURE_STATE(*aResult);
   1.667 +
   1.668 +    nsCOMPtr<nsIFile> rootDir;
   1.669 +    (*aResult)->GetRootDir(getter_AddRefs(rootDir));
   1.670 +    NS_ENSURE_SUCCESS(rv, rv);
   1.671 +
   1.672 +    nsAutoCString profileDir;
   1.673 +    rv = rootDir->GetRelativeDescriptor(appData, profileDir);
   1.674 +    NS_ENSURE_SUCCESS(rv, rv);
   1.675 +
   1.676 +    nsCString ini;
   1.677 +    ini.SetCapacity(512);
   1.678 +    ini.AppendLiteral("[General]\n");
   1.679 +    ini.AppendLiteral("StartWithLastProfile=1\n\n");
   1.680 +
   1.681 +    ini.AppendLiteral("[Profile0]\n");
   1.682 +    ini.AppendLiteral("Name=default\n");
   1.683 +    ini.AppendLiteral("IsRelative=1\n");
   1.684 +    ini.AppendLiteral("Path=");
   1.685 +    ini.Append(profileDir);
   1.686 +    ini.Append('\n');
   1.687 +    ini.AppendLiteral("Default=1\n\n");
   1.688 +
   1.689 +    FILE* writeFile;
   1.690 +    rv = profilesini->OpenANSIFileDesc("w", &writeFile);
   1.691 +    NS_ENSURE_SUCCESS(rv, rv);
   1.692 +
   1.693 +    if (fwrite(ini.get(), sizeof(char), ini.Length(), writeFile) !=
   1.694 +        ini.Length()) {
   1.695 +        rv = NS_ERROR_UNEXPECTED;
   1.696 +    }
   1.697 +    fclose(writeFile);
   1.698 +    return rv;
   1.699 +}
   1.700 +
   1.701 +NS_IMETHODIMP
   1.702 +nsToolkitProfileService::CreateProfile(nsIFile* aRootDir,
   1.703 +                                       const nsACString& aName,
   1.704 +                                       nsIToolkitProfile** aResult)
   1.705 +{
   1.706 +    return CreateProfileInternal(aRootDir, aName,
   1.707 +                                 nullptr, nullptr, nullptr, nullptr, false, aResult);
   1.708 +}
   1.709 +
   1.710 +nsresult
   1.711 +nsToolkitProfileService::CreateProfileInternal(nsIFile* aRootDir,
   1.712 +                                               const nsACString& aName,
   1.713 +                                               const nsACString* aProfileName,
   1.714 +                                               const nsACString* aAppName,
   1.715 +                                               const nsACString* aVendorName,
   1.716 +                                               nsIFile** aProfileDefaultsDir,
   1.717 +                                               bool aForExternalApp,
   1.718 +                                               nsIToolkitProfile** aResult)
   1.719 +{
   1.720 +    nsresult rv = NS_ERROR_FAILURE;
   1.721 +
   1.722 +    if (!aForExternalApp) {
   1.723 +        rv = GetProfileByName(aName, aResult);
   1.724 +        if (NS_SUCCEEDED(rv)) {
   1.725 +            return rv;
   1.726 +        }
   1.727 +    }
   1.728 +
   1.729 +    nsCOMPtr<nsIFile> rootDir (aRootDir);
   1.730 +
   1.731 +    nsAutoCString dirName;
   1.732 +    if (!rootDir) {
   1.733 +        rv = gDirServiceProvider->GetUserProfilesRootDir(getter_AddRefs(rootDir),
   1.734 +                                                         aProfileName, aAppName,
   1.735 +                                                         aVendorName);
   1.736 +        NS_ENSURE_SUCCESS(rv, rv);
   1.737 +
   1.738 +        dirName = aName;
   1.739 +        SaltProfileName(dirName);
   1.740 +
   1.741 +        if (NS_IsNativeUTF8()) {
   1.742 +            rootDir->AppendNative(dirName);
   1.743 +        } else {
   1.744 +            rootDir->Append(NS_ConvertUTF8toUTF16(dirName));
   1.745 +        }
   1.746 +    }
   1.747 +
   1.748 +    nsCOMPtr<nsIFile> localDir;
   1.749 +
   1.750 +    bool isRelative;
   1.751 +    rv = mAppData->Contains(rootDir, true, &isRelative);
   1.752 +    if (NS_SUCCEEDED(rv) && isRelative) {
   1.753 +        nsAutoCString path;
   1.754 +        rv = rootDir->GetRelativeDescriptor(mAppData, path);
   1.755 +        NS_ENSURE_SUCCESS(rv, rv);
   1.756 +
   1.757 +        rv = NS_NewNativeLocalFile(EmptyCString(), true,
   1.758 +                                   getter_AddRefs(localDir));
   1.759 +        NS_ENSURE_SUCCESS(rv, rv);
   1.760 +
   1.761 +        rv = localDir->SetRelativeDescriptor(mTempData, path);
   1.762 +    } else {
   1.763 +        localDir = rootDir;
   1.764 +    }
   1.765 +
   1.766 +    bool exists;
   1.767 +    rv = rootDir->Exists(&exists);
   1.768 +    NS_ENSURE_SUCCESS(rv, rv);
   1.769 +
   1.770 +    if (exists) {
   1.771 +        rv = rootDir->IsDirectory(&exists);
   1.772 +        NS_ENSURE_SUCCESS(rv, rv);
   1.773 +
   1.774 +        if (!exists)
   1.775 +            return NS_ERROR_FILE_NOT_DIRECTORY;
   1.776 +    }
   1.777 +    else {
   1.778 +        nsCOMPtr<nsIFile> profileDefaultsDir;
   1.779 +        nsCOMPtr<nsIFile> profileDirParent;
   1.780 +        nsAutoString profileDirName;
   1.781 +
   1.782 +        rv = rootDir->GetParent(getter_AddRefs(profileDirParent));
   1.783 +        NS_ENSURE_SUCCESS(rv, rv);
   1.784 +
   1.785 +        rv = rootDir->GetLeafName(profileDirName);
   1.786 +        NS_ENSURE_SUCCESS(rv, rv);
   1.787 +
   1.788 +        if (aProfileDefaultsDir) {
   1.789 +            profileDefaultsDir = *aProfileDefaultsDir;
   1.790 +        } else {
   1.791 +            bool dummy;
   1.792 +            rv = gDirServiceProvider->GetFile(NS_APP_PROFILE_DEFAULTS_50_DIR, &dummy,
   1.793 +                                              getter_AddRefs(profileDefaultsDir));
   1.794 +        }
   1.795 +
   1.796 +        if (NS_SUCCEEDED(rv) && profileDefaultsDir)
   1.797 +            rv = profileDefaultsDir->CopyTo(profileDirParent,
   1.798 +                                            profileDirName);
   1.799 +        if (NS_FAILED(rv) || !profileDefaultsDir) {
   1.800 +            // if copying failed, lets just ensure that the profile directory exists.
   1.801 +            rv = rootDir->Create(nsIFile::DIRECTORY_TYPE, 0700);
   1.802 +            NS_ENSURE_SUCCESS(rv, rv);
   1.803 +        }
   1.804 +        rv = rootDir->SetPermissions(0700);
   1.805 +#ifndef ANDROID
   1.806 +        // If the profile is on the sdcard, this will fail but its non-fatal
   1.807 +        NS_ENSURE_SUCCESS(rv, rv);
   1.808 +#endif
   1.809 +    }
   1.810 +
   1.811 +    rv = localDir->Exists(&exists);
   1.812 +    NS_ENSURE_SUCCESS(rv, rv);
   1.813 +
   1.814 +    if (!exists) {
   1.815 +        rv = localDir->Create(nsIFile::DIRECTORY_TYPE, 0700);
   1.816 +        NS_ENSURE_SUCCESS(rv, rv);
   1.817 +    }
   1.818 +
   1.819 +    // We created a new profile dir. Let's store a creation timestamp.
   1.820 +    // Note that this code path does not apply if the profile dir was
   1.821 +    // created prior to launching.
   1.822 +    rv = CreateTimesInternal(rootDir);
   1.823 +    NS_ENSURE_SUCCESS(rv, rv);
   1.824 +
   1.825 +    nsToolkitProfile* last = aForExternalApp ? nullptr : mFirst;
   1.826 +    if (last) {
   1.827 +        while (last->mNext)
   1.828 +            last = last->mNext;
   1.829 +    }
   1.830 +
   1.831 +    nsCOMPtr<nsIToolkitProfile> profile =
   1.832 +        new nsToolkitProfile(aName, rootDir, localDir, last, aForExternalApp);
   1.833 +    if (!profile) return NS_ERROR_OUT_OF_MEMORY;
   1.834 +
   1.835 +    NS_ADDREF(*aResult = profile);
   1.836 +    return NS_OK;
   1.837 +}
   1.838 +
   1.839 +nsresult
   1.840 +nsToolkitProfileService::CreateTimesInternal(nsIFile* aProfileDir)
   1.841 +{
   1.842 +    nsresult rv = NS_ERROR_FAILURE;
   1.843 +    nsCOMPtr<nsIFile> creationLog;
   1.844 +    rv = aProfileDir->Clone(getter_AddRefs(creationLog));
   1.845 +    NS_ENSURE_SUCCESS(rv, rv);
   1.846 +
   1.847 +    rv = creationLog->AppendNative(NS_LITERAL_CSTRING("times.json"));
   1.848 +    NS_ENSURE_SUCCESS(rv, rv);
   1.849 +
   1.850 +    bool exists = false;
   1.851 +    creationLog->Exists(&exists);
   1.852 +    if (exists) {
   1.853 +      return NS_OK;
   1.854 +    }
   1.855 +
   1.856 +    rv = creationLog->Create(nsIFile::NORMAL_FILE_TYPE, 0700);
   1.857 +    NS_ENSURE_SUCCESS(rv, rv);
   1.858 +
   1.859 +    // We don't care about microsecond resolution.
   1.860 +    int64_t msec = PR_Now() / PR_USEC_PER_MSEC;
   1.861 +
   1.862 +    // Write it out.
   1.863 +    PRFileDesc *writeFile;
   1.864 +    rv = creationLog->OpenNSPRFileDesc(PR_WRONLY, 0700, &writeFile);
   1.865 +    NS_ENSURE_SUCCESS(rv, rv);
   1.866 +
   1.867 +    PR_fprintf(writeFile, "{\n\"created\": %lld\n}\n", msec);
   1.868 +    PR_Close(writeFile);
   1.869 +    return NS_OK;
   1.870 +}
   1.871 +
   1.872 +NS_IMETHODIMP
   1.873 +nsToolkitProfileService::GetProfileCount(uint32_t *aResult)
   1.874 +{
   1.875 +    if (!mFirst)
   1.876 +        *aResult = 0;
   1.877 +    else if (! mFirst->mNext)
   1.878 +        *aResult = 1;
   1.879 +    else
   1.880 +        *aResult = 2;
   1.881 +
   1.882 +    return NS_OK;
   1.883 +}
   1.884 +
   1.885 +NS_IMETHODIMP
   1.886 +nsToolkitProfileService::Flush()
   1.887 +{
   1.888 +    // Errors during writing might cause unhappy semi-written files.
   1.889 +    // To avoid this, write the entire thing to a buffer, then write
   1.890 +    // that buffer to disk.
   1.891 +
   1.892 +    nsresult rv;
   1.893 +    uint32_t pCount = 0;
   1.894 +    nsToolkitProfile *cur;
   1.895 +
   1.896 +    for (cur = mFirst; cur != nullptr; cur = cur->mNext)
   1.897 +        ++pCount;
   1.898 +
   1.899 +    uint32_t length;
   1.900 +    nsAutoArrayPtr<char> buffer (new char[100+MAXPATHLEN*pCount]);
   1.901 +
   1.902 +    NS_ENSURE_TRUE(buffer, NS_ERROR_OUT_OF_MEMORY);
   1.903 +
   1.904 +    char *end = buffer;
   1.905 +
   1.906 +    end += sprintf(end,
   1.907 +                   "[General]\n"
   1.908 +                   "StartWithLastProfile=%s\n\n",
   1.909 +                   mStartWithLast ? "1" : "0");
   1.910 +
   1.911 +    nsAutoCString path;
   1.912 +    cur = mFirst;
   1.913 +    pCount = 0;
   1.914 +
   1.915 +    while (cur) {
   1.916 +        // if the profile dir is relative to appdir...
   1.917 +        bool isRelative;
   1.918 +        rv = mAppData->Contains(cur->mRootDir, true, &isRelative);
   1.919 +        if (NS_SUCCEEDED(rv) && isRelative) {
   1.920 +            // we use a relative descriptor
   1.921 +            rv = cur->mRootDir->GetRelativeDescriptor(mAppData, path);
   1.922 +        } else {
   1.923 +            // otherwise, a persistent descriptor
   1.924 +            rv = cur->mRootDir->GetPersistentDescriptor(path);
   1.925 +            NS_ENSURE_SUCCESS(rv, rv);
   1.926 +        }
   1.927 +
   1.928 +        end += sprintf(end,
   1.929 +                       "[Profile%u]\n"
   1.930 +                       "Name=%s\n"
   1.931 +                       "IsRelative=%s\n"
   1.932 +                       "Path=%s\n",
   1.933 +                       pCount, cur->mName.get(),
   1.934 +                       isRelative ? "1" : "0", path.get());
   1.935 +
   1.936 +        if (mChosen == cur) {
   1.937 +            end += sprintf(end, "Default=1\n");
   1.938 +        }
   1.939 +
   1.940 +        end += sprintf(end, "\n");
   1.941 +
   1.942 +        cur = cur->mNext;
   1.943 +        ++pCount;
   1.944 +    }
   1.945 +
   1.946 +    FILE* writeFile;
   1.947 +    rv = mListFile->OpenANSIFileDesc("w", &writeFile);
   1.948 +    NS_ENSURE_SUCCESS(rv, rv);
   1.949 +
   1.950 +    if (buffer) {
   1.951 +        length = end - buffer;
   1.952 +
   1.953 +        if (fwrite(buffer, sizeof(char), length, writeFile) != length) {
   1.954 +            fclose(writeFile);
   1.955 +            return NS_ERROR_UNEXPECTED;
   1.956 +        }
   1.957 +    }
   1.958 +
   1.959 +    fclose(writeFile);
   1.960 +    return NS_OK;
   1.961 +}
   1.962 +
   1.963 +NS_IMPL_ISUPPORTS(nsToolkitProfileFactory, nsIFactory)
   1.964 +
   1.965 +NS_IMETHODIMP
   1.966 +nsToolkitProfileFactory::CreateInstance(nsISupports* aOuter, const nsID& aIID,
   1.967 +                                        void** aResult)
   1.968 +{
   1.969 +    if (aOuter)
   1.970 +        return NS_ERROR_NO_AGGREGATION;
   1.971 +
   1.972 +    nsCOMPtr<nsIToolkitProfileService> profileService =
   1.973 +        nsToolkitProfileService::gService;
   1.974 +    if (!profileService) {
   1.975 +        nsresult rv = NS_NewToolkitProfileService(getter_AddRefs(profileService));
   1.976 +        if (NS_FAILED(rv))
   1.977 +            return rv;
   1.978 +    }
   1.979 +    return profileService->QueryInterface(aIID, aResult);
   1.980 +}
   1.981 +
   1.982 +NS_IMETHODIMP
   1.983 +nsToolkitProfileFactory::LockFactory(bool aVal)
   1.984 +{
   1.985 +    return NS_OK;
   1.986 +}
   1.987 +
   1.988 +nsresult
   1.989 +NS_NewToolkitProfileFactory(nsIFactory* *aResult)
   1.990 +{
   1.991 +    *aResult = new nsToolkitProfileFactory();
   1.992 +    if (!*aResult)
   1.993 +        return NS_ERROR_OUT_OF_MEMORY;
   1.994 +
   1.995 +    NS_ADDREF(*aResult);
   1.996 +    return NS_OK;
   1.997 +}
   1.998 +
   1.999 +nsresult
  1.1000 +NS_NewToolkitProfileService(nsIToolkitProfileService* *aResult)
  1.1001 +{
  1.1002 +    nsToolkitProfileService* profileService = new nsToolkitProfileService();
  1.1003 +    if (!profileService)
  1.1004 +        return NS_ERROR_OUT_OF_MEMORY;
  1.1005 +    nsresult rv = profileService->Init();
  1.1006 +    if (NS_FAILED(rv)) {
  1.1007 +        NS_ERROR("nsToolkitProfileService::Init failed!");
  1.1008 +        delete profileService;
  1.1009 +        return rv;
  1.1010 +    }
  1.1011 +
  1.1012 +    NS_ADDREF(*aResult = profileService);
  1.1013 +    return NS_OK;
  1.1014 +}
  1.1015 +
  1.1016 +nsresult
  1.1017 +XRE_GetFileFromPath(const char *aPath, nsIFile* *aResult)
  1.1018 +{
  1.1019 +#if defined(XP_MACOSX)
  1.1020 +    int32_t pathLen = strlen(aPath);
  1.1021 +    if (pathLen > MAXPATHLEN)
  1.1022 +        return NS_ERROR_INVALID_ARG;
  1.1023 +
  1.1024 +    CFURLRef fullPath =
  1.1025 +        CFURLCreateFromFileSystemRepresentation(nullptr, (const UInt8 *) aPath,
  1.1026 +                                                pathLen, true);
  1.1027 +    if (!fullPath)
  1.1028 +        return NS_ERROR_FAILURE;
  1.1029 +
  1.1030 +    nsCOMPtr<nsIFile> lf;
  1.1031 +    nsresult rv = NS_NewNativeLocalFile(EmptyCString(), true,
  1.1032 +                                        getter_AddRefs(lf));
  1.1033 +    if (NS_SUCCEEDED(rv)) {
  1.1034 +        nsCOMPtr<nsILocalFileMac> lfMac = do_QueryInterface(lf, &rv);
  1.1035 +        if (NS_SUCCEEDED(rv)) {
  1.1036 +            rv = lfMac->InitWithCFURL(fullPath);
  1.1037 +            if (NS_SUCCEEDED(rv))
  1.1038 +                NS_ADDREF(*aResult = lf);
  1.1039 +        }
  1.1040 +    }
  1.1041 +    CFRelease(fullPath);
  1.1042 +    return rv;
  1.1043 +
  1.1044 +#elif defined(XP_UNIX)
  1.1045 +    char fullPath[MAXPATHLEN];
  1.1046 +
  1.1047 +    if (!realpath(aPath, fullPath))
  1.1048 +        return NS_ERROR_FAILURE;
  1.1049 +
  1.1050 +    return NS_NewNativeLocalFile(nsDependentCString(fullPath), true,
  1.1051 +                                 aResult);
  1.1052 +#elif defined(XP_WIN)
  1.1053 +    WCHAR fullPath[MAXPATHLEN];
  1.1054 +
  1.1055 +    if (!_wfullpath(fullPath, NS_ConvertUTF8toUTF16(aPath).get(), MAXPATHLEN))
  1.1056 +        return NS_ERROR_FAILURE;
  1.1057 +
  1.1058 +    return NS_NewLocalFile(nsDependentString(fullPath), true,
  1.1059 +                           aResult);
  1.1060 +
  1.1061 +#else
  1.1062 +#error Platform-specific logic needed here.
  1.1063 +#endif
  1.1064 +}

mercurial