toolkit/profile/nsToolkitProfileService.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

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

mercurial