make install notification work on subsequent start after install - not done yet

This commit is contained in:
ben%bengoodger.com 2005-06-30 01:35:45 +00:00
Родитель 56f44188ce
Коммит 5f0359fa0a
7 изменённых файлов: 225 добавлений и 67 удалений

Просмотреть файл

@ -42,9 +42,7 @@
# SYNTAX HINTS: dashes are delimiters. Use underscores instead.
# The first character after a period must be alphabetic.
pref("app.update.logEnabled", true);
// pref("startup.homepage_override_url","chrome://browser-region/locale/region.properties");
pref("startup.homepage_override_url","chrome://browser-region/locale/region.properties");
pref("general.startup.browser", true);
pref("browser.chromeURL","chrome://browser/content/");
@ -118,6 +116,13 @@ pref("app.update.nagTimer.restart", 1800);
// default=5 seconds
pref("app.update.timer", 5000);
// Whether or not we show a dialog box informing the user that the update was
// successfully applied. This is off in Firefox by default since we show a
// upgrade start page instead! Other apps may wish to show this UI, and supply
// a whatsNewURL field in their brand.properties that contains a link to a page
// which tells users what's new in this new update.
pref("app.update.showInstalledUI", false);
// Symmetric (can be overridden by individual extensions) update preferences.
// e.g.
// extensions.{GUID}.update.enabled
@ -173,9 +178,6 @@ pref("browser.shell.checkDefaultBrowser", true);
pref("browser.startup.page", 1);
pref("browser.startup.homepage", "resource:/browserconfig.properties");
// "browser.startup.homepage_override" was for 4.x
pref("browser.startup.homepage_override.1", false);
pref("browser.cache.disk.capacity", 50000);
pref("browser.enable_automatic_image_resizing", true);
pref("browser.urlbar.matchOnlyTyped", false);
@ -319,11 +321,6 @@ pref("alerts.slideIncrementTime", 10);
pref("alerts.totalOpenTime", 4000);
pref("alerts.height", 50);
// update notifications prefs
pref("update_notifications.enabled", true);
pref("update_notifications.provider.0.frequency", 7); // number of days
pref("update_notifications.provider.0.datasource", "chrome://browser-region/locale/region.properties");
pref("browser.xul.error_pages.enabled", true);
pref("signon.rememberSignons", true);

Просмотреть файл

@ -14,7 +14,7 @@ browser.search.order.1=Google
browser.search.order.2=Yahoo
#config.js
startup.homepage_override_url=http://start.mozilla.org/firefox
startup.homepage_override_url=http://www.mozilla.org/products/firefox/releases/whatsnew/
# search-panel.properties
defaultSearchURL=http://www.google.com/search?hl=en&lr=&ie=UTF-8&oe=UTF-8&q=

Просмотреть файл

@ -54,6 +54,10 @@
<!ENTITY errorManual.label "You can update &brandShortName; manually by visiting this link
and downloading the latest version:">
<!ENTITY errorpatching.title "Update Failed">
<!ENTITY errorpatching.intro "The partial Update could not be applied.
&brandShortName; will try again by downloading a complete Update.">
<!ENTITY finished.title "Update Downloaded">
<!ENTITY finished.intro "The update was successfully downloaded and verified. You must now restart
&brandShortName; so that the update can be installed.">
@ -69,6 +73,7 @@
<!ENTITY installed.title "Update Installed">
<!ENTITY installed.intro "The update was successfully installed.">
<!ENTITY whatsnew.label "Read more about what's new...">
<!ENTITY update.details.label "Details">
<!ENTITY update.installedOn.label "Installed on:">

Просмотреть файл

@ -67,3 +67,6 @@ checker_error-2152398868=AUS: No data was received (Please try again)
checker_error-2152398919=AUS: Data transfer was interrupted (Please try again)
checker_error-2152398867=AUS: Port not allowed (Contact your Administrator)
checker_error-verification_failed=The integrity of the update could not be verified (Contact your Administrator)
installSuccess=The Update was successfully installed
patchApplyFailure=The Update could not be installed (Patch Apply Failed)

Просмотреть файл

@ -54,6 +54,7 @@ const STATE_DOWNLOADING = "downloading";
const STATE_PENDING = "pending";
const STATE_APPLYING = "applying";
const STATE_SUCCEEDED = "succeeded";
const STATE_DOWNLOAD_FAILED = "download-failed";
const STATE_FAILED = "failed";
const SRCEVT_FOREGROUND = 1;
@ -239,34 +240,63 @@ var gUpdates = {
*
* This is determined by how we were called by the update prompt:
*
* U'Prompt Method: Arg0: Update State: Src Event:
* showUpdateAvailable nsIUpdate obj -- background
* showUpdateDownloaded nsIUpdate obj pending background
* showUpdateInstalled nsIUpdate obj succeeded either
* showUpdateError nsIUpdate obj failed either
* checkForUpdates null -- foreground
* U'Prompt Method: Arg0: Update State: Src Event: p'Failed: Result:
* showUpdateAvailable nsIUpdate obj -- background -- updatesfound
* showUpdateDownloaded nsIUpdate obj pending background -- finishedBackground
* showUpdateInstalled nsIUpdate obj succeeded either -- installed
* showUpdateError nsIUpdate obj failed either partial errorpatching
* showUpdateError nsIUpdate obj failed either complete errors
* checkForUpdates null -- foreground -- checking
* checkForUpdates null downloading foreground -- downloading
*/
get startPage() {
dump("*** GET STARTPAGE\n");
if (window.arguments) {
var arg0 = window.arguments[0];
dump("*** arg0 = " + arg0 + "\n");
if (arg0 instanceof Components.interfaces.nsIUpdate) {
// If the first argument is a nsIUpdate object, we are notifying the
// user that the background checking found an update that requires
// their permission to install, and it's ready for download.
this.setUpdate(arg0);
var p = this.update.selectedPatch;
dump("*** P = " + p + "\n");
if (p) {
switch (p.state) {
LOG("Downloader", "WIZARD UI STATE = " + p.state);
var state = p.state;
if (state == STATE_DOWNLOADING) {
var patchFailed = false;
try {
patchFailed = this.update.getProperty("patchingFailed");
}
catch (e) {
}
if (patchFailed == "partial") {
// If the system failed to apply the partial patch, show the
// screen which best describes this condition, which is triggered
// by the |STATE_FAILED| state.
state = STATE_FAILED;
}
else if (patchFailed == "complete") {
// Otherwise, if the complete patch failed, which is far less
// likely, show the error text held by the update object in the
// generic errors page, triggered by the |STATE_DOWNLOAD_FAILED|
// state.
state = STATE_DOWNLOAD_FAILED;
}
}
// Now select the best page to start with, given the current state of
// the Update.
switch (state) {
case STATE_PENDING:
this.sourceEvent = SRCEVT_BACKGROUND;
return document.getElementById("finishedBackground");
case STATE_SUCCEEDED:
dump("*** :::::: goats\n");
return document.getElementById("installed");
case STATE_DOWNLOADING:
return document.getElementById("downloading");
case STATE_FAILED:
window.getAttention();
return document.getElementById("errorpatching");
case STATE_DOWNLOAD_FAILED:
case STATE_APPLYING:
return document.getElementById("errors");
}
@ -921,6 +951,11 @@ var gDownloadingPage = {
return;
}
// Say that this was a foreground download, not a background download,
// since the user cared enough to look in on this process.
gUpdates.update.QueryInterface(Components.interfaces.nsIWritablePropertyBag);
gUpdates.update.setProperty("foregroundDownload", "true");
// Pause any active background download and restart it as a foreground
// download.
updates.pauseDownload();
@ -1159,7 +1194,8 @@ var gDownloadingPage = {
const NS_BINDING_ABORTED = 0x804b0002;
switch (status) {
case Components.results.NS_ERROR_UNEXPECTED:
if (u.selectedPatch.state == STATE_FAILED && u.isCompleteUpdate) {
if (u.selectedPatch.state == STATE_DOWNLOAD_FAILED &&
u.isCompleteUpdate) {
// Verification error of complete patch, informational text is held in
// the update object.
gUpdates.wiz.currentPage = document.getElementById("errors");
@ -1237,6 +1273,15 @@ var gErrorsPage = {
var errorLinkLabel = document.getElementById("errorLinkLabel");
errorLinkLabel.value = manualURL.data;
},
/**
* Initialize, for the "Error Applying Patch" case.
*/
onPageShowPatching: function() {
gUpdates.wiz.getButton("back").disabled = true;
gUpdates.wiz.getButton("cancel").disabled = true;
gUpdates.wiz.getButton("next").focus();
},
};
/**
@ -1356,7 +1401,22 @@ var gInstalledPage = {
* Initialize
*/
onPageShow: function() {
var ai =
Components.classes["@mozilla.org/xre/app-info;1"].
getService(Components.interfaces.nsIXULAppInfo);
var branding = document.getElementById("brandStrings");
try {
var url = branding.getFormattedString("whatsNewURL", [ai.version]);
var whatsnewLink = document.getElementById("whatsnewLink");
whatsnewLink.href = url;
whatsnewLink.hidden = false;
}
catch (e) {
}
gUpdates.wiz.getButton("cancel").disabled = true;
gUpdates.wiz.getButton("finish").focus();
},
};
@ -1372,3 +1432,13 @@ function tryToClose() {
return true;
}
/**
* Callback for the Update Prompt to set the current page if an Update Wizard
* window is already found to be open.
* @param pageid
* The ID of the page to switch to
*/
function setCurrentPage(pageid) {
gUpdates.wiz.currentPage = document.getElementById(pageid);
}

Просмотреть файл

@ -172,6 +172,12 @@
</hbox>
</wizardpage>
<wizardpage id="errorpatching" pageid="errorpatching" next="downloading"
label="&errorpatching.title;" object="gErrorsPage"
onpageshow="gErrorsPage.onPageShowPatching();">
<label>&errorpatching.intro;</label>
</wizardpage>
<wizardpage id="finished" pageid="finished"
label="&finished.title;" object="gFinishedPage"
onpageshow="gFinishedPage.onPageShow();">
@ -200,6 +206,12 @@
label="&installed.title;" object="gInstalledPage"
onpageshow="gInstalledPage.onPageShow();">
<label>&installed.intro;</label>
<separator/>
<hbox>
<link id="whatsnewLink" hidden="true">
<label>&whatsnew.label;</label>
</link>
</hbox>
</wizardpage>
</wizard>

Просмотреть файл

@ -45,7 +45,8 @@ const PREF_APP_UPDATE_TIMER = "app.update.timer";
const PREF_APP_UPDATE_LOG_BRANCH = "app.update.log.";
const PREF_APP_UPDATE_URL = "app.update.url";
const PREF_APP_UPDATE_URL_OVERRIDE = "app.update.url.override";
const PREF_UPDATE_LASTUPDATETIME_FMT = "app.update.lastUpdateTime.%ID%";
const PREF_APP_UPDATE_SHOW_INSTALLED_UI = "app.update.showInstalledUI";
const PREF_APP_UPDATE_LASTUPDATETIME_FMT = "app.update.lastUpdateTime.%ID%";
const PREF_APP_EXTENSIONS_VERSION = "app.extensions.version";
const URI_UPDATE_PROMPT_DIALOG = "chrome://mozapps/content/update/updates.xul";
@ -78,6 +79,7 @@ const STATE_DOWNLOADING = "downloading";
const STATE_PENDING = "pending";
const STATE_APPLYING = "applying";
const STATE_SUCCEEDED = "succeeded";
const STATE_DOWNLOAD_FAILED = "download-failed";
const STATE_FAILED = "failed";
const DOWNLOAD_CHUNK_SIZE = 65536;
@ -411,7 +413,8 @@ UpdatePrompt.prototype = {
* See nsIUpdateService.idl
*/
checkForUpdates: function(parent) {
this._showUI(parent, URI_UPDATE_PROMPT_DIALOG, null, "Update:Wizard", null);
this._showUI(parent, URI_UPDATE_PROMPT_DIALOG, null, "Update:Wizard",
null, null);
},
/**
@ -420,7 +423,7 @@ UpdatePrompt.prototype = {
showUpdateAvailable: function(parent, update) {
if (this._enabled) {
this._showUI(parent, URI_UPDATE_PROMPT_DIALOG, null, "Update:Wizard",
update);
"updatesavailable", update);
}
},
@ -430,7 +433,7 @@ UpdatePrompt.prototype = {
showUpdateDownloaded: function(parent, update) {
if (this._enabled) {
this._showUI(parent, URI_UPDATE_PROMPT_DIALOG, null, "Update:Wizard",
update);
"finishedBackground", update);
}
},
@ -438,9 +441,11 @@ UpdatePrompt.prototype = {
* See nsIUpdateService.idl
*/
showUpdateInstalled: function(update) {
if (this._enabled) {
this._showUI(null, URI_UPDATE_PROMPT_DIALOG, "modal", "Update:Wizard",
update);
var showUpdateInstalledUI = getPref("getBoolPref",
PREF_APP_UPDATE_SHOW_INSTALLED_UI, true);
if (this._enabled && showUpdateInstalledUI) {
this._showUI(null, URI_UPDATE_PROMPT_DIALOG, null, "Update:Wizard",
"installed", update);
}
},
@ -449,8 +454,8 @@ UpdatePrompt.prototype = {
*/
showUpdateError: function(update) {
if (this._enabled) {
this._showUI(null, URI_UPDATE_PROMPT_DIALOG, "modal", "Update:Wizard",
update);
this._showUI(null, URI_UPDATE_PROMPT_DIALOG, null, "Update:Wizard",
"errors", update);
}
},
@ -458,7 +463,8 @@ UpdatePrompt.prototype = {
* See nsIUpdateService.idl
*/
showUpdateHistory: function(parent) {
this._showUI(parent, URI_UPDATE_HISTORY_DIALOG, "modal", "Update:History", null);
this._showUI(parent, URI_UPDATE_HISTORY_DIALOG, "modal", "Update:History",
null, null);
},
/**
@ -477,11 +483,13 @@ UpdatePrompt.prototype = {
* @param name
* The Window Name of the dialog to show, in case it is already open
* and can merely be focused
* @param page
* The page of the wizard to be displayed, if one is already open.
* @param update
* An update to pass to the UI in the window arguments.
* Can be null
*/
_showUI: function(parent, uri, features, name, update) {
_showUI: function(parent, uri, features, name, page, update) {
var ary = null;
if (update) {
ary = Components.classes["@mozilla.org/supports-array;1"]
@ -492,8 +500,11 @@ UpdatePrompt.prototype = {
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator);
var win = wm.getMostRecentWindow(name);
if (win)
if (win) {
if (page && "setCurrentPage" in win)
win.setCurrentPage(page);
win.focus();
}
else {
var openFeatures = "chrome,centerscreen,dialog";
if (features)
@ -573,9 +584,24 @@ UpdateService.prototype = {
},
/**
*
* Perform post-processing on updates lingering in the updates directory
* from a previous browser session - either report install failures (and
* optionally attempt to fetch a different version if appropriate) or
* notify the user of install success.
*/
_postUpdateCleanup: function() {
/**
* Clean up updates list and the updates directory.
*/
function cleanup() {
// Move the update from the Active Update list into the Past Updates list.
um.activeUpdate = null;
um.saveUpdates();
// Now trash the updates directory, since we're done with it
cleanUpUpdatesDir();
}
// Detect installation failures and notify
var status = readStatusFile(getUpdatesDir());
if (status != null) {
@ -591,29 +617,45 @@ UpdateService.prototype = {
Components.classes["@mozilla.org/updates/update-prompt;1"].
createInstance(Components.interfaces.nsIUpdatePrompt);
var shouldCleanup = true;
var update = um.activeUpdate;
if (!update)
update = new Update(null);
update.state = status;
var sbs =
Components.classes["@mozilla.org/intl/stringbundle;1"].
getService(Components.interfaces.nsIStringBundleService);
var bundle = sbs.createBundle(URI_UPDATES_PROPERTIES);
if (status == STATE_SUCCEEDED) {
update.statusText = "Install Succeeded";
update.statusText = bundle.GetStringFromName("installSuccess");
LOG("UpdateService", "_postUpdateCleanup: Install Succeeded, Showing UI");
prompter.showUpdateInstalled(update);
// Done with this update. Clean it up.
cleanup();
}
else {
// Something went wrong with the patch application process.
update.statusText = "goats";
// XXXben todo: synthesize the best message
LOG("UpdateService", "_postUpdateCleanup: Install Failed, Showing UI");
cleanup();
update.statusText = bundle.GetStringFromName("patchApplyFailure");
var oldType = update.selectedPatch ? update.selectedPatch.type
: "complete";
if (update.selectedPatch && oldType == "partial") {
// Partial patch application failed, try downloading the complete
// update in the background instead.
LOG("UpdateService", "_postUpdateCleanup: Install of Partial Patch " +
"failed, downloading Complete Patch and maybe showing UI");
this.downloadUpdate(update, true);
}
else {
LOG("UpdateService", "_postUpdateCleanup: Install of Complete or " +
"only patch failed. Showing error.");
}
update.QueryInterface(Components.interfaces.nsIWritablePropertyBag);
update.setProperty("patchingFailed", oldType);
prompter.showUpdateError(update);
}
// Move the update from the Active Update list into the Past Updates list.
um.activeUpdate = null;
um.saveUpdates();
// Now trash the updates directory, since we're done with it
cleanUpUpdatesDir();
}
else {
LOG("UpdateService", "_postUpdateCleanup: No Status, No Update");
@ -1059,6 +1101,8 @@ UpdateManager.prototype = {
* The nsIUpdate object to add.
*/
_addUpdate: function(update) {
if (!update)
return;
if (this._updates) {
for (var i = 0; i < this._updates.length; ++i) {
if (this._updates[i].version == update.version) {
@ -1806,6 +1850,7 @@ Downloader.prototype = {
LOG("Downloader", "already downloaded and staged");
return null;
case STATE_FAILED:
case STATE_DOWNLOAD_FAILED:
case STATE_APPLYING:
case STATE_NONE:
// Something went wrong when we tried to apply the previous patch.
@ -2013,7 +2058,8 @@ Downloader.prototype = {
request.QueryInterface(nsIIncrementalDownload);
LOG("Downloader", "onStopRequest: " + request.URI.spec + ", status = " + status);
var state;
var state = this._patch.state;
LOG("Downloader", "STATE SET = " + state);
var shouldShowPrompt = false;
var deleteActiveUpdate = false;
const NS_BINDING_ABORTED = 0x804b0002;
@ -2034,7 +2080,7 @@ Downloader.prototype = {
this._update.statusText = "Install Pending";
} else {
LOG("Downloader", "onStopRequest: download verification failed");
state = STATE_FAILED;
state = STATE_DOWNLOAD_FAILED;
var sbs =
Components.classes["@mozilla.org/intl/stringbundle;1"].
@ -2063,7 +2109,7 @@ Downloader.prototype = {
status != NS_ERROR_ABORT) {
LOG("Downloader", "onStopRequest: Non-verification failure");
// Some sort of other failure, log this in the |statusText| property
state = STATE_FAILED;
state = STATE_DOWNLOAD_FAILED;
// XXXben - if |request| (The Incremental Download) provided a means
// for accessing the http channel we could do more here.
@ -2094,7 +2140,8 @@ Downloader.prototype = {
this._request = null;
if (state == STATE_FAILED && !this._update.isCompleteUpdate) {
if (state == STATE_DOWNLOAD_FAILED) {
if (!this._update.isCompleteUpdate) {
// If we were downloading a patch and the patch verification phase
// failed, log this and then commence downloading the complete update.
LOG("Downloader", "onStopRequest: Verification of patch failed, downloading complete update");
@ -2103,6 +2150,30 @@ Downloader.prototype = {
// This will reset the |.state| property on this._update if a new
// download initiates.
}
else {
// In all other failure cases, i.e. we're S.O.L. - no more failing over
// ...
// If this was ever a foreground download, and now there is no UI active
// (e.g. because the user closed the download window) and there was an
// error, we must notify now. Otherwise we can keep the failure to
// ourselves since the user won't be expecting it.
var fgdl = false;
try {
fgdl = this._update.getProperty("foregroundDownload");
}
catch (e) {
}
if (fgdl == "true") {
var prompter =
Components.classes["@mozilla.org/updates/update-prompt;1"].
createInstance(Components.interfaces.nsIUpdatePrompt);
this._update.QueryInterface(Components.interfaces.nsIWritablePropertyBag);
this._update.setProperty("downloadFailed", "true");
prompter.showUpdateError(this._update);
}
}
}
// Do this after *everything* else, since it will likely cause the app
// to shut down.
@ -2174,7 +2245,7 @@ TimerManager.prototype = {
timerData.callback instanceof Components.interfaces.nsITimerCallback) {
timerData.callback.notify(timer);
timerData.lastUpdateTime = now;
var preference = PREF_UPDATE_LASTUPDATETIME_FMT.replace(/%ID%/, timerID);
var preference = PREF_APP_UPDATE_LASTUPDATETIME_FMT.replace(/%ID%/, timerID);
gPref.setIntPref(preference, now);
}
}
@ -2184,7 +2255,7 @@ TimerManager.prototype = {
* See nsIUpdateService.idl
*/
registerTimer: function(id, callback, interval) {
var preference = PREF_UPDATE_LASTUPDATETIME_FMT.replace(/%ID%/, id);
var preference = PREF_APP_UPDATE_LASTUPDATETIME_FMT.replace(/%ID%/, id);
var lastUpdateTime = getPref("getIntPref", preference,
Math.round(Date.now() / 1000));
this._timers[id] = { callback : callback,