1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is The Browser Profile Migrator.
17 * The Initial Developer of the Original Code is Ben Goodger.
18 * Portions created by the Initial Developer are Copyright (C) 2004
19 * the Initial Developer. All Rights Reserved.
22 * Ben Goodger <ben@bengoodger.com>
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 #include "nsProfileMigrator.h"
40 #include "nsIBrowserProfileMigrator.h"
41 #include "nsIComponentManager.h"
42 #include "nsIDOMWindowInternal.h"
43 #include "nsILocalFile.h"
44 #include "nsIObserverService.h"
45 #include "nsIProperties.h"
46 #include "nsIServiceManager.h"
47 #include "nsISupportsPrimitives.h"
48 #include "nsISupportsArray.h"
49 #include "nsIToolkitProfile.h"
50 #include "nsIToolkitProfileService.h"
51 #include "nsIWindowWatcher.h"
54 #include "nsBrowserCompsCID.h"
55 #include "nsComponentManagerUtils.h"
56 #include "nsDirectoryServiceDefs.h"
57 #include "nsServiceManagerUtils.h"
60 #include "nsStringAPI.h"
61 #include "nsUnicharUtils.h"
64 #include "nsIWindowsRegKey.h"
65 #include "nsILocalFileWin.h"
70 #include "nsAutoPtr.h"
74 #define MAXPATHLEN PATH_MAX
75 #elif defined(_MAX_PATH)
76 #define MAXPATHLEN _MAX_PATH
77 #elif defined(CCHMAXPATH)
78 #define MAXPATHLEN CCHMAXPATH
80 #define MAXPATHLEN 1024
84 ///////////////////////////////////////////////////////////////////////////////
87 #define MIGRATION_WIZARD_FE_URL "chrome://browser/content/migration/migration.xul"
88 #define MIGRATION_WIZARD_FE_FEATURES "chrome,dialog,modal,centerscreen,titlebar"
91 nsProfileMigrator::Migrate(nsIProfileStartup
* aStartup
)
96 nsCOMPtr
<nsIBrowserProfileMigrator
> bpm
;
98 rv
= GetDefaultBrowserMigratorKey(key
, bpm
);
99 if (NS_FAILED(rv
)) return rv
;
102 nsCAutoString
contractID(NS_BROWSERPROFILEMIGRATOR_CONTRACTID_PREFIX
);
103 contractID
.Append(key
);
105 bpm
= do_CreateInstance(contractID
.get());
106 if (!bpm
) return NS_ERROR_FAILURE
;
110 bpm
->GetSourceExists(&sourceExists
);
113 // The "Default Browser" key in the registry was set to a browser for which
114 // no profile data exists. On Windows, this means the Default Browser settings
115 // in the registry are bad, and we should just fall back to IE in this case.
116 bpm
= do_CreateInstance(NS_BROWSERPROFILEMIGRATOR_CONTRACTID_PREFIX
"ie");
118 return NS_ERROR_FAILURE
;
122 nsCOMPtr
<nsISupportsCString
> cstr
123 (do_CreateInstance("@mozilla.org/supports-cstring;1"));
124 if (!cstr
) return NS_ERROR_OUT_OF_MEMORY
;
127 // By opening the Migration FE with a supplied bpm, it will automatically
129 nsCOMPtr
<nsIWindowWatcher
> ww(do_GetService(NS_WINDOWWATCHER_CONTRACTID
));
130 nsCOMPtr
<nsISupportsArray
> params
=
131 do_CreateInstance(NS_SUPPORTSARRAY_CONTRACTID
);
132 if (!ww
|| !params
) return NS_ERROR_FAILURE
;
134 params
->AppendElement(cstr
);
135 params
->AppendElement(bpm
);
136 params
->AppendElement(aStartup
);
138 nsCOMPtr
<nsIDOMWindow
> migrateWizard
;
139 return ww
->OpenWindow(nsnull
,
140 MIGRATION_WIZARD_FE_URL
,
142 MIGRATION_WIZARD_FE_FEATURES
,
144 getter_AddRefs(migrateWizard
));
148 nsProfileMigrator::Import()
150 if (ImportRegistryProfiles(NS_LITERAL_CSTRING("Firefox")))
153 return NS_ERROR_FAILURE
;
156 ///////////////////////////////////////////////////////////////////////////////
159 NS_IMPL_ISUPPORTS1(nsProfileMigrator
, nsIProfileMigrator
)
163 #define INTERNAL_NAME_FIREBIRD "firebird"
164 #define INTERNAL_NAME_FIREFOX "firefox"
165 #define INTERNAL_NAME_PHOENIX "phoenix"
166 #define INTERNAL_NAME_IEXPLORE "iexplore"
167 #define INTERNAL_NAME_MOZILLA_SUITE "apprunner"
168 #define INTERNAL_NAME_SEAMONKEY "seamonkey"
169 #define INTERNAL_NAME_DOGBERT "netscape"
170 #define INTERNAL_NAME_OPERA "opera"
174 nsProfileMigrator::GetDefaultBrowserMigratorKey(nsACString
& aKey
,
175 nsCOMPtr
<nsIBrowserProfileMigrator
>& bpm
)
179 nsCOMPtr
<nsIWindowsRegKey
> regKey
=
180 do_CreateInstance("@mozilla.org/windows-registry-key;1");
182 return NS_ERROR_FAILURE
;
184 NS_NAMED_LITERAL_STRING(kCommandKey
,
185 "SOFTWARE\\Classes\\HTTP\\shell\\open\\command");
187 if (NS_FAILED(regKey
->Open(nsIWindowsRegKey::ROOT_KEY_LOCAL_MACHINE
,
188 kCommandKey
, nsIWindowsRegKey::ACCESS_READ
)))
189 return NS_ERROR_FAILURE
;
192 if (NS_FAILED(regKey
->ReadStringValue(EmptyString(), value
)))
193 return NS_ERROR_FAILURE
;
195 PRInt32 len
= value
.Find(NS_LITERAL_STRING(".exe"), CaseInsensitiveCompare
);
197 return NS_ERROR_FAILURE
;
203 // skip an opening quotation mark if present
204 if (value
.get()[1] != ':') {
209 const nsDependentSubstring
filePath(Substring(value
, start
, len
));
211 // We want to find out what the default browser is but the path in and of itself
212 // isn't enough. Why? Because sometimes on Windows paths get truncated like so:
213 // C:\PROGRA~1\MOZILL~2\MOZILL~1.EXE
214 // How do we know what product that is? Mozilla or Mozilla Firebird? etc. Mozilla's
215 // file objects do nothing to 'normalize' the path so we need to attain an actual
216 // product descriptor from the file somehow, and in this case it means getting
217 // the "InternalName" field of the file's VERSIONINFO resource.
219 // In the file's resource segment there is a VERSIONINFO section that is laid
225 // InternalName "iexplore"
227 // Translation <TranslationID>
229 // By Querying the VERSIONINFO section for its Tranlations, we can find out where
230 // the InternalName lives. (A file can have more than one translation of its
231 // VERSIONINFO segment, but we just assume the first one).
233 nsCOMPtr
<nsILocalFile
> lf
;
234 NS_NewLocalFile(filePath
, PR_TRUE
, getter_AddRefs(lf
));
236 return NS_ERROR_FAILURE
;
238 nsCOMPtr
<nsILocalFileWin
> lfw
= do_QueryInterface(lf
);
240 return NS_ERROR_FAILURE
;
242 nsAutoString internalName
;
243 if (NS_FAILED(lfw
->GetVersionInfoField("InternalName", internalName
)))
244 return NS_ERROR_FAILURE
;
246 if (internalName
.LowerCaseEqualsLiteral(INTERNAL_NAME_IEXPLORE
)) {
250 if (internalName
.LowerCaseEqualsLiteral(INTERNAL_NAME_MOZILLA_SUITE
) ||
251 internalName
.LowerCaseEqualsLiteral(INTERNAL_NAME_SEAMONKEY
)) {
255 if (internalName
.LowerCaseEqualsLiteral(INTERNAL_NAME_DOGBERT
)) {
259 if (internalName
.LowerCaseEqualsLiteral(INTERNAL_NAME_OPERA
)) {
264 // Migrate data from any existing Application Data\Phoenix\* installations.
265 if (internalName
.LowerCaseEqualsLiteral(INTERNAL_NAME_FIREBIRD
) ||
266 internalName
.LowerCaseEqualsLiteral(INTERNAL_NAME_FIREFOX
) ||
267 internalName
.LowerCaseEqualsLiteral(INTERNAL_NAME_PHOENIX
)) {
272 PRBool exists
= PR_FALSE
;
273 #define CHECK_MIGRATOR(browser) do {\
274 bpm = do_CreateInstance(NS_BROWSERPROFILEMIGRATOR_CONTRACTID_PREFIX browser);\
276 bpm->GetSourceExists(&exists);\
282 #if defined(XP_MACOSX)
283 CHECK_MIGRATOR("safari");
284 CHECK_MIGRATOR("macie");
286 CHECK_MIGRATOR("phoenix");
287 CHECK_MIGRATOR("seamonkey");
288 CHECK_MIGRATOR("opera");
290 #undef CHECK_MIGRATOR
292 return NS_ERROR_FAILURE
;
296 nsProfileMigrator::ImportRegistryProfiles(const nsACString
& aAppName
)
300 nsCOMPtr
<nsIToolkitProfileService
> profileSvc
301 (do_GetService(NS_PROFILESERVICE_CONTRACTID
));
302 NS_ENSURE_TRUE(profileSvc
, NS_ERROR_FAILURE
);
304 nsCOMPtr
<nsIProperties
> dirService
305 (do_GetService("@mozilla.org/file/directory_service;1"));
306 NS_ENSURE_TRUE(dirService
, NS_ERROR_FAILURE
);
308 nsCOMPtr
<nsILocalFile
> regFile
;
310 rv
= dirService
->Get(NS_WIN_APPDATA_DIR
, NS_GET_IID(nsILocalFile
),
311 getter_AddRefs(regFile
));
312 NS_ENSURE_SUCCESS(rv
, PR_FALSE
);
313 regFile
->AppendNative(aAppName
);
314 regFile
->AppendNative(NS_LITERAL_CSTRING("registry.dat"));
315 #elif defined(XP_MACOSX)
316 rv
= dirService
->Get(NS_MAC_USER_LIB_DIR
, NS_GET_IID(nsILocalFile
),
317 getter_AddRefs(regFile
));
318 NS_ENSURE_SUCCESS(rv
, PR_FALSE
);
319 regFile
->AppendNative(aAppName
);
320 regFile
->AppendNative(NS_LITERAL_CSTRING("Application Registry"));
321 #elif defined(XP_OS2)
322 rv
= dirService
->Get(NS_OS2_HOME_DIR
, NS_GET_IID(nsILocalFile
),
323 getter_AddRefs(regFile
));
324 NS_ENSURE_SUCCESS(rv
, PR_FALSE
);
325 regFile
->AppendNative(aAppName
);
326 regFile
->AppendNative(NS_LITERAL_CSTRING("registry.dat"));
327 #elif defined(XP_BEOS)
328 rv
= dirService
->Get(NS_BEOS_SETTINGS_DIR
, NS_GET_IID(nsILocalFile
),
329 getter_AddRefs(regFile
));
330 NS_ENSURE_SUCCESS(rv
, PR_FALSE
);
331 regFile
->AppendNative(aAppName
);
332 regFile
->AppendNative(NS_LITERAL_CSTRING("appreg"));
334 rv
= dirService
->Get(NS_UNIX_HOME_DIR
, NS_GET_IID(nsILocalFile
),
335 getter_AddRefs(regFile
));
336 NS_ENSURE_SUCCESS(rv
, PR_FALSE
);
337 nsCAutoString dotAppName
;
338 ToLowerCase(aAppName
, dotAppName
);
339 dotAppName
.Insert('.', 0);
341 regFile
->AppendNative(dotAppName
);
342 regFile
->AppendNative(NS_LITERAL_CSTRING("appreg"));
346 rv
= regFile
->GetNativePath(path
);
347 NS_ENSURE_SUCCESS(rv
, PR_FALSE
);
349 if (NR_StartupRegistry())
352 PRBool migrated
= PR_FALSE
;
355 REGENUM enumstate
= 0;
356 char profileName
[MAXREGNAMELEN
];
358 if (NR_RegOpen(path
.get(), ®
))
361 if (NR_RegGetKey(reg
, ROOTKEY_COMMON
, "Profiles", &profiles
))
364 while (!NR_RegEnumSubkeys(reg
, profiles
, &enumstate
,
365 profileName
, MAXREGNAMELEN
, REGENUM_CHILDREN
)) {
366 #ifdef DEBUG_bsmedberg
367 printf("Found profile %s.\n", profileName
);
371 if (NR_RegGetKey(reg
, profiles
, profileName
, &profile
)) {
372 NS_ERROR("Could not get the key that was enumerated.");
376 char profilePath
[MAXPATHLEN
];
377 if (NR_RegGetEntryString(reg
, profile
, "directory",
378 profilePath
, MAXPATHLEN
))
381 nsCOMPtr
<nsILocalFile
> profileFile
382 (do_CreateInstance("@mozilla.org/file/local;1"));
386 #if defined (XP_MACOSX)
387 rv
= profileFile
->SetPersistentDescriptor(nsDependentCString(profilePath
));
389 NS_ConvertUTF8toUTF16
widePath(profilePath
);
390 rv
= profileFile
->InitWithPath(widePath
);
392 if (NS_FAILED(rv
)) continue;
394 nsCOMPtr
<nsIToolkitProfile
> tprofile
;
395 profileSvc
->CreateProfile(profileFile
, nsnull
,
396 nsDependentCString(profileName
),
397 getter_AddRefs(tprofile
));
404 NR_ShutdownRegistry();