nsProfileMigrator.cpp
Go to the documentation of this file.
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
4  *
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/
9  *
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
13  * License.
14  *
15  * The Original Code is The Browser Profile Migrator.
16  *
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.
20  *
21  * Contributor(s):
22  * Ben Goodger <ben@bengoodger.com>
23  *
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.
35  *
36  * ***** END LICENSE BLOCK ***** */
37 
38 #include "nsProfileMigrator.h"
39 
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"
52 
53 #include "nsCOMPtr.h"
54 #include "nsBrowserCompsCID.h"
55 #include "nsComponentManagerUtils.h"
56 #include "nsDirectoryServiceDefs.h"
57 #include "nsServiceManagerUtils.h"
58 
59 #include "NSReg.h"
60 #include "nsStringAPI.h"
61 #include "nsUnicharUtils.h"
62 #ifdef XP_WIN
63 #include <windows.h>
64 #include "nsIWindowsRegKey.h"
65 #include "nsILocalFileWin.h"
66 #else
67 #include <limits.h>
68 #endif
69 
70 #include "nsAutoPtr.h"
71 
72 #ifndef MAXPATHLEN
73 #ifdef PATH_MAX
74 #define MAXPATHLEN PATH_MAX
75 #elif defined(_MAX_PATH)
76 #define MAXPATHLEN _MAX_PATH
77 #elif defined(CCHMAXPATH)
78 #define MAXPATHLEN CCHMAXPATH
79 #else
80 #define MAXPATHLEN 1024
81 #endif
82 #endif
83 
85 // nsIProfileMigrator
86 
87 #define MIGRATION_WIZARD_FE_URL "chrome://browser/content/migration/migration.xul"
88 #define MIGRATION_WIZARD_FE_FEATURES "chrome,dialog,modal,centerscreen,titlebar"
89 
90 NS_IMETHODIMP
91 nsProfileMigrator::Migrate(nsIProfileStartup* aStartup)
92 {
93  nsresult rv;
94 
95  nsCAutoString key;
96  nsCOMPtr<nsIBrowserProfileMigrator> bpm;
97 
98  rv = GetDefaultBrowserMigratorKey(key, bpm);
99  if (NS_FAILED(rv)) return rv;
100 
101  if (!bpm) {
103  contractID.Append(key);
104 
105  bpm = do_CreateInstance(contractID.get());
106  if (!bpm) return NS_ERROR_FAILURE;
107  }
108 
109  PRBool sourceExists;
110  bpm->GetSourceExists(&sourceExists);
111  if (!sourceExists) {
112 #ifdef XP_WIN
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");
117 #else
118  return NS_ERROR_FAILURE;
119 #endif
120  }
121 
122  nsCOMPtr<nsISupportsCString> cstr
123  (do_CreateInstance("@mozilla.org/supports-cstring;1"));
124  if (!cstr) return NS_ERROR_OUT_OF_MEMORY;
125  cstr->SetData(key);
126 
127  // By opening the Migration FE with a supplied bpm, it will automatically
128  // migrate from it.
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;
133 
134  params->AppendElement(cstr);
135  params->AppendElement(bpm);
136  params->AppendElement(aStartup);
137 
138  nsCOMPtr<nsIDOMWindow> migrateWizard;
139  return ww->OpenWindow(nsnull,
141  "_blank",
143  params,
144  getter_AddRefs(migrateWizard));
145 }
146 
147 NS_IMETHODIMP
148 nsProfileMigrator::Import()
149 {
150  if (ImportRegistryProfiles(NS_LITERAL_CSTRING("Firefox")))
151  return NS_OK;
152 
153  return NS_ERROR_FAILURE;
154 }
155 
157 // nsProfileMigrator
158 
159 NS_IMPL_ISUPPORTS1(nsProfileMigrator, nsIProfileMigrator)
160 
161 #ifdef XP_WIN
162 
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"
171 #endif
172 
173 nsresult
175  nsCOMPtr<nsIBrowserProfileMigrator>& bpm)
176 {
177 #if XP_WIN
178 
179  nsCOMPtr<nsIWindowsRegKey> regKey =
180  do_CreateInstance("@mozilla.org/windows-registry-key;1");
181  if (!regKey)
182  return NS_ERROR_FAILURE;
183 
184  NS_NAMED_LITERAL_STRING(kCommandKey,
185  "SOFTWARE\\Classes\\HTTP\\shell\\open\\command");
186 
187  if (NS_FAILED(regKey->Open(nsIWindowsRegKey::ROOT_KEY_LOCAL_MACHINE,
188  kCommandKey, nsIWindowsRegKey::ACCESS_READ)))
189  return NS_ERROR_FAILURE;
190 
191  nsAutoString value;
192  if (NS_FAILED(regKey->ReadStringValue(EmptyString(), value)))
193  return NS_ERROR_FAILURE;
194 
195  PRInt32 len = value.Find(NS_LITERAL_STRING(".exe"), CaseInsensitiveCompare);
196  if (len == -1)
197  return NS_ERROR_FAILURE;
198 
199  // Move past ".exe"
200  len += 4;
201 
202  PRUint32 start = 0;
203  // skip an opening quotation mark if present
204  if (value.get()[1] != ':') {
205  start = 1;
206  --len;
207  }
208 
209  const nsDependentSubstring filePath(Substring(value, start, len));
210 
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.
218  //
219  // In the file's resource segment there is a VERSIONINFO section that is laid
220  // out like this:
221  //
222  // VERSIONINFO
223  // StringFileInfo
224  // <TranslationID>
225  // InternalName "iexplore"
226  // VarFileInfo
227  // Translation <TranslationID>
228  //
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).
232 
233  nsCOMPtr<nsILocalFile> lf;
234  NS_NewLocalFile(filePath, PR_TRUE, getter_AddRefs(lf));
235  if (!lf)
236  return NS_ERROR_FAILURE;
237 
238  nsCOMPtr<nsILocalFileWin> lfw = do_QueryInterface(lf);
239  if (!lfw)
240  return NS_ERROR_FAILURE;
241 
242  nsAutoString internalName;
243  if (NS_FAILED(lfw->GetVersionInfoField("InternalName", internalName)))
244  return NS_ERROR_FAILURE;
245 
246  if (internalName.LowerCaseEqualsLiteral(INTERNAL_NAME_IEXPLORE)) {
247  aKey = "ie";
248  return NS_OK;
249  }
250  if (internalName.LowerCaseEqualsLiteral(INTERNAL_NAME_MOZILLA_SUITE) ||
251  internalName.LowerCaseEqualsLiteral(INTERNAL_NAME_SEAMONKEY)) {
252  aKey = "seamonkey";
253  return NS_OK;
254  }
255  if (internalName.LowerCaseEqualsLiteral(INTERNAL_NAME_DOGBERT)) {
256  aKey = "dogbert";
257  return NS_OK;
258  }
259  if (internalName.LowerCaseEqualsLiteral(INTERNAL_NAME_OPERA)) {
260  aKey = "opera";
261  return NS_OK;
262  }
263 
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)) {
268  aKey = "phoenix";
269  return NS_OK;
270  }
271 #else
272  PRBool exists = PR_FALSE;
273 #define CHECK_MIGRATOR(browser) do {\
274  bpm = do_CreateInstance(NS_BROWSERPROFILEMIGRATOR_CONTRACTID_PREFIX browser);\
275  if (bpm)\
276  bpm->GetSourceExists(&exists);\
277  if (exists) {\
278  aKey = browser;\
279  return NS_OK;\
280  }} while(0)
281 
282 #if defined(XP_MACOSX)
283  CHECK_MIGRATOR("safari");
284  CHECK_MIGRATOR("macie");
285 #endif
286  CHECK_MIGRATOR("phoenix");
287  CHECK_MIGRATOR("seamonkey");
288  CHECK_MIGRATOR("opera");
289 
290 #undef CHECK_MIGRATOR
291 #endif
292  return NS_ERROR_FAILURE;
293 }
294 
295 PRBool
296 nsProfileMigrator::ImportRegistryProfiles(const nsACString& aAppName)
297 {
298  nsresult rv;
299 
300  nsCOMPtr<nsIToolkitProfileService> profileSvc
301  (do_GetService(NS_PROFILESERVICE_CONTRACTID));
302  NS_ENSURE_TRUE(profileSvc, NS_ERROR_FAILURE);
303 
304  nsCOMPtr<nsIProperties> dirService
305  (do_GetService("@mozilla.org/file/directory_service;1"));
306  NS_ENSURE_TRUE(dirService, NS_ERROR_FAILURE);
307 
308  nsCOMPtr<nsILocalFile> regFile;
309 #ifdef XP_WIN
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"));
333 #else
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);
340 
341  regFile->AppendNative(dotAppName);
342  regFile->AppendNative(NS_LITERAL_CSTRING("appreg"));
343 #endif
344 
345  nsCAutoString path;
346  rv = regFile->GetNativePath(path);
347  NS_ENSURE_SUCCESS(rv, PR_FALSE);
348 
349  if (NR_StartupRegistry())
350  return PR_FALSE;
351 
352  PRBool migrated = PR_FALSE;
353  HREG reg = nsnull;
354  RKEY profiles = 0;
355  REGENUM enumstate = 0;
356  char profileName[MAXREGNAMELEN];
357 
358  if (NR_RegOpen(path.get(), &reg))
359  goto cleanup;
360 
361  if (NR_RegGetKey(reg, ROOTKEY_COMMON, "Profiles", &profiles))
362  goto cleanup;
363 
364  while (!NR_RegEnumSubkeys(reg, profiles, &enumstate,
365  profileName, MAXREGNAMELEN, REGENUM_CHILDREN)) {
366 #ifdef DEBUG_bsmedberg
367  printf("Found profile %s.\n", profileName);
368 #endif
369 
370  RKEY profile = 0;
371  if (NR_RegGetKey(reg, profiles, profileName, &profile)) {
372  NS_ERROR("Could not get the key that was enumerated.");
373  continue;
374  }
375 
376  char profilePath[MAXPATHLEN];
377  if (NR_RegGetEntryString(reg, profile, "directory",
378  profilePath, MAXPATHLEN))
379  continue;
380 
381  nsCOMPtr<nsILocalFile> profileFile
382  (do_CreateInstance("@mozilla.org/file/local;1"));
383  if (!profileFile)
384  continue;
385 
386 #if defined (XP_MACOSX)
387  rv = profileFile->SetPersistentDescriptor(nsDependentCString(profilePath));
388 #else
389  NS_ConvertUTF8toUTF16 widePath(profilePath);
390  rv = profileFile->InitWithPath(widePath);
391 #endif
392  if (NS_FAILED(rv)) continue;
393 
394  nsCOMPtr<nsIToolkitProfile> tprofile;
395  profileSvc->CreateProfile(profileFile, nsnull,
396  nsDependentCString(profileName),
397  getter_AddRefs(tprofile));
398  migrated = PR_TRUE;
399  }
400 
401 cleanup:
402  if (reg)
403  NR_RegClose(reg);
404  NR_ShutdownRegistry();
405  return migrated;
406 }
function start(ch)
#define MIGRATION_WIZARD_FE_FEATURES
return NS_OK
#define CHECK_MIGRATOR(browser)
NS_IMPL_ISUPPORTS1(sbDeviceCapabilitiesUtils, sbIDeviceCapabilitiesUtils) sbDeviceCapabilitiesUtils
nsresult GetDefaultBrowserMigratorKey(nsACString &key, nsCOMPtr< nsIBrowserProfileMigrator > &bpm)
#define MAXPATHLEN
sbDeviceFirmwareAutoCheckForUpdate prototype contractID
PRBool ImportRegistryProfiles(const nsACString &aAppName)
#define NS_BROWSERPROFILEMIGRATOR_CONTRACTID_PREFIX
#define MIGRATION_WIZARD_FE_URL
function cleanup()
countRef value
Definition: FeedWriter.js:1423
const ACCESS_READ
Definition: pageInfo.js:194