Make the update wizard actually invoke XPInstall APIs to install the updates

This commit is contained in:
ben%bengoodger.com 2004-04-28 07:30:08 +00:00
parent 2194ffe4d2
commit 1b88aad30a
10 changed files with 279 additions and 39 deletions

View File

@ -164,6 +164,36 @@ nsExtensionManager.prototype = {
// we don't do this every time we start.
autoregFile.remove(false);
}
// Load default preferences files for all extensions
var defaultsManifest = fileLocator.get("ProfD", Components.interfaces.nsIFile);
defaultsManifest.append("extensions");
defaultsManifest.append("Defaults");
if (defaultsManifest.exists()) {
var pref = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefService);
var fis = Components.classes["@mozilla.org/network/file-input-stream;1"]
.createInstance(Components.interfaces.nsIFileInputStream);
fis.init(defaultsManifest, -1, -1, false);
var lis = fis.QueryInterface(Components.interfaces.nsILineInputStream);
var line = { value: "" };
var more = false;
do {
more = lis.readLine(line);
var lf = Components.classes["@mozilla.org/file/local;1"]
.createInstance(Components.interfaces.nsILocalFile);
var path = line.value;
if (path.charAt(path.length-1) == "\n")
path = path.substr(0, path.length - 1);
lf.initWithPath(path);
if (lf.exists())
pref.readUserPrefs(lf);
}
while (more);
fis.close();
}
break;
}
},
@ -175,7 +205,7 @@ nsExtensionManager.prototype = {
// Check to see if the version of the application that is being started
// now is the same one that was started last time.
var pref = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch);
.getService(Components.interfaces.nsIPrefBranch);
var currAppVersion = pref.getCharPref(PREF_EM_APP_VERSION);
try {
var lastAppVersion = pref.getCharPref(PREF_EM_LAST_APP_VERSION);
@ -211,7 +241,7 @@ nsExtensionManager.prototype = {
return rv;
},
_writeAutoReg: function ()
_writeProfileFile: function (aSubfolder, aFileName, aGetDirFunc, aWriteLineFunc)
{
// When an operation is performed that requires a component re-registration
// (extension enabled/disabled, installed, uninstalled), we must write the
@ -230,14 +260,16 @@ nsExtensionManager.prototype = {
// Open the .autoreg file for writing.
var autoregFile = profileDir.clone();
autoregFile.append(".autoreg");
var dataFile = profileDir.clone();
if (aSubfolder)
dataFile.append(aSubfolder);
dataFile.append(aFileName);
var fos = Components.classes["@mozilla.org/network/file-output-stream;1"]
.createInstance(Components.interfaces.nsIFileOutputStream);
const MODE_WRONLY = 0x02;
const MODE_CREATE = 0x08;
const MODE_TRUNCATE = 0x20;
fos.init(autoregFile, MODE_WRONLY | MODE_CREATE | MODE_TRUNCATE, 0664, 0);
fos.init(dataFile, MODE_WRONLY | MODE_CREATE | MODE_TRUNCATE, 0664, 0);
var extensions = this.getItemList(null, Components.interfaces.nsIUpdateItem.TYPE_EXTENSION, { });
for (var i = 0; i < extensions.length; ++i) {
@ -254,19 +286,60 @@ nsExtensionManager.prototype = {
var dir = location == "profile" ? profileDir : globalDir;
// Now synthesize the components dir for the extension
var componentsDir = dir.clone();
componentsDir.append("extensions");
componentsDir.append(extension.id);
componentsDir.append("components");
if (componentsDir.exists()) {
var sourceDir = aGetDirFunc(dir, extension.id);
if (sourceDir.exists()) {
// write the relative path of the components dir
var line = "reg:extensions/" + extension.id + "/components/\n";
fos.write(line, line.length);
aWriteLineFunc(fos, sourceDir, extension.id);
}
}
fos.close();
},
_getComponentsDir: function (aSourceDir, aExtensionID)
{
var sourceDir = aSourceDir.clone();
sourceDir.append("extensions");
sourceDir.append(aExtensionID);
sourceDir.append("components");
return sourceDir;
},
_getPreferencesDir: function (aSourceDir, aExtensionID)
{
var sourceDir = aSourceDir.clone();
sourceDir.append("extensions");
sourceDir.append(aExtensionID);
sourceDir.append("defaults");
sourceDir.append("preferences");
return sourceDir;
},
_writeAutoregLines: function (aStream, aSourceDir, aExtensionID)
{
var line = "reg:extensions/" + aExtensionID + "/components/\n";
aStream.write(line, line.length);
},
_writePreferencesLines: function (aStream, aSourceDir, aExtensionID)
{
var files = aSourceDir.directoryEntries;
while (files.hasMoreElements()) {
var file = files.getNext().QueryInterface(Components.interfaces.nsILocalFile);
var line = file.path + "\n";
aStream.write(line, line.length);
}
},
_writeProfileData: function ()
{
this._writeProfileFile(null, ".autoreg",
this._getComponentsDir,
this._writeAutoregLines);
this._writeProfileFile("extensions", "Defaults",
this._getPreferencesDir,
this._writePreferencesLines);
},
/////////////////////////////////////////////////////////////////////////////
// nsIExtensionManager
installExtensionFromStream: function (aStream, aUseProfile)
@ -290,25 +363,25 @@ nsExtensionManager.prototype = {
this._ensureDS();
this._ds.installExtension(ds, aUseProfile);
this._writeAutoReg();
this._writeProfileData();
},
uninstallExtension: function (aExtensionID)
{
this._ds.uninstallExtension(aExtensionID);
this._writeAutoReg();
this._writeProfileData();
},
enableExtension: function (aExtensionID)
{
this._ds.enableExtension(aExtensionID);
this._writeAutoReg();
this._writeProfileData();
},
disableExtension: function (aExtensionID)
{
this._ds.disableExtension(aExtensionID);
this._writeAutoReg();
this._writeProfileData();
},
// XXXben - handle the case where the item provides its own update url.

View File

@ -23,6 +23,7 @@ toolkit.jar:
* content/mozapps/update/update.js (update/content/update.js)
* content/mozapps/update/updates.xml (update/content/updates.xml)
* content/mozapps/update/update.css (update/content/update.css)
* content/mozapps/update/errors.xul (update/content/errors.xul)
* content/mozapps/shared/richview.xml (shared/content/richview.xml)
content/mozapps/contents.rdf (contents-content.rdf)
@ -39,6 +40,7 @@ en-US.jar:
locale/en-US/mozapps/extensions/about.dtd (extensions/locale/about.dtd)
locale/en-US/mozapps/update/update.dtd (update/locale/update.dtd)
locale/en-US/mozapps/update/update.properties (update/locale/update.properties)
locale/en-US/mozapps/update/errors.dtd (update/locale/errors.dtd)
locale/en-US/mozapps/contents.rdf (contents-locale.rdf)
classic.jar:

View File

@ -0,0 +1,81 @@
<?xml version="1.0"?>
# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is The Update Service.
#
# The Initial Developer of the Original Code is Ben Goodger.
# Portions created by the Initial Developer are Copyright (C) 2004
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Ben Goodger <ben@bengoodger.com>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<!DOCTYPE dialog SYSTEM "chrome://mozapps/locale/update/errors.dtd">
<dialog id="errors"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="&errors.title;"
onload="init()"
style="width: 25em;"
buttons="cancel">
<script type="application/x-javascript">
<![CDATA[
function init()
{
var items = window.arguments[0];
var listbox = document.getElementById("extensions");
for (var i = 0; i < items.length; ++i) {
if (items[i].error) {
var listitem = document.createElement("listitem");
listitem.setAttribute("label", items[i].name);
listbox.appendChild(listitem);
}
}
var strings = document.getElementById("updateStrings");
var cancel = document.documentElement.getButton("cancel");
cancel.label = strings.getString("closeButton");
cancel.focus();
}
]]>
</script>
<stringbundleset id="updateSet">
<stringbundle id="updateStrings" src="chrome://mozapps/locale/update/update.properties"/>
</stringbundleset>
<label>&errors.intro.title;</label>
<separator/>
<listbox id="extensions" rows="7"/>
<separator/>
</dialog>

View File

@ -368,17 +368,72 @@ var gInstallingPage = {
// Get XPInstallManager and kick off download/install
// process, registering us as an observer.
//XXXben
window.advance = function()
{
document.getElementById("installing").setAttribute("next", "finished");
document.documentElement.advance();
var items = [];
var foundList = document.getElementById("foundList");
for (var i = 0; i < foundList.childNodes.length; ++i) {
var item = foundList.childNodes[i];
if (item.type != nsIUpdateItem.TYPE_APP) {
items.push(item.url);
this._objs.push({ name: item.name });
}
}
setTimeout("advance()", 2000);
var xpimgr = Components.classes["@mozilla.org/xpinstall/install-manager;1"]
.createInstance(Components.interfaces.nsIXPInstallManager);
xpimgr.initManagerFromChrome(items, items.length, this);
},
/////////////////////////////////////////////////////////////////////////////
// nsIXPIProgressDialog
onStateChange: function (aIndex, aState, aValue)
{
var strings = document.getElementById("updateStrings");
const nsIXPIProgressDialog = Components.interfaces.nsIXPIProgressDialog;
switch (aState) {
case nsIXPIProgressDialog.DOWNLOAD_START:
var label = strings.getFormattedString("downloadingPrefix", [this._objs[aIndex].name]);
var actionItem = document.getElementById("actionItem");
actionItem.value = label;
break;
case nsIXPIProgressDialog.DOWNLOAD_DONE:
case nsIXPIProgressDialog.INSTALL_START:
var label = strings.getFormattedString("installingPrefix", [this._objs[aIndex].name]);
var actionItem = document.getElementById("actionItem");
actionItem.value = label;
break;
case nsIXPIProgressDialog.INSTALL_DONE:
if (aValue) {
this._objs[aIndex].error = aValue;
this._errors = true;
}
break;
case nsIXPIProgressDialog.DIALOG_CLOSE:
document.getElementById("installing").setAttribute("next", this._errors ? "errors" : "finished");
document.documentElement.advance();
break;
}
},
_objs: [],
_errors: false,
onProgress: function (aIndex, aValue, aMaxValue)
{
var downloadProgress = document.getElementById("downloadProgress");
downloadProgress.value = Math.ceil((aValue/aMaxValue) * 100);
}
};
var gErrorsPage = {
onShowErrors: function ()
{
openDialog("chrome://mozapps/content/update/errors.xul", "",
"modal", gInstallingPage._objs);
}
};
var gFinishedPage = {
onPageShow: function ()

View File

@ -131,10 +131,20 @@
label="&installing.title;"
onpageshow="gInstallingPage.onPageShow();">
<label>&installing.intro.label;</label>
<label>&installing.disclaimer.label;</label>
<label id="actionItem"/>
<progressmeter id="downloadProgress"/>
<separator/>
</wizardpage>
<wizardpage id="errors" pageid="errors"
label="&errors.title;"
align="right">
<label>&errors.intro.label;</label>
<separator/>
<button label="&errors.details.label;" accesskey="&errors.details.accesskey;"
oncommand="gErrorsPage.onShowErrors();"/>
<separator/>
</wizardpage>
<wizardpage id="finished" pageid="finished"

View File

@ -24,6 +24,7 @@
var os = Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService);
os.addObserver(this, "Update:Ended", false);
this.refreshData("null");
]]>
</constructor>
<destructor>
@ -41,18 +42,24 @@
<parameter name="aData"/>
<body>
<![CDATA[
if (aTopic == "Update:Ended") {
if (aTopic == "Update:Ended")
this.refreshData(Components.interfaces.nsIUpdateService.SOURCE_EVENT_BACKGROUND);
]]>
</body>
</method>
<method name="refreshData">
<parameter name="aSourceEvent"/>
<body>
<![CDATA[
var updates = Components.classes["@mozilla.org/updates/update-service;1"]
.getService(Components.interfaces.nsIUpdateService);
this.severity = updates.updateSeverity;
this.updateCount = updates.updateCount;
delete updates;
updates = null;
#ifdef XP_WIN
if (parseInt(aData) == Components.interfaces.nsIUpdateService.SOURCE_EVENT_BACKGROUND)
if (parseInt(aSourceEvent) == Components.interfaces.nsIUpdateService.SOURCE_EVENT_BACKGROUND)
this._showUpdateInfo();
#endif
}
]]>
</body>
</method>

View File

@ -0,0 +1,5 @@
<!ENTITY errors.title "Errors">
<!ENTITY errors.intro.title "The following components could not be installed due to errors
(the file could not be downloaded, was corrupt, or for some
other reason).">

View File

@ -1,12 +1,12 @@
<!ENTITY updateWizard.title "&brandShortName; Update">
<!ENTITY mismatch.title "Incompatible Extensions">
<!ENTITY mismatch.intro1.label "The following extensions are not compatible with the new version
<!ENTITY mismatch.title "Incompatible Components">
<!ENTITY mismatch.intro1.label "The following components are not compatible with the new version
of &brandShortName; you have just installed:">
<!ENTITY mismatch.intro2.label "They have been disabled until compatible versions are
installed.">
<!ENTITY mismatch.intro3.label "&brandShortName; can check for and install newer, compatible
versions of these extensions.">
versions of these components.">
<!ENTITY checking.title "Checking for Updates">
<!ENTITY checking.intro.label "&brandShortName; is now checking for available updates...">
@ -37,14 +37,16 @@
<!ENTITY finished.title "Update Complete">
<!ENTITY finished.updated.label "&brandShortName; has installed the available updates.">
<!ENTITY finished.remaining.label "Some incompatible extensions could not be updated, perhaps
<!ENTITY finished.remaining.label "Some incompatible components could not be updated, perhaps
because compatible versions are not available at this time.
&brandShortName; will check periodically and inform you
when updated versions become available.">
<!ENTITY finished.remaining2.label "Some incompatible extensions could not be updated, perhaps
<!ENTITY finished.remaining2.label "Some incompatible components could not be updated, perhaps
because compatible versions are not available at this time.
&brandShortName; can check periodically and inform you
when updated versions become available.">
<!ENTITY finished.error.label "&brandShortName; did not succeed in downloading and
installing some updates.">
<!ENTITY finished.enableChecking.label "Allow &brandShortName; to check for updates.">
<!ENTITY finished.mismatch.label "Click Finish to continue starting &brandShortName;.">
@ -55,5 +57,9 @@
web site where you can download the latest version of
&brandShortName;.">
<!ENTITY errors.title "Problems During Update">
<!ENTITY errors.intro.label "&brandShortName; encountered problems when updating your
software, and as a result not all components could be updated.">
<!ENTITY errors.details.label "Details">
<!ENTITY errors.details.accesskey "D">

View File

@ -10,3 +10,7 @@ update.app.url=http://localhost/update.rdf
updatesAvailableTitle=New Updates Available
updatesAvailableText=Click Here to View
downloadingPrefix=Downloading: %S
installingPrefix=Installing: %S
closeButton=Close

View File

@ -94,9 +94,6 @@ nsBackgroundUpdateService.prototype = {
var interval = this._pref.getIntPref(PREF_UPDATE_INTERVAL);
var lastUpdateTime = this._pref.getIntPref(PREF_UPDATE_LASTUPDATEDATE);
var timeSinceLastCheck = Date.UTC() - lastUpdateTime;
this.checkForUpdatesInternal([], 0, nsIUpdateItem.TYPE_ANY,
nsIUpdateService.SOURCE_EVENT_BACKGROUND); /// XXXben
if (timeSinceLastCheck > interval) {
if (!this.updating)
this.checkForUpdatesInternal([], 0, nsIUpdateItem.TYPE_ANY,