mirror of
https://github.com/gryf/pentadactyl-pm.git
synced 2025-12-21 06:57:59 +01:00
Fix tab number updates in FF36. Closes issue 300.
This commit is contained in:
@@ -1,530 +0,0 @@
|
||||
/* * ***** BEGIN LICENSE BLOCK *****
|
||||
* 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 MozMill Test code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Henrik Skupin <hskupin@mozilla.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 ***** */
|
||||
|
||||
/**
|
||||
* @fileoverview
|
||||
* The SoftwareUpdateAPI adds support for an easy access to the update process.
|
||||
*/
|
||||
|
||||
// Include required modules
|
||||
var prefs = require("prefs");
|
||||
var utils = require("utils");
|
||||
|
||||
const gTimeoutUpdateCheck = 10000;
|
||||
const gTimeoutUpdateDownload = 360000;
|
||||
|
||||
const PREF_DISABLED_ADDONS = "extensions.disabledAddons";
|
||||
|
||||
// Helper lookup constants for elements of the software update dialog
|
||||
const WIZARD = '/id("updates")';
|
||||
const WIZARD_BUTTONS = WIZARD + '/anon({"anonid":"Buttons"})';
|
||||
const WIZARD_DECK = WIZARD + '/anon({"anonid":"Deck"})';
|
||||
|
||||
const WIZARD_PAGES = {
|
||||
dummy: 'dummy',
|
||||
checking: 'checking',
|
||||
pluginUpdatesFound: 'pluginupdatesfound',
|
||||
noUpdatesFound: 'noupdatesfound',
|
||||
manualUpdate: 'manualUpdate',
|
||||
incompatibleCheck: 'incompatibleCheck',
|
||||
updatesFoundBasic: 'updatesfoundbasic',
|
||||
updatesFoundBillboard: 'updatesfoundbillboard',
|
||||
license: 'license',
|
||||
incompatibleList: 'incompatibleList',
|
||||
downloading: 'downloading',
|
||||
errors: 'errors',
|
||||
errorPatching: 'errorpatching',
|
||||
finished: 'finished',
|
||||
finishedBackground: 'finishedBackground',
|
||||
installed: 'installed'
|
||||
}
|
||||
|
||||
// On Mac there is another DOM structure used as on Windows and Linux
|
||||
if (mozmill.isMac) {
|
||||
var WIZARD_BUTTONS_BOX = WIZARD_BUTTONS +
|
||||
'/anon({"flex":"1"})/{"class":"wizard-buttons-btm"}/';
|
||||
var WIZARD_BUTTON = {
|
||||
back: '{"dlgtype":"back"}',
|
||||
next: '{"dlgtype":"next"}',
|
||||
cancel: '{"dlgtype":"cancel"}',
|
||||
finish: '{"dlgtype":"finish"}',
|
||||
extra1: '{"dlgtype":"extra1"}',
|
||||
extra2: '{"dlgtype":"extra2"}'
|
||||
}
|
||||
} else {
|
||||
var WIZARD_BUTTONS_BOX = WIZARD_BUTTONS +
|
||||
'/anon({"flex":"1"})/{"class":"wizard-buttons-box-2"}/';
|
||||
var WIZARD_BUTTON = {
|
||||
back: '{"dlgtype":"back"}',
|
||||
next: 'anon({"anonid":"WizardButtonDeck"})/[1]/{"dlgtype":"next"}',
|
||||
cancel: '{"dlgtype":"cancel"}',
|
||||
finish: 'anon({"anonid":"WizardButtonDeck"})/[0]/{"dlgtype":"finish"}',
|
||||
extra1: '{"dlgtype":"extra1"}',
|
||||
extra2: '{"dlgtype":"extra2"}'
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for software update class
|
||||
*/
|
||||
function softwareUpdate() {
|
||||
this._controller = null;
|
||||
this._wizard = null;
|
||||
this._downloadDuration = -1;
|
||||
|
||||
this._aus = Cc["@mozilla.org/updates/update-service;1"].
|
||||
getService(Ci.nsIApplicationUpdateService);
|
||||
this._ums = Cc["@mozilla.org/updates/update-manager;1"].
|
||||
getService(Ci.nsIUpdateManager);
|
||||
this._vc = Cc["@mozilla.org/xpcom/version-comparator;1"].
|
||||
getService(Ci.nsIVersionComparator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Class for software updates
|
||||
*/
|
||||
softwareUpdate.prototype = {
|
||||
/**
|
||||
* Returns the active update
|
||||
*
|
||||
* @returns The currently selected update
|
||||
* @type nsIUpdate
|
||||
*/
|
||||
get activeUpdate() {
|
||||
return this._ums.activeUpdate;
|
||||
},
|
||||
|
||||
/**
|
||||
* Check if the user has permissions to run the software update
|
||||
*
|
||||
* @returns Status if the user has the permissions.
|
||||
* @type {boolean}
|
||||
*/
|
||||
get allowed() {
|
||||
return this._aus.canCheckForUpdates && this._aus.canApplyUpdates;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns information of the current build version
|
||||
*/
|
||||
get buildInfo() {
|
||||
return {
|
||||
buildid : utils.appInfo.buildID,
|
||||
disabled_addons : prefs.preferences.getPref(PREF_DISABLED_ADDONS, ''),
|
||||
locale : utils.appInfo.locale,
|
||||
user_agent : utils.appInfo.userAgent,
|
||||
version : utils.appInfo.version
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the current update channel
|
||||
*/
|
||||
get channel() {
|
||||
return prefs.preferences.getPref('app.update.channel', '');
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the controller of the associated engine manager dialog
|
||||
*
|
||||
* @returns Controller of the browser window
|
||||
* @type MozMillController
|
||||
*/
|
||||
get controller() {
|
||||
return this._controller;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the current step of the software update dialog wizard
|
||||
*/
|
||||
get currentPage() {
|
||||
return this._wizard.getNode().getAttribute('currentpageid');
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns true if the offered update is a complete update
|
||||
*/
|
||||
get isCompleteUpdate() {
|
||||
// Throw when isCompleteUpdate is called without an update. This should
|
||||
// never happen except if the test is incorrectly written.
|
||||
if (!this.activeUpdate)
|
||||
throw new Error(arguments.callee.name + ": isCompleteUpdate called " +
|
||||
"when activeUpdate is null!");
|
||||
|
||||
var patchCount = this.activeUpdate.patchCount;
|
||||
if ((patchCount < 1) || (patchCount > 2)) {
|
||||
throw new Error("An update must have one or two patches included.");
|
||||
}
|
||||
|
||||
// XXX: After Firefox 4 has been released and we do not have to test any
|
||||
// beta release anymore uncomment out the following code
|
||||
// if (this.activeUpdate.patchCount == 2) {
|
||||
// var patch0URL = this.activeUpdate.getPatchAt(0).URL;
|
||||
// var patch1URL = this.activeUpdate.getPatchAt(1).URL;
|
||||
// Test that the update snippet created by releng doesn't have the same
|
||||
// url for both patches (bug 514040).
|
||||
// controller.assertJS("subject.patch0URL != subject.patch1URL",
|
||||
// {patch0URL: patch0URL, patch1URL: patch1URL});
|
||||
// }
|
||||
|
||||
return (this.activeUpdate.selectedPatch.type == "complete");
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns information of the active update in the queue.
|
||||
*/
|
||||
get patchInfo() {
|
||||
this._controller.assert(function() {
|
||||
return !!this.activeUpdate;
|
||||
}, "An active update is in the queue.", this);
|
||||
|
||||
return {
|
||||
buildid : this.activeUpdate.buildID,
|
||||
channel : this.channel,
|
||||
is_complete : this.isCompleteUpdate,
|
||||
size : this.activeUpdate.selectedPatch.size,
|
||||
type : this.activeUpdate.type,
|
||||
url : this.activeUpdate.selectedPatch.finalURL || "n/a",
|
||||
download_duration : this._downloadDuration,
|
||||
version : this.activeUpdate.version
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the update type (minor or major)
|
||||
*
|
||||
* @returns The update type
|
||||
*/
|
||||
get updateType() {
|
||||
return this.activeUpdate.type;
|
||||
},
|
||||
|
||||
/**
|
||||
* Check if updates have been found
|
||||
*/
|
||||
get updatesFound() {
|
||||
return this.currentPage.indexOf("updatesfound") == 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* Checks if an update has been applied correctly
|
||||
*
|
||||
* @param {object} updateData
|
||||
* All the data collected during the update process
|
||||
*/
|
||||
assertUpdateApplied : function softwareUpdate_assertUpdateApplied(updateData) {
|
||||
// Get the information from the last update
|
||||
var info = updateData.updates[updateData.updateIndex];
|
||||
|
||||
// The upgraded version should be identical with the version given by
|
||||
// the update and we shouldn't have run a downgrade
|
||||
var check = this._vc.compare(info.build_post.version, info.build_pre.version);
|
||||
this._controller.assert(function () {
|
||||
return check >= 0;
|
||||
}, "The version number of the upgraded build is higher or equal.");
|
||||
|
||||
// The build id should be identical with the one from the update
|
||||
this._controller.assert(function () {
|
||||
return info.build_post.buildid === info.patch.buildid;
|
||||
}, "The build id is equal to the build id of the update.");
|
||||
|
||||
// If a target build id has been given, check if it matches the updated build
|
||||
info.target_buildid = updateData.targetBuildID;
|
||||
if (info.target_buildid) {
|
||||
this._controller.assert(function () {
|
||||
return info.build_post.buildid === info.target_buildid;
|
||||
}, "Target build id matches id of updated build.");
|
||||
}
|
||||
|
||||
// An upgrade should not change the builds locale
|
||||
this._controller.assert(function () {
|
||||
return info.build_post.locale === info.build_pre.locale;
|
||||
}, "The locale of the updated build is identical to the original locale.");
|
||||
|
||||
// Check that no application-wide add-ons have been disabled
|
||||
this._controller.assert(function () {
|
||||
return info.build_post.disabled_addons === info.build_pre.disabled_addons;
|
||||
}, "No application-wide add-ons have been disabled by the update.");
|
||||
},
|
||||
|
||||
/**
|
||||
* Close the software update dialog
|
||||
*/
|
||||
closeDialog: function softwareUpdate_closeDialog() {
|
||||
if (this._controller) {
|
||||
this._controller.keypress(null, "VK_ESCAPE", {});
|
||||
this._controller.sleep(500);
|
||||
this._controller = null;
|
||||
this._wizard = null;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Download the update of the given channel and type
|
||||
* @param {string} channel
|
||||
* Update channel to use
|
||||
* @param {boolean} waitForFinish
|
||||
* Sets if the function should wait until the download has been finished
|
||||
* @param {number} timeout
|
||||
* Timeout the download has to stop
|
||||
*/
|
||||
download : function softwareUpdate_download(channel, waitForFinish, timeout) {
|
||||
waitForFinish = waitForFinish ? waitForFinish : true;
|
||||
|
||||
// Check that the correct channel has been set
|
||||
this._controller.assert(function() {
|
||||
return channel == this.channel;
|
||||
}, "The current update channel is identical to the specified one.", this);
|
||||
|
||||
// Retrieve the timestamp, so we can measure the duration of the download
|
||||
var startTime = Date.now();
|
||||
|
||||
// Click the next button
|
||||
var next = this.getElement({type: "button", subtype: "next"});
|
||||
this._controller.click(next);
|
||||
|
||||
// Wait for the download page - if it fails the update was already cached
|
||||
try {
|
||||
this.waitForWizardPage(WIZARD_PAGES.downloading);
|
||||
|
||||
if (waitForFinish)
|
||||
this.waitforDownloadFinished(timeout);
|
||||
} catch (ex) {
|
||||
this.waitForWizardPage(WIZARD_PAGES.finished);
|
||||
}
|
||||
|
||||
// Calculate the duration in ms
|
||||
this._downloadDuration = Date.now() - startTime;
|
||||
},
|
||||
|
||||
/**
|
||||
* Update the update.status file and set the status to 'failed:6'
|
||||
*/
|
||||
forceFallback : function softwareUpdate_forceFallback() {
|
||||
var dirService = Cc["@mozilla.org/file/directory_service;1"].
|
||||
getService(Ci.nsIProperties);
|
||||
|
||||
var updateDir;
|
||||
var updateStatus;
|
||||
|
||||
// Check the global update folder first
|
||||
try {
|
||||
updateDir = dirService.get("UpdRootD", Ci.nsIFile);
|
||||
updateDir.append("updates");
|
||||
updateDir.append("0");
|
||||
|
||||
updateStatus = updateDir.clone();
|
||||
updateStatus.append("update.status");
|
||||
} catch (ex) {
|
||||
}
|
||||
|
||||
if (updateStatus == undefined || !updateStatus.exists()) {
|
||||
updateDir = dirService.get("XCurProcD", Ci.nsIFile);
|
||||
updateDir.append("updates");
|
||||
updateDir.append("0");
|
||||
|
||||
updateStatus = updateDir.clone();
|
||||
updateStatus.append("update.status");
|
||||
}
|
||||
|
||||
var foStream = Cc["@mozilla.org/network/file-output-stream;1"].
|
||||
createInstance(Ci.nsIFileOutputStream);
|
||||
var status = "failed: 6\n";
|
||||
foStream.init(updateStatus, 0x02 | 0x08 | 0x20, -1, 0);
|
||||
foStream.write(status, status.length);
|
||||
foStream.close();
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets all the needed external DTD urls as an array
|
||||
*
|
||||
* @returns Array of external DTD urls
|
||||
* @type [string]
|
||||
*/
|
||||
getDtds : function softwareUpdate_getDtds() {
|
||||
var dtds = ["chrome://mozapps/locale/update/history.dtd",
|
||||
"chrome://mozapps/locale/update/updates.dtd"]
|
||||
return dtds;
|
||||
},
|
||||
|
||||
/**
|
||||
* Retrieve an UI element based on the given spec
|
||||
*
|
||||
* @param {object} spec
|
||||
* Information of the UI element which should be retrieved
|
||||
* type: General type information
|
||||
* subtype: Specific element or property
|
||||
* value: Value of the element or property
|
||||
* @returns Element which has been created
|
||||
* @type {ElemBase}
|
||||
*/
|
||||
getElement : function softwareUpdate_getElement(spec) {
|
||||
var elem = null;
|
||||
|
||||
switch(spec.type) {
|
||||
/**
|
||||
* subtype: subtype to match
|
||||
* value: value to match
|
||||
*/
|
||||
case "button":
|
||||
elem = new elementslib.Lookup(this._controller.window.document,
|
||||
WIZARD_BUTTONS_BOX + WIZARD_BUTTON[spec.subtype]);
|
||||
break;
|
||||
case "wizard":
|
||||
elem = new elementslib.Lookup(this._controller.window.document, WIZARD);
|
||||
break;
|
||||
case "wizard_page":
|
||||
elem = new elementslib.Lookup(this._controller.window.document, WIZARD_DECK +
|
||||
'/id(' + spec.subtype + ')');
|
||||
break;
|
||||
case "download_progress":
|
||||
elem = new elementslib.ID(this._controller.window.document, "downloadProgress");
|
||||
break;
|
||||
default:
|
||||
throw new Error(arguments.callee.name + ": Unknown element type - " + spec.type);
|
||||
}
|
||||
|
||||
return elem;
|
||||
},
|
||||
|
||||
/**
|
||||
* Open software update dialog
|
||||
*
|
||||
* @param {MozMillController} browserController
|
||||
* Mozmill controller of the browser window
|
||||
*/
|
||||
openDialog: function softwareUpdate_openDialog(browserController) {
|
||||
// XXX: After Firefox 4 has been released and we do not have to test any
|
||||
// beta release anymore uncomment out the following code
|
||||
|
||||
// With version >= 4.0b7pre the update dialog is reachable from within the
|
||||
// about window now.
|
||||
var appVersion = utils.appInfo.version;
|
||||
|
||||
if (this._vc.compare(appVersion, "4.0b7pre") >= 0) {
|
||||
// XXX: We can't open the about window, otherwise a parallel download of
|
||||
// the update will let us fallback to a complete one all the time
|
||||
|
||||
// Open the about window and check the update button
|
||||
//var aboutItem = new elementslib.Elem(browserController.menus.helpMenu.aboutName);
|
||||
//browserController.click(aboutItem);
|
||||
//
|
||||
//utils.handleWindow("type", "Browser:About", function(controller) {
|
||||
// // XXX: Bug 599290 - Check for updates has been completely relocated
|
||||
// // into the about window. We can't check the in-about ui yet.
|
||||
// var updateButton = new elementslib.ID(controller.window.document,
|
||||
// "checkForUpdatesButton");
|
||||
// //controller.click(updateButton);
|
||||
// controller.waitForElement(updateButton, gTimeout);
|
||||
//});
|
||||
|
||||
// For now just call the old ui until we have support for the about window.
|
||||
var updatePrompt = Cc["@mozilla.org/updates/update-prompt;1"].
|
||||
createInstance(Ci.nsIUpdatePrompt);
|
||||
updatePrompt.checkForUpdates();
|
||||
} else {
|
||||
// For builds <4.0b7pre
|
||||
updateItem = new elementslib.Elem(browserController.menus.helpMenu.checkForUpdates);
|
||||
browserController.click(updateItem);
|
||||
}
|
||||
|
||||
this.waitForDialogOpen(browserController);
|
||||
},
|
||||
|
||||
/**
|
||||
* Wait that check for updates has been finished
|
||||
* @param {number} timeout
|
||||
*/
|
||||
waitForCheckFinished : function softwareUpdate_waitForCheckFinished(timeout) {
|
||||
timeout = timeout ? timeout : gTimeoutUpdateCheck;
|
||||
|
||||
this._controller.waitFor(function() {
|
||||
return this.currentPage != WIZARD_PAGES.checking;
|
||||
}, "Check for updates has been completed.", timeout, null, this);
|
||||
},
|
||||
|
||||
/**
|
||||
* Wait for the software update dialog
|
||||
*
|
||||
* @param {MozMillController} browserController
|
||||
* Mozmill controller of the browser window
|
||||
*/
|
||||
waitForDialogOpen : function softwareUpdate_waitForDialogOpen(browserController) {
|
||||
this._controller = utils.handleWindow("type", "Update:Wizard",
|
||||
undefined, false);
|
||||
this._wizard = this.getElement({type: "wizard"});
|
||||
|
||||
this._controller.waitFor(function () {
|
||||
return this.currentPage !== WIZARD_PAGES.dummy;
|
||||
}, "Dummy wizard page has been made invisible - got " + this.currentPage,
|
||||
undefined, undefined, this);
|
||||
|
||||
this._controller.window.focus();
|
||||
},
|
||||
|
||||
/**
|
||||
* Wait until the download has been finished
|
||||
*
|
||||
* @param {number} timeout
|
||||
* Timeout the download has to stop
|
||||
*/
|
||||
waitforDownloadFinished: function softwareUpdate_waitForDownloadFinished(timeout) {
|
||||
timeout = timeout ? timeout : gTimeoutUpdateDownload;
|
||||
|
||||
var progress = this.getElement({type: "download_progress"});
|
||||
this._controller.waitFor(function () {
|
||||
return progress.getNode().value === '100';
|
||||
}, "Update has been finished downloading.", timeout);
|
||||
|
||||
this.waitForWizardPage(WIZARD_PAGES.finished);
|
||||
},
|
||||
|
||||
/**
|
||||
* Waits for the given page of the update dialog wizard
|
||||
*/
|
||||
waitForWizardPage : function softwareUpdate_waitForWizardPage(step) {
|
||||
this._controller.waitFor(function () {
|
||||
return this.currentPage === step;
|
||||
}, "New wizard page has been selected - got " + this.currentPage +
|
||||
", expected " + step, undefined, undefined, this);
|
||||
}
|
||||
}
|
||||
|
||||
// Export of variables
|
||||
exports.WIZARD_PAGES = WIZARD_PAGES;
|
||||
|
||||
// Export of classes
|
||||
exports.softwareUpdate = softwareUpdate;
|
||||
Reference in New Issue
Block a user