toolkit/mozapps/update/nsUpdateServiceStub.js

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/toolkit/mozapps/update/nsUpdateServiceStub.js	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,183 @@
     1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     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 +const Ci = Components.interfaces;
    1.10 +const Cc = Components.classes;
    1.11 +const Cu = Components.utils;
    1.12 +
    1.13 +Cu.import("resource://gre/modules/XPCOMUtils.jsm");
    1.14 +Cu.import("resource://gre/modules/FileUtils.jsm");
    1.15 +Cu.import("resource://gre/modules/Services.jsm");
    1.16 +
    1.17 +const DIR_UPDATES         = "updates";
    1.18 +const FILE_UPDATES_DB     = "updates.xml";
    1.19 +const FILE_UPDATE_ACTIVE  = "active-update.xml";
    1.20 +const FILE_LAST_LOG       = "last-update.log";
    1.21 +const FILE_BACKUP_LOG     = "backup-update.log";
    1.22 +const FILE_UPDATE_STATUS  = "update.status";
    1.23 +
    1.24 +const KEY_UPDROOT         = "UpdRootD";
    1.25 +
    1.26 +#ifdef XP_WIN
    1.27 +
    1.28 +const PREF_APP_UPDATE_MIGRATE_APP_DIR = "app.update.migrated.updateDir";
    1.29 +
    1.30 +
    1.31 +function getTaskbarIDHash(rootKey, exePath, appInfoName) {
    1.32 +  let registry = Cc["@mozilla.org/windows-registry-key;1"].
    1.33 +                 createInstance(Ci.nsIWindowsRegKey);
    1.34 +  try {
    1.35 +    registry.open(rootKey, "Software\\Mozilla\\" + appInfoName + "\\TaskBarIDs",
    1.36 +                  Ci.nsIWindowsRegKey.ACCESS_READ);
    1.37 +    if (registry.hasValue(exePath)) {
    1.38 +      return registry.readStringValue(exePath);
    1.39 +    }
    1.40 +  } catch (ex) {
    1.41 +  } finally {
    1.42 +    registry.close();
    1.43 +  }
    1.44 +  return undefined;
    1.45 +};
    1.46 +
    1.47 +/*
    1.48 + * Migrates old update directory files to the new update directory
    1.49 + * which is based on a hash of the installation.
    1.50 + */
    1.51 +function migrateOldUpdateDir() {
    1.52 +  // Get the old udpate root leaf dir. It is based on the sub directory of
    1.53 +  // program files, or if the exe path is not inside program files, the appname.
    1.54 +  var appinfo = Components.classes["@mozilla.org/xre/app-info;1"].
    1.55 +                getService(Components.interfaces.nsIXULAppInfo).
    1.56 +                QueryInterface(Components.interfaces.nsIXULRuntime);
    1.57 +  var updateLeafName;
    1.58 +  var programFiles = FileUtils.getFile("ProgF", []);
    1.59 +  var exeFile = FileUtils.getFile("XREExeF", []);
    1.60 +  if (exeFile.path.substring(0, programFiles.path.length).toLowerCase() ==
    1.61 +      programFiles.path.toLowerCase()) {
    1.62 +    updateLeafName = exeFile.parent.leafName;
    1.63 +  } else {
    1.64 +    updateLeafName = appinfo.name;
    1.65 +  }
    1.66 +
    1.67 +  // Get the old update root dir
    1.68 +  var oldUpdateRoot;
    1.69 +  if (appinfo.vendor) {
    1.70 +    oldUpdateRoot = FileUtils.getDir("LocalAppData", [appinfo.vendor,
    1.71 +                                                      appinfo.name,
    1.72 +                                                      updateLeafName], false);
    1.73 +  } else {
    1.74 +    oldUpdateRoot = FileUtils.getDir("LocalAppData", [appinfo.name,
    1.75 +                                                      updateLeafName], false);
    1.76 +  }
    1.77 +
    1.78 +  // Obtain the new update root
    1.79 +  var newUpdateRoot = FileUtils.getDir("UpdRootD", [], true);
    1.80 +
    1.81 +  // If there is no taskbar ID then we want to retry this migration
    1.82 +  // at a later time if the application gets a taskbar ID.
    1.83 +  var taskbarID = getTaskbarIDHash(Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE,
    1.84 +                                   exeFile.parent.path, appinfo.name);
    1.85 +  if (!taskbarID) {
    1.86 +    taskbarID = getTaskbarIDHash(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
    1.87 +                                 exeFile.parent.path, appinfo.name);
    1.88 +    if (!taskbarID) {
    1.89 +      return;
    1.90 +    }
    1.91 +  }
    1.92 +
    1.93 +  Services.prefs.setBoolPref(PREF_APP_UPDATE_MIGRATE_APP_DIR, true);
    1.94 +
    1.95 +  // Sanity checks only to ensure we don't delete something we don't mean to.
    1.96 +  if (oldUpdateRoot.path.toLowerCase() == newUpdateRoot.path.toLowerCase() ||
    1.97 +      updateLeafName.length == 0) {
    1.98 +    return;
    1.99 +  }
   1.100 +
   1.101 +  // If the old update root doesn't exist then we have already migrated
   1.102 +  // or else there is no work to do.
   1.103 +  if (!oldUpdateRoot.exists()) {
   1.104 +    return;
   1.105 +  }
   1.106 +
   1.107 +  // Get an array of all of the files we want to migrate.
   1.108 +  // We do this so we don't copy anything extra.
   1.109 +  var filesToMigrate = [FILE_UPDATES_DB, FILE_UPDATE_ACTIVE,
   1.110 +                        ["updates", FILE_LAST_LOG], ["updates", FILE_BACKUP_LOG],
   1.111 +                        ["updates", "0", FILE_UPDATE_STATUS]];
   1.112 +
   1.113 +  // Move each of those files to the new directory
   1.114 +  filesToMigrate.forEach(relPath => {
   1.115 +    let oldFile = oldUpdateRoot.clone();
   1.116 +    let newFile = newUpdateRoot.clone();
   1.117 +    if (relPath instanceof Array) {
   1.118 +      relPath.forEach(relPathPart => {
   1.119 +        oldFile.append(relPathPart);
   1.120 +        newFile.append(relPathPart);
   1.121 +      });
   1.122 +    } else {
   1.123 +      oldFile.append(relPath);
   1.124 +      newFile.append(relPath);
   1.125 +    }
   1.126 +
   1.127 +    try {
   1.128 +      if (!newFile.exists()) {
   1.129 +        oldFile.moveTo(newFile.parent, newFile.leafName);
   1.130 +      }
   1.131 +    } catch (e) {
   1.132 +      Components.utils.reportError(e);
   1.133 +    }
   1.134 +  });
   1.135 +
   1.136 +  oldUpdateRoot.remove(true);
   1.137 +}
   1.138 +#endif
   1.139 +
   1.140 +/**
   1.141 + * Gets the specified directory at the specified hierarchy under the update root
   1.142 + * directory without creating it if it doesn't exist.
   1.143 + * @param   pathArray
   1.144 + *          An array of path components to locate beneath the directory
   1.145 + *          specified by |key|
   1.146 + * @return  nsIFile object for the location specified.
   1.147 + */
   1.148 +function getUpdateDirNoCreate(pathArray) {
   1.149 +  return FileUtils.getDir(KEY_UPDROOT, pathArray, false);
   1.150 +}
   1.151 +
   1.152 +function UpdateServiceStub() {
   1.153 +#ifdef XP_WIN
   1.154 +  // Don't attempt this migration more than once for perf reasons
   1.155 +  var migrated = 0;
   1.156 +  try {
   1.157 +    migrated = Services.prefs.getBoolPref(PREF_APP_UPDATE_MIGRATE_APP_DIR);
   1.158 +  } catch (e) {
   1.159 +  }
   1.160 +
   1.161 +  if (!migrated) {
   1.162 +    try {
   1.163 +      migrateOldUpdateDir();
   1.164 +    } catch (e) {
   1.165 +      Components.utils.reportError(e);
   1.166 +    }
   1.167 +  }
   1.168 +#endif
   1.169 +
   1.170 +  let statusFile = getUpdateDirNoCreate([DIR_UPDATES, "0"]);
   1.171 +  statusFile.append(FILE_UPDATE_STATUS);
   1.172 +  // If the update.status file exists then initiate post update processing.
   1.173 +  if (statusFile.exists()) {
   1.174 +    let aus = Components.classes["@mozilla.org/updates/update-service;1"].
   1.175 +              getService(Ci.nsIApplicationUpdateService).
   1.176 +              QueryInterface(Ci.nsIObserver);
   1.177 +    aus.observe(null, "post-update-processing", "");
   1.178 +  }
   1.179 +}
   1.180 +UpdateServiceStub.prototype = {
   1.181 +  observe: function(){},
   1.182 +  classID: Components.ID("{e43b0010-04ba-4da6-b523-1f92580bc150}"),
   1.183 +  QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver])
   1.184 +};
   1.185 +
   1.186 +this.NSGetFactory = XPCOMUtils.generateNSGetFactory([UpdateServiceStub]);

mercurial