summaryrefslogtreecommitdiffstats
path: root/comm/mail/components/migration/src/nsNetscapeProfileMigratorBase.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'comm/mail/components/migration/src/nsNetscapeProfileMigratorBase.cpp')
-rw-r--r--comm/mail/components/migration/src/nsNetscapeProfileMigratorBase.cpp371
1 files changed, 371 insertions, 0 deletions
diff --git a/comm/mail/components/migration/src/nsNetscapeProfileMigratorBase.cpp b/comm/mail/components/migration/src/nsNetscapeProfileMigratorBase.cpp
new file mode 100644
index 0000000000..b4a7affe03
--- /dev/null
+++ b/comm/mail/components/migration/src/nsNetscapeProfileMigratorBase.cpp
@@ -0,0 +1,371 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsAppDirectoryServiceDefs.h"
+#include "nsIFile.h"
+#include "nsIInputStream.h"
+#include "nsILineInputStream.h"
+#include "nsIPrefBranch.h"
+#include "nsIPrefLocalizedString.h"
+#include "nsIPrefService.h"
+#include "nsIServiceManager.h"
+#include "nsIURL.h"
+#include "nsNetscapeProfileMigratorBase.h"
+#include "nsNetUtil.h"
+#include "prtime.h"
+#include "prprf.h"
+#include "nsITimer.h"
+#include "nsINIParser.h"
+#include "nsMailProfileMigratorUtils.h"
+#include "nsIDirectoryEnumerator.h"
+#include "nsServiceManagerUtils.h"
+
+#define MIGRATION_BUNDLE \
+ "chrome://messenger/locale/migration/migration.properties"
+
+#define FILE_NAME_PREFS_5X u"prefs.js"_ns
+
+///////////////////////////////////////////////////////////////////////////////
+// nsNetscapeProfileMigratorBase
+nsNetscapeProfileMigratorBase::nsNetscapeProfileMigratorBase() {
+ mObserverService = do_GetService("@mozilla.org/observer-service;1");
+ mMaxProgress = 0;
+ mCurrentProgress = 0;
+ mFileCopyTransactionIndex = 0;
+}
+
+NS_IMPL_ISUPPORTS(nsNetscapeProfileMigratorBase, nsIMailProfileMigrator,
+ nsITimerCallback)
+
+nsresult nsNetscapeProfileMigratorBase::GetProfileDataFromProfilesIni(
+ nsIFile* aDataDir, nsTArray<nsString>& aProfileNames,
+ nsTArray<RefPtr<nsIFile>>& aProfileLocations) {
+ nsCOMPtr<nsIFile> profileIni;
+ nsresult rv = aDataDir->Clone(getter_AddRefs(profileIni));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ profileIni->Append(u"profiles.ini"_ns);
+
+ // Does it exist?
+ bool profileFileExists = false;
+ rv = profileIni->Exists(&profileFileExists);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (!profileFileExists) return NS_ERROR_FILE_NOT_FOUND;
+
+ nsINIParser parser;
+ rv = parser.Init(profileIni);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoCString buffer, filePath;
+ bool isRelative;
+
+ // This is an infinite loop that is broken when we no longer find profiles
+ // for profileID with IsRelative option.
+ for (unsigned int c = 0; true; ++c) {
+ nsAutoCString profileID("Profile");
+ profileID.AppendInt(c);
+
+ if (NS_FAILED(parser.GetString(profileID.get(), "IsRelative", buffer)))
+ break;
+
+ isRelative = buffer.EqualsLiteral("1");
+
+ rv = parser.GetString(profileID.get(), "Path", filePath);
+ if (NS_FAILED(rv)) {
+ NS_ERROR("Malformed profiles.ini: Path= not found");
+ continue;
+ }
+
+ rv = parser.GetString(profileID.get(), "Name", buffer);
+ if (NS_FAILED(rv)) {
+ NS_ERROR("Malformed profiles.ini: Name= not found");
+ continue;
+ }
+
+ nsCOMPtr<nsIFile> rootDir;
+ rv = NS_NewNativeLocalFile(EmptyCString(), true, getter_AddRefs(rootDir));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = isRelative ? rootDir->SetRelativeDescriptor(aDataDir, filePath)
+ : rootDir->SetPersistentDescriptor(filePath);
+ if (NS_FAILED(rv)) continue;
+
+ bool exists = false;
+ rootDir->Exists(&exists);
+
+ if (exists) {
+ aProfileLocations.AppendElement(rootDir);
+ aProfileNames.AppendElement(NS_ConvertUTF8toUTF16(buffer));
+ }
+ }
+ return NS_OK;
+}
+
+#define GETPREF(xform, method, value) \
+ nsresult rv = aBranch->method(xform->sourcePrefName, value); \
+ if (NS_SUCCEEDED(rv)) xform->prefHasValue = true; \
+ return rv;
+
+#define SETPREF(xform, method, value) \
+ if (xform->prefHasValue) { \
+ return aBranch->method( \
+ xform->targetPrefName ? xform->targetPrefName : xform->sourcePrefName, \
+ value); \
+ } \
+ return NS_OK;
+
+nsresult nsNetscapeProfileMigratorBase::GetString(PrefTransform* aTransform,
+ nsIPrefBranch* aBranch) {
+ PrefTransform* xform = (PrefTransform*)aTransform;
+ nsCString str;
+ nsresult rv = aBranch->GetCharPref(xform->sourcePrefName, str);
+ if (NS_SUCCEEDED(rv)) {
+ xform->prefHasValue = true;
+ xform->stringValue = moz_xstrdup(str.get());
+ }
+ return rv;
+}
+
+nsresult nsNetscapeProfileMigratorBase::SetString(PrefTransform* aTransform,
+ nsIPrefBranch* aBranch) {
+ PrefTransform* xform = (PrefTransform*)aTransform;
+ SETPREF(xform, SetCharPref, nsDependentCString(xform->stringValue));
+}
+
+nsresult nsNetscapeProfileMigratorBase::GetBool(PrefTransform* aTransform,
+ nsIPrefBranch* aBranch) {
+ PrefTransform* xform = (PrefTransform*)aTransform;
+ GETPREF(xform, GetBoolPref, &xform->boolValue);
+}
+
+nsresult nsNetscapeProfileMigratorBase::SetBool(PrefTransform* aTransform,
+ nsIPrefBranch* aBranch) {
+ PrefTransform* xform = (PrefTransform*)aTransform;
+ SETPREF(xform, SetBoolPref, xform->boolValue);
+}
+
+nsresult nsNetscapeProfileMigratorBase::GetInt(PrefTransform* aTransform,
+ nsIPrefBranch* aBranch) {
+ PrefTransform* xform = (PrefTransform*)aTransform;
+ GETPREF(xform, GetIntPref, &xform->intValue);
+}
+
+nsresult nsNetscapeProfileMigratorBase::SetInt(PrefTransform* aTransform,
+ nsIPrefBranch* aBranch) {
+ PrefTransform* xform = (PrefTransform*)aTransform;
+ SETPREF(xform, SetIntPref, xform->intValue);
+}
+
+nsresult nsNetscapeProfileMigratorBase::CopyFile(
+ const nsAString& aSourceFileName, const nsAString& aTargetFileName) {
+ nsCOMPtr<nsIFile> sourceFile;
+ mSourceProfile->Clone(getter_AddRefs(sourceFile));
+
+ sourceFile->Append(aSourceFileName);
+ bool exists = false;
+ sourceFile->Exists(&exists);
+ if (!exists) return NS_OK;
+
+ nsCOMPtr<nsIFile> targetFile;
+ mTargetProfile->Clone(getter_AddRefs(targetFile));
+
+ targetFile->Append(aTargetFileName);
+ targetFile->Exists(&exists);
+ if (exists) targetFile->Remove(false);
+
+ return sourceFile->CopyTo(mTargetProfile, aTargetFileName);
+}
+
+nsresult nsNetscapeProfileMigratorBase::GetSignonFileName(
+ bool aReplace, nsACString& aFileName) {
+ nsresult rv;
+ if (aReplace) {
+ // Find out what the signons file was called, this is stored in a pref
+ // in Seamonkey.
+ nsCOMPtr<nsIPrefService> psvc(do_GetService(NS_PREFSERVICE_CONTRACTID));
+ psvc->ResetPrefs();
+
+ nsCOMPtr<nsIFile> sourcePrefsName;
+ mSourceProfile->Clone(getter_AddRefs(sourcePrefsName));
+ sourcePrefsName->Append(FILE_NAME_PREFS_5X);
+ psvc->ReadUserPrefsFromFile(sourcePrefsName);
+
+ nsCOMPtr<nsIPrefBranch> branch(do_QueryInterface(psvc));
+ rv = branch->GetCharPref("signon.SignonFileName", aFileName);
+ } else
+ rv = LocateSignonsFile(aFileName);
+ return rv;
+}
+
+nsresult nsNetscapeProfileMigratorBase::LocateSignonsFile(nsACString& aResult) {
+ nsCOMPtr<nsIDirectoryEnumerator> entries;
+ nsresult rv = mSourceProfile->GetDirectoryEntries(getter_AddRefs(entries));
+ if (NS_FAILED(rv)) return rv;
+
+ nsAutoCString fileName;
+ bool hasMore = false;
+ while (NS_SUCCEEDED(entries->HasMoreElements(&hasMore)) && hasMore) {
+ nsCOMPtr<nsIFile> currFile;
+ rv = entries->GetNextFile(getter_AddRefs(currFile));
+ if (NS_FAILED(rv)) break;
+
+ nsCOMPtr<nsIURI> uri;
+ rv = NS_NewFileURI(getter_AddRefs(uri), currFile);
+ if (NS_FAILED(rv)) break;
+ nsCOMPtr<nsIURL> url(do_QueryInterface(uri));
+
+ nsAutoCString extn;
+ url->GetFileExtension(extn);
+
+ if (extn.EqualsIgnoreCase("s")) {
+ url->GetFileName(fileName);
+ break;
+ }
+ }
+
+ aResult = fileName;
+
+ return NS_OK;
+}
+
+// helper function, copies the contents of srcDir into destDir.
+// destDir will be created if it doesn't exist.
+
+nsresult nsNetscapeProfileMigratorBase::RecursiveCopy(nsIFile* srcDir,
+ nsIFile* destDir) {
+ nsresult rv;
+ bool isDir;
+
+ rv = srcDir->IsDirectory(&isDir);
+ if (NS_FAILED(rv)) return rv;
+ if (!isDir) return NS_ERROR_INVALID_ARG;
+
+ bool exists;
+ rv = destDir->Exists(&exists);
+ if (NS_SUCCEEDED(rv) && !exists)
+ rv = destDir->Create(nsIFile::DIRECTORY_TYPE, 0775);
+ if (NS_FAILED(rv)) return rv;
+
+ nsCOMPtr<nsIDirectoryEnumerator> dirIterator;
+ rv = srcDir->GetDirectoryEntries(getter_AddRefs(dirIterator));
+ if (NS_FAILED(rv)) return rv;
+
+ bool hasMore = false;
+ while (NS_SUCCEEDED(dirIterator->HasMoreElements(&hasMore)) && hasMore) {
+ nsCOMPtr<nsIFile> dirEntry;
+ rv = dirIterator->GetNextFile(getter_AddRefs(dirEntry));
+ if (NS_SUCCEEDED(rv) && dirEntry) {
+ rv = dirEntry->IsDirectory(&isDir);
+ if (NS_SUCCEEDED(rv)) {
+ if (isDir) {
+ nsCOMPtr<nsIFile> newChild;
+ rv = destDir->Clone(getter_AddRefs(newChild));
+ if (NS_SUCCEEDED(rv)) {
+ nsAutoString leafName;
+ dirEntry->GetLeafName(leafName);
+ newChild->AppendRelativePath(leafName);
+ rv = newChild->Exists(&exists);
+ if (NS_SUCCEEDED(rv) && !exists) {
+ rv = newChild->Create(nsIFile::DIRECTORY_TYPE, 0775);
+ if (NS_FAILED(rv)) return rv;
+ }
+ rv = RecursiveCopy(dirEntry, newChild);
+ }
+ } else {
+ // we aren't going to do any actual file copying here. Instead, add
+ // this to our file transaction list so we can copy files
+ // asynchronously...
+ fileTransactionEntry fileEntry;
+ fileEntry.srcFile = dirEntry;
+ fileEntry.destFile = destDir;
+
+ mFileCopyTransactions.AppendElement(fileEntry);
+ }
+ }
+ }
+ }
+
+ return rv;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// nsITimerCallback
+
+NS_IMETHODIMP
+nsNetscapeProfileMigratorBase::Notify(nsITimer* timer) {
+ CopyNextFolder();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsNetscapeProfileMigratorBase::GetName(nsACString& aName) {
+ aName.AssignLiteral("nsNetscapeProfileMigratorBase");
+ return NS_OK;
+}
+
+void nsNetscapeProfileMigratorBase::CopyNextFolder() {
+ if (mFileCopyTransactionIndex < mFileCopyTransactions.Length()) {
+ fileTransactionEntry fileTransaction =
+ mFileCopyTransactions.ElementAt(mFileCopyTransactionIndex++);
+
+ // copy the file
+ fileTransaction.srcFile->CopyTo(fileTransaction.destFile,
+ fileTransaction.newName);
+
+ // add to our current progress
+ int64_t fileSize;
+ fileTransaction.srcFile->GetFileSize(&fileSize);
+ mCurrentProgress += fileSize;
+
+ uint32_t percentage = (uint32_t)(mCurrentProgress * 100 / mMaxProgress);
+
+ nsAutoString index;
+ index.AppendInt(percentage);
+
+ NOTIFY_OBSERVERS(MIGRATION_PROGRESS, index.get());
+
+ // fire a timer to handle the next one.
+ nsresult rv = NS_NewTimerWithCallback(
+ getter_AddRefs(mFileIOTimer), static_cast<nsITimerCallback*>(this),
+ percentage == 100 ? 500 : 0, nsITimer::TYPE_ONE_SHOT, nullptr);
+ if (NS_FAILED(rv)) {
+ NS_WARNING("Could not start mFileIOTimer timer");
+ }
+ } else
+ EndCopyFolders();
+
+ return;
+}
+
+void nsNetscapeProfileMigratorBase::EndCopyFolders() {
+ mFileCopyTransactions.Clear();
+ mFileCopyTransactionIndex = 0;
+
+ // notify the UI that we are done with the migration process
+ nsAutoString index;
+ index.AppendInt(nsIMailProfileMigrator::MAILDATA);
+ NOTIFY_OBSERVERS(MIGRATION_ITEMAFTERMIGRATE, index.get());
+
+ NOTIFY_OBSERVERS(MIGRATION_ENDED, nullptr);
+}
+
+NS_IMETHODIMP
+nsNetscapeProfileMigratorBase::GetSourceHasMultipleProfiles(bool* aResult) {
+ nsTArray<nsString> profiles;
+ GetSourceProfiles(profiles);
+
+ *aResult = profiles.Length() > 1;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsNetscapeProfileMigratorBase::GetSourceExists(bool* aResult) {
+ nsTArray<nsString> profiles;
+ GetSourceProfiles(profiles);
+
+ *aResult = profiles.Length() > 0;
+ return NS_OK;
+}