Merge mozilla-central into tracemonkey.

This commit is contained in:
Chris Leary 2011-01-04 10:51:14 -08:00
Родитель c61d1351d6 8d23ead26d
Коммит 09bf0c0c2d
264 изменённых файлов: 5402 добавлений и 1690 удалений

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

@ -152,7 +152,7 @@ var TestPilotMenuUtils;
* whether they opened with Firefox on startup or were opened later. */
TestPilotWindowHandlers.setUpToolbarFeedbackButton();
if (TestPilotSetup.startupComplete) {
if (TestPilotSetup && TestPilotSetup.startupComplete) {
TestPilotSetup.onWindowLoad(window);
} else {
let observerSvc = Cc["@mozilla.org/observer-service;1"]

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

@ -171,6 +171,34 @@
task.changeStatus(newStatus, false);
}
function showIndexFileDropdown() {
var prefService = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
var prefName = "extensions.testpilot.indexFileName";
var selector = document.getElementById("index-file-selector");
if (prefService.getCharPref(prefName) == "index.json") {
selector.selectedIndex = 0;
} else {
selector.selectedIndex = 1;
}
}
function setSelectedIndexFile() {
var prefService = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
var prefName = "extensions.testpilot.indexFileName";
var selector = document.getElementById("index-file-selector");
var i = selector.selectedIndex;
prefService.setCharPref( prefName, selector.options[i].value );
// DELETE CACHED INDEX FILE
var file = Components.classes["@mozilla.org/file/directory_service;1"].
getService(Components.interfaces.nsIProperties).
get("ProfD", Components.interfaces.nsIFile);
file.append("TestPilotExperimentFiles");
file.append("index.json");
if (file.exists()) {
file.remove(false);
}
}
</script>
@ -180,7 +208,7 @@
</head>
<body onload="populateFileDropdown();showSelectedTaskStatus();">
<body onload="populateFileDropdown();showSelectedTaskStatus();showIndexFileDropdown();">
<fieldset>
<p><select id="task-selector" onchange="showSelectedTaskStatus();"></select> Current Status = <span id="show-status-span"></span>.
@ -208,6 +236,11 @@ or set it to
<button onclick="reloadAllExperiments();">Reload All Experiments</button>
<button onclick="remindMe();">Notify Me</button>
<button onclick="testJarStore();">Test Jar Store</button>
Index file:
<select id="index-file-selector" onchange="setSelectedIndexFile();">
<option value="index.json">index.json</option>
<option value="index-dev.json">index-dev.json</option>
</select>
</p>
</fieldset>
<p><span id="debug"></span></p>

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

@ -60,7 +60,7 @@ var stringBundle;
function uploadData() {
Components.utils.import("resource://testpilot/modules/setup.js");
let eid = parseInt(getUrlParam("eid"));
let eid = getUrlParam("eid");
let task = TestPilotSetup.getTaskById(eid);
// If always-submit-checkbox is checked, set the pref
@ -97,7 +97,7 @@ var stringBundle;
function deleteData() {
Components.utils.import("resource://testpilot/modules/setup.js");
Components.utils.import("resource://testpilot/modules/tasks.js");
let eid = parseInt(getUrlParam("eid"));
let eid = getUrlParam("eid");
let task = TestPilotSetup.getTaskById(eid);
task.dataStore.wipeAllData();
// reload the URL after wiping all data.
@ -150,7 +150,7 @@ var stringBundle;
const nsIFilePicker = Components.interfaces.nsIFilePicker;
let filePicker = Components.classes["@mozilla.org/filepicker;1"].
createInstance(nsIFilePicker);
let eid = parseInt(getUrlParam("eid"));
let eid = getUrlParam("eid");
let task = TestPilotSetup.getTaskById(eid);
filePicker.init(window, null, nsIFilePicker.modeSave);
@ -268,7 +268,7 @@ var stringBundle;
function onQuitPageLoad() {
Components.utils.import("resource://testpilot/modules/setup.js");
setStrings(PAGE_TYPE_QUIT);
let eid = parseInt(getUrlParam("eid"));
let eid = getUrlParam("eid");
let task = TestPilotSetup.getTaskById(eid);
let header = document.getElementById("about-quit-title");
header.innerHTML =
@ -285,7 +285,7 @@ var stringBundle;
function quitExperiment() {
Components.utils.import("resource://testpilot/modules/setup.js");
Components.utils.import("resource://testpilot/modules/tasks.js");
let eid = parseInt(getUrlParam("eid"));
let eid = getUrlParam("eid");
let reason = document.getElementById("reason-for-quit").value;
let task = TestPilotSetup.getTaskById(eid);
task.optOut(reason, function(success) {
@ -306,7 +306,7 @@ var stringBundle;
function updateRecurSettings() {
Components.utils.import("resource://testpilot/modules/setup.js");
let eid = parseInt(getUrlParam("eid"));
let eid = getUrlParam("eid");
let experiment = TestPilotSetup.getTaskById(eid);
let recurSelector = document.getElementById("recur-selector");
let newValue = recurSelector.options[recurSelector.selectedIndex].value;
@ -367,9 +367,7 @@ var stringBundle;
var contentDiv = document.getElementById("experiment-specific-text");
var dataPrivacyDiv = document.getElementById("data-privacy-text");
// Get experimentID from the GET args of page
// TODO no reason actually to do parseInt here -- all it accomplishes
// is preventing us from using non-numeric study IDs.
var eid = parseInt(getUrlParam("eid"));
var eid = getUrlParam("eid");
var experiment = TestPilotSetup.getTaskById(eid);
if (!experiment) {
// Possible that experiments aren't done loading yet. Try again in

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

@ -1,3 +1,40 @@
/* ***** 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 Test Pilot.
*
* The Initial Developer of the Original Code is Mozilla.
* Portions created by the Initial Developer are Copyright (C) 2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Jono X <jono@mozilla.com>
* Raymond Lee <raymond@appcoast.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 ***** */
const MULTIPLE_CHOICE = 0;
const CHECK_BOXES_WITH_FREE_ENTRY = 1;
const SCALE = 2;
@ -58,9 +95,16 @@ function onBuiltinSurveyLoad() {
}
function drawSurveyForm(task, contentDiv) {
let oldAnswers = task.oldAnswers;
let surveyQuestions = task.surveyQuestions;
/* Fill form fields with old survey answers if available --
* but not if the survey version has changed since you stored them!!
* (bug 576482) */
let oldAnswers = null;
if (task.oldAnswers && (task.version == task.oldAnswers["version_number"])) {
oldAnswers = task.oldAnswers["answers"];
}
let submitButton = document.getElementById("survey-submit");
submitButton.setAttribute("style", "");
let changeButton = document.getElementById("change-answers");

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

@ -185,7 +185,7 @@ exports.RemoteExperimentLoader.prototype = {
} else {
this._fileGetter = downloadFile;
}
this._logger.trace("About to instantiate preferences store.");
this._logger.trace("About to instantiate jar store.");
this._jarStore = new JarStore();
this._experimentFileNames = [];
let self = this;
@ -324,11 +324,17 @@ exports.RemoteExperimentLoader.prototype = {
// TODO a bad thing that can go wrong: If we have a net connection but the index file
// has not changed, we currently don't try to download anything...
// The logic is bad because executeCachedIndexFile is called in two different
// cases: the one with no network, and the one with network but unchanged file.
// Another bad thing: If there's a jar download that's corrupt or unreadable or has
// the wrong permissions or something, we need to kill it and download a new one.
// the wrong permissions or something, we need to kill it and download a new one.
// Should also try to download a new jar if any required modules are missing
// (Which is currently the case!)
// WTF every jar file I'm downloading appears as 0 bytes with __x__x___ permissions!
// (module "about_firefox.js" is not found; there is no about_firefox.jar on disk,
// indicating it didn't download, and we're not trying again because index-dev is
// unmodified. Hmmm.)
_cachedIndexNsiFile: null,
get cachedIndexNsiFile() {

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

@ -120,6 +120,10 @@ var TestPilotTask = {
return this._id;
},
get version() {
return this._versionNumber;
},
get taskType() {
return null;
},
@ -248,15 +252,16 @@ var TestPilotTask = {
}
};
function TestPilotExperiment(expInfo, dataStore, handlers, webContent) {
function TestPilotExperiment(expInfo, dataStore, handlers, webContent, dateOverrideFunc) {
// All four of these are objects defined in the remote experiment file
this._init(expInfo, dataStore, handlers, webContent);
this._init(expInfo, dataStore, handlers, webContent, dateOverrideFunc);
}
TestPilotExperiment.prototype = {
_init: function TestPilotExperiment__init(expInfo,
dataStore,
handlers,
webContent) {
webContent,
dateOverrideFunc) {
/* expInfo is a dictionary defined in the remote experiment code, which
* should have the following properties:
* startDate (string representation of date)
@ -270,6 +275,14 @@ TestPilotExperiment.prototype = {
* recursAutomatically (boolean)
* recurrenceInterval (number of days)
* versionNumber (int) */
// dateOverrideFunc: For unit testing. Optional. If provided, will be called
// instead of Date.now() for determining the current time.
if (dateOverrideFunc) {
this._now = dateOverrideFunc;
} else {
this._now = Date.now;
}
this._taskInit(expInfo.testId, expInfo.testName, expInfo.testInfoUrl,
expInfo.summary, expInfo.thumbnail);
this._webContent = webContent;
@ -293,8 +306,8 @@ TestPilotExperiment.prototype = {
this._startDate = Date.parse(expInfo.startDate);
Application.prefs.setValue(prefName, expInfo.startDate);
} else {
this._startDate = Date.now();
Application.prefs.setValue(prefName, (new Date()).toString());
this._startDate = this._now();
Application.prefs.setValue(prefName, (new Date(this._startDate)).toString());
}
}
@ -580,7 +593,7 @@ TestPilotExperiment.prototype = {
checkDate: function TestPilotExperiment_checkDate() {
// This method handles all date-related status changes and should be
// called periodically.
let currentDate = Date.now();
let currentDate = this._now();
// Reset automatically recurring tests:
if (this._recursAutomatically &&
@ -774,7 +787,7 @@ TestPilotExperiment.prototype = {
self._uploadRetryTimer.cancel(); // Stop retrying - it worked!
}
self.changeStatus(TaskConstants.STATUS_SUBMITTED);
self._dateForDataDeletion = Date.now() + TIME_FOR_DATA_DELETION;
self._dateForDataDeletion = self._now() + TIME_FOR_DATA_DELETION;
self._expirationDateForDataSubmission = null;
callback(true);
} else {
@ -919,8 +932,7 @@ TestPilotBuiltinSurvey.prototype = {
return null;
} else {
this._logger.info("Trying to json.parse this: " + surveyResults);
let surveyJson = sanitizeJSONStrings( JSON.parse(surveyResults) );
return surveyJson["answers"];
return sanitizeJSONStrings( JSON.parse(surveyResults) );
}
},

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

@ -55,7 +55,7 @@ body {
border-radius: 0.5em;
-webkit-border-radius: 0.5em;
background: rgba(220, 240, 247, 0.8) url('chrome://testpilot/skin/images/callout.png') no-repeat top center;
//display: inline;
/* display: inline; */
}
#container {
@ -124,7 +124,7 @@ body {
rgba(255, 255, 255, 1) 0 1px,
rgba(133, 153, 166, 0.3) 0px 1px 8.5px;
background-color: #e7eaec;
//display: inline;
/* display: inline; */
}
.home_button {
@ -143,7 +143,7 @@ body {
rgba(255, 255, 255, 1) 0 1px,
rgba(133, 153, 166, 0.3) 0px 1px 8.5px;
background-color: #e7eaec;
//display: inline;
/* display: inline; */
}
.callout {
@ -158,7 +158,7 @@ body {
inset rgba(185, 221, 234, 0.2) 0 -10px 8.5px,
inset rgba(185, 221, 234, 1) 0 0px 1px,
inset rgba(255, 255, 255, 0.2) 0 10px 8.5px;
//display: inline;
/* display: inline; */
}
#data-privacy-text {
@ -169,7 +169,7 @@ body {
.home_callout {
font-size: 16px;
vertical-align: middle;
width: 280px;
/* width: 280px;*/
padding: 8px 24px;
margin: 8px auto;
color: rgba(0, 0, 0, 0.8);
@ -180,7 +180,7 @@ body {
inset rgba(185, 221, 234, 0.2) 0 -10px 8.5px,
inset rgba(185, 221, 234, 1) 0 0px 1px,
inset rgba(255, 255, 255, 0.2) 0 10px 8.5px;
//display: inline;
/* display: inline; */
}
.home_callout_continue {
@ -197,7 +197,7 @@ body {
inset rgba(185, 221, 234, 0.2) 0 -10px 8.5px,
inset rgba(185, 221, 234, 1) 0 0px 1px,
inset rgba(255, 255, 255, 0.2) 0 10px 8.5px;
//display: inline;
/* display: inline; */
}
.home_callout_continue a {color: #6c9735; text-decoration: none;}

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

@ -1,7 +1,3 @@
#feedback-menu-button {
-moz-appearance: button;
}
#pilot-notification-popup {
-moz-appearance: none;
background-color: Menu;

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

@ -1,5 +1,7 @@
EXPORTED_SYMBOLS = ["runAllTests"];
var Cu = Components.utils;
var Cc = Components.classes;
var Ci = Components.interfaces;
var testsRun = 0;
var testsPassed = 0;
@ -314,6 +316,221 @@ function testRemoteLoaderIndexCache() {
cheapAssertEqual(remoteLoader._loadCachedIndexFile(), data);
}
function StubDataStore(fileName, tableName, columns) {
}
StubDataStore.prototype = {
storeEvent: function(uiEvent, callback) {
callback(true);
},
getJSONRows: function(callback) {
callback([]);
},
getAllDataAsJSON: function(useDisplayValues, callback) {
callback([]);
},
wipeAllData: function(callback) {
callback(true);
},
nukeTable: function() {
},
haveData: function(callback) {
callback(true);
},
getHumanReadableColumnNames: function() {
},
getPropertyNames: function() {
}
};
function StubWebContent() {
}
StubWebContent.prototype = {
inProgressHtml: "",
completedHtml: "",
upcomingHtml: "",
canceledHtml: "",
remainDataHtml: "",
dataExpiredHtml: "",
deletedRemainDataHtml: "",
inProgressDataPrivacyHtml: "",
completedDataPrivacyHtml: "",
canceledDataPrivacyHtml: "",
dataExpiredDataPrivacyHtml: "",
remainDataPrivacyHtml: "",
deletedRemainDataPrivacyHtml: "",
onPageLoad: function(experiment, document, graphUtils) {
}
};
function StubHandlers() {
}
StubHandlers.prototype = {
onNewWindow: function(window) {
},
onWindowClosed: function(window) {
},
onAppStartup: function() {
},
onAppShutdown: function() {
},
onExperimentStartup: function(store) {
},
onExperimentShutdown: function() {
},
onEnterPrivateBrowsing: function() {
},
onExitPrivateBrowsing: function() {
},
uninstallAll: function() {
}
};
function testRecurringStudyStateChange() {
Cu.import("resource://testpilot/modules/tasks.js");
let expInfo = {
startDate: null,
duration: 7,
testName: "Unit Test Recurring Study",
testId: "unit_test_recur_study",
testInfoUrl: "https://testpilot.mozillalabs.com/",
summary: "Be sure to wipe all prefs and the store in the setup/teardown",
thumbnail: "",
optInRequired: false,
recursAutomatically: true,
recurrenceInterval: 30,
versionNumber: 1
};
dump("Looking for prefs to delete...\n");
let prefService = Cc["@mozilla.org/preferences-service;1"]
.getService(Ci.nsIPrefService)
.QueryInterface(Ci.nsIPrefBranch2);
let prefStem = "extensions.testpilot";
let prefNames = prefService.getChildList(prefStem);
for each (let prefName in prefNames) {
if (prefName.indexOf("unit_test_recur_study") != -1) {
dump("Clearing pref " + prefName + "\n");
prefService.clearUserPref(prefName);
}
}
const START_DATE = 1292629441000;
let stubDate = START_DATE;
let stubDateFunction = function() {
return stubDate;
};
let advanceDate = function(days) {
stubDate += days * 24 * 60 * 60 * 1000;
};
let dataStore = new StubDataStore();
let handlers = new StubHandlers();
let webContent = new StubWebContent();
let task = new TestPilotExperiment(expInfo, dataStore, handlers, webContent,
stubDateFunction);
// for this test, show popup on new study is set to true...
prefService.setBoolPref("extensions.testpilot.popup.showOnNewStudy", true);
// TODO another test with this turned off.
cheapAssertEqual(task.id, "unit_test_recur_study", "id should be id");
cheapAssertEqual(task.version, 1, "version should be version");
cheapAssertEqual(task.title, "Unit Test Recurring Study", "title should be title");
cheapAssertEqual(task.taskType, TaskConstants.TYPE_EXPERIMENT, "Should be experiment");
// Ensure that end date is 7 days past the start date
cheapAssertEqual(task.startDate, START_DATE, "Start date is wrong");
cheapAssertEqual(task.endDate, START_DATE + 7 * 24 * 60 * 60 * 1000, "End date is wrong");
cheapAssertEqual(task.status, TaskConstants.STATUS_NEW, "Status should be new");
// advance time a little and check date... b/c showOnNewStudy is true, it won't start:
advanceDate(1);
task.checkDate();
cheapAssertEqual(task.status, TaskConstants.STATUS_NEW, "Status should still be new");
// Now we fake the user action needed to advance it from NEW to STARTING:
task.changeStatus(TaskConstants.STATUS_STARTING);
cheapAssertEqual(task.status, TaskConstants.STATUS_STARTING, "Status should now be starting");
// when we check date again, it should advance from starting to in-progress:
task.checkDate();
cheapAssertEqual(task.status, TaskConstants.STATUS_IN_PROGRESS, "Status should be in progress");
// Go 7 days into the future
advanceDate(7);
task.checkDate();
cheapAssertEqual(task.status, TaskConstants.STATUS_FINISHED, "Status should be finished");
/* So how is the buggy bug happening? It seems like:
*
* - Data is posted successfully
* - Task status set to 6
* - (Reschedule is happening somewhere silently in here, which is screwing things
* up maybe?)
* - Reload everything
* - It's past its end date, so the task status gets switched to Finished.
*/
// TODO ideally figure out how to fake an upload - until then, just set status to 6.
task.changeStatus(TaskConstants.STATUS_SUBMITTED);
cheapAssertEqual(task.status, TaskConstants.STATUS_SUBMITTED, "Should be submitted.");
// Delete and recreate task, make sure it recovers its status and start/end
// dates correctly
task = null;
let task2 = new TestPilotExperiment(expInfo, dataStore, handlers, webContent,
stubDateFunction);
cheapAssertEqual(task2.status, TaskConstants.STATUS_SUBMITTED, "Status should be submitted!");
// It should remain submitted; it should have rescheduled itself to 30 days ahead.
cheapAssertEqual(task2.startDate, START_DATE + 30 * 24 * 60 * 60 * 1000,
"Start date is wrong");
cheapAssertEqual(task2.endDate, START_DATE + 37 * 24 * 60 * 60 * 1000,
"End date is wrong");
// test task._reschedule()?
// basically test everything that can happen in checkDate:
/* - reset of automatically recurring test (with NEVER_SUBMIT on and with it off) when
* we pass the (new) start date.
* - test that we jumped ahead to STARTING if optInRequired is false... and that
* we don't jump ahead to starting if it's true! And the popup.showOnNewStudy pref
* should have the same effect!!
*
* - When a test finishes (status is less than finished and current date passes end date)
* then it should switch to finish. If it recurs automatically, it should then
* reschedule; if study-specific recur pref is ALWAYS_SUBMIT (OR if global
* extensions.testpilot.alwaysSubmitData is true) it should then submit, but if it's
* NEVER_SUBMIT it should then cancel and wipe data. If none of these are true
* it should just reschedule but remain on status = finished.
*
* If it ends and doesn't recur automatically, then it should autosubmit if
* extensions.testpilot.alwaysSubmitData is true.
*
* At this point, a data deletion date and an expiration date for data submission
* should be set (unless dat was already wiped as a result of NEVER_SUBMIT).
*
*
* - Data expiration (this clause looks maybe wrong in the code - why is there another
* autosubmit command here?)
* If study is finished but not submitted and we pass expiration date for data
* submission, cancel and wipe data. (Expired should really be a status code!!)
* If study is submitted and we pass the date for data deletion, then wipe the data.
*
* */
// Trying to upload when status is already submitted or greater should be a no-op.
// Successful submit should advance us to SUBMITTED and generate/store a time for
// data deletion.
/* getWebContent and getDataPrivacyContent should give us back the right strings
* based on all the state. */
}
function runAllTests() {
testTheDataStore();
testFirefoxVersionCheck();
@ -321,10 +538,12 @@ function runAllTests() {
//testTheCuddlefishPreferencesFilesystem();
//testRemoteLoader();
testRemoteLoaderIndexCache();
testRecurringStudyStateChange();
dump("TESTING COMPLETE. " + testsPassed + " out of " + testsRun +
" tests passed.");
}
//exports.runAllTests = runAllTests;

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

@ -474,6 +474,10 @@ window[chromehidden~="toolbar"] toolbar:not(.toolbar-primary):not(.chromeclass-m
-moz-binding: url("chrome://browser/content/urlbarBindings.xml#geolocation-notification");
}
#addon-progress-notification {
-moz-binding: url("chrome://browser/content/urlbarBindings.xml#addon-progress-notification");
}
/* override hidden="true" for the status bar compatibility shim
in case it was persisted for the real status bar */
#status-bar {

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

@ -705,6 +705,23 @@ const gXPInstallObserver = {
PopupNotifications.show(browser, notificationID, messageString, anchorID,
action, null, options);
break;
case "addon-install-started":
function needsDownload(aInstall) {
return aInstall.state != AddonManager.STATE_DOWNLOADED;
}
// If all installs have already been downloaded then there is no need to
// show the download progress
if (!installInfo.installs.some(needsDownload))
return;
notificationID = "addon-progress";
messageString = gNavigatorBundle.getString("addonDownloading");
messageString = PluralForm.get(installInfo.installs.length, messageString);
options.installs = installInfo.installs;
options.contentWindow = browser.contentWindow;
options.sourceURI = browser.currentURI;
PopupNotifications.show(browser, notificationID, messageString, anchorID,
null, null, options);
break;
case "addon-install-failed":
// TODO This isn't terribly ideal for the multiple failure case
installInfo.installs.forEach(function(aInstall) {
@ -1384,6 +1401,7 @@ function prepareForStartup() {
function delayedStartup(isLoadingBlank, mustLoadSidebar) {
Services.obs.addObserver(gSessionHistoryObserver, "browser:purge-session-history", false);
Services.obs.addObserver(gXPInstallObserver, "addon-install-disabled", false);
Services.obs.addObserver(gXPInstallObserver, "addon-install-started", false);
Services.obs.addObserver(gXPInstallObserver, "addon-install-blocked", false);
Services.obs.addObserver(gXPInstallObserver, "addon-install-failed", false);
Services.obs.addObserver(gXPInstallObserver, "addon-install-complete", false);
@ -1626,6 +1644,7 @@ function BrowserShutdown()
Services.obs.removeObserver(gSessionHistoryObserver, "browser:purge-session-history");
Services.obs.removeObserver(gXPInstallObserver, "addon-install-disabled");
Services.obs.removeObserver(gXPInstallObserver, "addon-install-started");
Services.obs.removeObserver(gXPInstallObserver, "addon-install-blocked");
Services.obs.removeObserver(gXPInstallObserver, "addon-install-failed");
Services.obs.removeObserver(gXPInstallObserver, "addon-install-complete");

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

@ -25,6 +25,7 @@ function wait_for_notification(aCallback) {
PopupNotifications.panel.addEventListener("popupshown", function() {
PopupNotifications.panel.removeEventListener("popupshown", arguments.callee, false);
info("Saw notification");
is(PopupNotifications.panel.childNodes.length, 1, "Should be only one notification");
aCallback(PopupNotifications.panel);
}, false);
}
@ -112,6 +113,10 @@ function test_blocked_install() {
// Click on Allow
EventUtils.synthesizeMouse(notification.button, 20, 10, {});
// Notification should have changed to progress notification
notification = aPanel.childNodes[0];
is(notification.id, "addon-progress-notification", "Should have seen the progress notification");
// Wait for the install confirmation dialog
wait_for_install_dialog(function(aWindow) {
// Wait for the complete notification
@ -119,7 +124,7 @@ function test_blocked_install() {
let notification = aPanel.childNodes[0];
is(notification.id, "addon-install-complete-notification", "Should have seen the install complete");
is(notification.button.label, "Restart Now", "Should have seen the right button");
is(notification.getAttribute("label"),
is(notification.getAttribute("label"),
"XPI Test will be installed after you restart " + gApp + ".",
"Should have seen the right message");
@ -144,28 +149,34 @@ function test_blocked_install() {
},
function test_whitelisted_install() {
// Wait for the install confirmation dialog
wait_for_install_dialog(function(aWindow) {
// Wait for the complete notification
wait_for_notification(function(aPanel) {
let notification = aPanel.childNodes[0];
is(notification.id, "addon-install-complete-notification", "Should have seen the install complete");
is(notification.button.label, "Restart Now", "Should have seen the right button");
is(notification.getAttribute("label"),
"XPI Test will be installed after you restart " + gApp + ".",
"Should have seen the right message");
// Wait for the progress notification
wait_for_notification(function(aPanel) {
let notification = aPanel.childNodes[0];
is(notification.id, "addon-progress-notification", "Should have seen the progress notification");
AddonManager.getAllInstalls(function(aInstalls) {
is(aInstalls.length, 1, "Should be one pending install");
aInstalls[0].cancel();
// Wait for the install confirmation dialog
wait_for_install_dialog(function(aWindow) {
// Wait for the complete notification
wait_for_notification(function(aPanel) {
let notification = aPanel.childNodes[0];
is(notification.id, "addon-install-complete-notification", "Should have seen the install complete");
is(notification.button.label, "Restart Now", "Should have seen the right button");
is(notification.getAttribute("label"),
"XPI Test will be installed after you restart " + gApp + ".",
"Should have seen the right message");
gBrowser.removeTab(gBrowser.selectedTab);
Services.perms.remove("example.com", "install");
runNextTest();
AddonManager.getAllInstalls(function(aInstalls) {
is(aInstalls.length, 1, "Should be one pending install");
aInstalls[0].cancel();
gBrowser.removeTab(gBrowser.selectedTab);
Services.perms.remove("example.com", "install");
runNextTest();
});
});
});
aWindow.document.documentElement.acceptDialog();
aWindow.document.documentElement.acceptDialog();
});
});
var pm = Services.perms;
@ -179,18 +190,24 @@ function test_whitelisted_install() {
},
function test_failed_download() {
// Wait for the failed notification
// Wait for the progress notification
wait_for_notification(function(aPanel) {
let notification = aPanel.childNodes[0];
is(notification.id, "addon-install-failed-notification", "Should have seen the install fail");
is(notification.getAttribute("label"),
"The add-on could not be downloaded because of a connection failure " +
"on example.com.",
"Should have seen the right message");
is(notification.id, "addon-progress-notification", "Should have seen the progress notification");
gBrowser.removeTab(gBrowser.selectedTab);
Services.perms.remove("example.com", "install");
runNextTest();
// Wait for the failed notification
wait_for_notification(function(aPanel) {
let notification = aPanel.childNodes[0];
is(notification.id, "addon-install-failed-notification", "Should have seen the install fail");
is(notification.getAttribute("label"),
"The add-on could not be downloaded because of a connection failure " +
"on example.com.",
"Should have seen the right message");
gBrowser.removeTab(gBrowser.selectedTab);
Services.perms.remove("example.com", "install");
runNextTest();
});
});
var pm = Services.perms;
@ -204,18 +221,24 @@ function test_failed_download() {
},
function test_corrupt_file() {
// Wait for the failed notification
// Wait for the progress notification
wait_for_notification(function(aPanel) {
let notification = aPanel.childNodes[0];
is(notification.id, "addon-install-failed-notification", "Should have seen the install fail");
is(notification.getAttribute("label"),
"The add-on downloaded from example.com could not be installed " +
"because it appears to be corrupt.",
"Should have seen the right message");
is(notification.id, "addon-progress-notification", "Should have seen the progress notification");
gBrowser.removeTab(gBrowser.selectedTab);
Services.perms.remove("example.com", "install");
runNextTest();
// Wait for the failed notification
wait_for_notification(function(aPanel) {
let notification = aPanel.childNodes[0];
is(notification.id, "addon-install-failed-notification", "Should have seen the install fail");
is(notification.getAttribute("label"),
"The add-on downloaded from example.com could not be installed " +
"because it appears to be corrupt.",
"Should have seen the right message");
gBrowser.removeTab(gBrowser.selectedTab);
Services.perms.remove("example.com", "install");
runNextTest();
});
});
var pm = Services.perms;
@ -229,18 +252,24 @@ function test_corrupt_file() {
},
function test_incompatible() {
// Wait for the failed notification
// Wait for the progress notification
wait_for_notification(function(aPanel) {
let notification = aPanel.childNodes[0];
is(notification.id, "addon-install-failed-notification", "Should have seen the install fail");
is(notification.getAttribute("label"),
"XPI Test could not be installed because it is not compatible with " +
gApp + " " + gVersion + ".",
"Should have seen the right message");
is(notification.id, "addon-progress-notification", "Should have seen the progress notification");
gBrowser.removeTab(gBrowser.selectedTab);
Services.perms.remove("example.com", "install");
runNextTest();
// Wait for the failed notification
wait_for_notification(function(aPanel) {
let notification = aPanel.childNodes[0];
is(notification.id, "addon-install-failed-notification", "Should have seen the install fail");
is(notification.getAttribute("label"),
"XPI Test could not be installed because it is not compatible with " +
gApp + " " + gVersion + ".",
"Should have seen the right message");
gBrowser.removeTab(gBrowser.selectedTab);
Services.perms.remove("example.com", "install");
runNextTest();
});
});
var pm = Services.perms;
@ -254,31 +283,37 @@ function test_incompatible() {
},
function test_restartless() {
// Wait for the install confirmation dialog
wait_for_install_dialog(function(aWindow) {
// Wait for the complete notification
wait_for_notification(function(aPanel) {
let notification = aPanel.childNodes[0];
is(notification.id, "addon-install-complete-notification", "Should have seen the install complete");
is(notification.button.label, "Open Add-ons Manager", "Should have seen the right button");
is(notification.getAttribute("label"),
"XPI Test has been installed successfully.",
"Should have seen the right message");
// Wait for the progress notification
wait_for_notification(function(aPanel) {
let notification = aPanel.childNodes[0];
is(notification.id, "addon-progress-notification", "Should have seen the progress notification");
AddonManager.getAllInstalls(function(aInstalls) {
is(aInstalls.length, 0, "Should be no pending installs");
// Wait for the install confirmation dialog
wait_for_install_dialog(function(aWindow) {
// Wait for the complete notification
wait_for_notification(function(aPanel) {
let notification = aPanel.childNodes[0];
is(notification.id, "addon-install-complete-notification", "Should have seen the install complete");
is(notification.button.label, "Open Add-ons Manager", "Should have seen the right button");
is(notification.getAttribute("label"),
"XPI Test has been installed successfully.",
"Should have seen the right message");
AddonManager.getAddonByID("restartless-xpi@tests.mozilla.org", function(aAddon) {
aAddon.uninstall();
AddonManager.getAllInstalls(function(aInstalls) {
is(aInstalls.length, 0, "Should be no pending installs");
gBrowser.removeTab(gBrowser.selectedTab);
Services.perms.remove("example.com", "install");
runNextTest();
AddonManager.getAddonByID("restartless-xpi@tests.mozilla.org", function(aAddon) {
aAddon.uninstall();
gBrowser.removeTab(gBrowser.selectedTab);
Services.perms.remove("example.com", "install");
runNextTest();
});
});
});
});
aWindow.document.documentElement.acceptDialog();
aWindow.document.documentElement.acceptDialog();
});
});
var pm = Services.perms;
@ -292,32 +327,38 @@ function test_restartless() {
},
function test_multiple() {
// Wait for the install confirmation dialog
wait_for_install_dialog(function(aWindow) {
// Wait for the complete notification
wait_for_notification(function(aPanel) {
let notification = aPanel.childNodes[0];
is(notification.id, "addon-install-complete-notification", "Should have seen the install complete");
is(notification.button.label, "Restart Now", "Should have seen the right button");
is(notification.getAttribute("label"),
"2 add-ons will be installed after you restart " + gApp + ".",
"Should have seen the right message");
// Wait for the progress notification
wait_for_notification(function(aPanel) {
let notification = aPanel.childNodes[0];
is(notification.id, "addon-progress-notification", "Should have seen the progress notification");
AddonManager.getAllInstalls(function(aInstalls) {
is(aInstalls.length, 1, "Should be one pending install");
aInstalls[0].cancel();
// Wait for the install confirmation dialog
wait_for_install_dialog(function(aWindow) {
// Wait for the complete notification
wait_for_notification(function(aPanel) {
let notification = aPanel.childNodes[0];
is(notification.id, "addon-install-complete-notification", "Should have seen the install complete");
is(notification.button.label, "Restart Now", "Should have seen the right button");
is(notification.getAttribute("label"),
"2 add-ons will be installed after you restart " + gApp + ".",
"Should have seen the right message");
AddonManager.getAddonByID("restartless-xpi@tests.mozilla.org", function(aAddon) {
aAddon.uninstall();
AddonManager.getAllInstalls(function(aInstalls) {
is(aInstalls.length, 1, "Should be one pending install");
aInstalls[0].cancel();
gBrowser.removeTab(gBrowser.selectedTab);
Services.perms.remove("example.com", "install");
runNextTest();
AddonManager.getAddonByID("restartless-xpi@tests.mozilla.org", function(aAddon) {
aAddon.uninstall();
gBrowser.removeTab(gBrowser.selectedTab);
Services.perms.remove("example.com", "install");
runNextTest();
});
});
});
});
aWindow.document.documentElement.acceptDialog();
aWindow.document.documentElement.acceptDialog();
});
});
var pm = Services.perms;
@ -332,27 +373,33 @@ function test_multiple() {
},
function test_url() {
// Wait for the install confirmation dialog
wait_for_install_dialog(function(aWindow) {
// Wait for the complete notification
wait_for_notification(function(aPanel) {
let notification = aPanel.childNodes[0];
is(notification.id, "addon-install-complete-notification", "Should have seen the install complete");
is(notification.button.label, "Restart Now", "Should have seen the right button");
is(notification.getAttribute("label"),
"XPI Test will be installed after you restart " + gApp + ".",
"Should have seen the right message");
// Wait for the progress notification
wait_for_notification(function(aPanel) {
let notification = aPanel.childNodes[0];
is(notification.id, "addon-progress-notification", "Should have seen the progress notification");
AddonManager.getAllInstalls(function(aInstalls) {
is(aInstalls.length, 1, "Should be one pending install");
aInstalls[0].cancel();
// Wait for the install confirmation dialog
wait_for_install_dialog(function(aWindow) {
// Wait for the complete notification
wait_for_notification(function(aPanel) {
let notification = aPanel.childNodes[0];
is(notification.id, "addon-install-complete-notification", "Should have seen the install complete");
is(notification.button.label, "Restart Now", "Should have seen the right button");
is(notification.getAttribute("label"),
"XPI Test will be installed after you restart " + gApp + ".",
"Should have seen the right message");
gBrowser.removeTab(gBrowser.selectedTab);
runNextTest();
AddonManager.getAllInstalls(function(aInstalls) {
is(aInstalls.length, 1, "Should be one pending install");
aInstalls[0].cancel();
gBrowser.removeTab(gBrowser.selectedTab);
runNextTest();
});
});
});
aWindow.document.documentElement.acceptDialog();
aWindow.document.documentElement.acceptDialog();
});
});
gBrowser.selectedTab = gBrowser.addTab();
@ -391,17 +438,22 @@ function test_wronghost() {
gBrowser.removeEventListener("load", arguments.callee, true);
// Wait for the complete notification
// Wait for the progress notification
wait_for_notification(function(aPanel) {
let notification = aPanel.childNodes[0];
is(notification.id, "addon-install-failed-notification", "Should have seen the install fail");
is(notification.getAttribute("label"),
"The add-on downloaded from example.com could not be installed " +
"because it appears to be corrupt.",
"Should have seen the right message");
is(notification.id, "addon-progress-notification", "Should have seen the progress notification");
// Wait for the complete notification
wait_for_notification(function(aPanel) {
let notification = aPanel.childNodes[0];
is(notification.id, "addon-install-failed-notification", "Should have seen the install fail");
is(notification.getAttribute("label"),
"The add-on downloaded from example.com could not be installed " +
"because it appears to be corrupt.",
"Should have seen the right message");
gBrowser.removeTab(gBrowser.selectedTab);
runNextTest();
gBrowser.removeTab(gBrowser.selectedTab);
runNextTest();
});
});
gBrowser.loadURI(TESTROOT + "corrupt.xpi");
@ -410,44 +462,50 @@ function test_wronghost() {
},
function test_reload() {
// Wait for the install confirmation dialog
wait_for_install_dialog(function(aWindow) {
// Wait for the complete notification
wait_for_notification(function(aPanel) {
let notification = aPanel.childNodes[0];
is(notification.id, "addon-install-complete-notification", "Should have seen the install complete");
is(notification.button.label, "Restart Now", "Should have seen the right button");
is(notification.getAttribute("label"),
"XPI Test will be installed after you restart " + gApp + ".",
"Should have seen the right message");
// Wait for the progress notification
wait_for_notification(function(aPanel) {
let notification = aPanel.childNodes[0];
is(notification.id, "addon-progress-notification", "Should have seen the progress notification");
function test_fail() {
ok(false, "Reloading should not have hidden the notification");
}
// Wait for the install confirmation dialog
wait_for_install_dialog(function(aWindow) {
// Wait for the complete notification
wait_for_notification(function(aPanel) {
let notification = aPanel.childNodes[0];
is(notification.id, "addon-install-complete-notification", "Should have seen the install complete");
is(notification.button.label, "Restart Now", "Should have seen the right button");
is(notification.getAttribute("label"),
"XPI Test will be installed after you restart " + gApp + ".",
"Should have seen the right message");
PopupNotifications.panel.addEventListener("popuphiding", test_fail, false);
function test_fail() {
ok(false, "Reloading should not have hidden the notification");
}
gBrowser.addEventListener("load", function() {
if (gBrowser.currentURI.spec != TESTROOT2 + "enabled.html")
return;
PopupNotifications.panel.addEventListener("popuphiding", test_fail, false);
gBrowser.removeEventListener("load", arguments.callee, true);
gBrowser.addEventListener("load", function() {
if (gBrowser.currentURI.spec != TESTROOT2 + "enabled.html")
return;
PopupNotifications.panel.removeEventListener("popuphiding", test_fail, false);
gBrowser.removeEventListener("load", arguments.callee, true);
AddonManager.getAllInstalls(function(aInstalls) {
is(aInstalls.length, 1, "Should be one pending install");
aInstalls[0].cancel();
PopupNotifications.panel.removeEventListener("popuphiding", test_fail, false);
gBrowser.removeTab(gBrowser.selectedTab);
Services.perms.remove("example.com", "install");
runNextTest();
});
}, true);
gBrowser.loadURI(TESTROOT2 + "enabled.html");
AddonManager.getAllInstalls(function(aInstalls) {
is(aInstalls.length, 1, "Should be one pending install");
aInstalls[0].cancel();
gBrowser.removeTab(gBrowser.selectedTab);
Services.perms.remove("example.com", "install");
runNextTest();
});
}, true);
gBrowser.loadURI(TESTROOT2 + "enabled.html");
});
aWindow.document.documentElement.acceptDialog();
});
aWindow.document.documentElement.acceptDialog();
});
var pm = Services.perms;
@ -461,35 +519,41 @@ function test_reload() {
},
function test_theme() {
// Wait for the install confirmation dialog
wait_for_install_dialog(function(aWindow) {
// Wait for the complete notification
wait_for_notification(function(aPanel) {
let notification = aPanel.childNodes[0];
is(notification.id, "addon-install-complete-notification", "Should have seen the install complete");
is(notification.button.label, "Restart Now", "Should have seen the right button");
is(notification.getAttribute("label"),
"Theme Test will be installed after you restart " + gApp + ".",
"Should have seen the right message");
// Wait for the progress notification
wait_for_notification(function(aPanel) {
let notification = aPanel.childNodes[0];
is(notification.id, "addon-progress-notification", "Should have seen the progress notification");
gBrowser.removeTab(gBrowser.selectedTab);
Services.perms.remove("example.com", "install");
// Wait for the install confirmation dialog
wait_for_install_dialog(function(aWindow) {
// Wait for the complete notification
wait_for_notification(function(aPanel) {
let notification = aPanel.childNodes[0];
is(notification.id, "addon-install-complete-notification", "Should have seen the install complete");
is(notification.button.label, "Restart Now", "Should have seen the right button");
is(notification.getAttribute("label"),
"Theme Test will be installed after you restart " + gApp + ".",
"Should have seen the right message");
AddonManager.getAddonByID("{972ce4c6-7e08-4474-a285-3208198ce6fd}", function(aAddon) {
ok(aAddon.userDisabled, "Should be switching away from the default theme.");
// Undo the pending theme switch
aAddon.userDisabled = false;
gBrowser.removeTab(gBrowser.selectedTab);
Services.perms.remove("example.com", "install");
AddonManager.getAddonByID("theme-xpi@tests.mozilla.org", function(aAddon) {
isnot(aAddon, null, "Test theme will have been installed");
aAddon.uninstall();
AddonManager.getAddonByID("{972ce4c6-7e08-4474-a285-3208198ce6fd}", function(aAddon) {
ok(aAddon.userDisabled, "Should be switching away from the default theme.");
// Undo the pending theme switch
aAddon.userDisabled = false;
runNextTest();
AddonManager.getAddonByID("theme-xpi@tests.mozilla.org", function(aAddon) {
isnot(aAddon, null, "Test theme will have been installed");
aAddon.uninstall();
runNextTest();
});
});
});
});
aWindow.document.documentElement.acceptDialog();
aWindow.document.documentElement.acceptDialog();
});
});
var pm = Services.perms;
@ -544,49 +608,121 @@ function test_renotify_blocked() {
},
function test_renotify_installed() {
// Wait for the install confirmation dialog
wait_for_install_dialog(function(aWindow) {
// Wait for the complete notification
wait_for_notification(function(aPanel) {
let notification = aPanel.childNodes[0];
is(notification.id, "addon-install-complete-notification", "Should have seen the install complete");
// Wait for the progress notification
wait_for_notification(function(aPanel) {
let notification = aPanel.childNodes[0];
is(notification.id, "addon-progress-notification", "Should have seen the progress notification");
// Dismiss the notification
aPanel.addEventListener("popuphidden", function () {
aPanel.removeEventListener("popuphidden", arguments.callee, false);
// Wait for the install confirmation dialog
wait_for_install_dialog(function(aWindow) {
// Wait for the complete notification
wait_for_notification(function(aPanel) {
let notification = aPanel.childNodes[0];
is(notification.id, "addon-install-complete-notification", "Should have seen the install complete");
// Install another
executeSoon(function () {
// Wait for the install confirmation dialog
wait_for_install_dialog(function(aWindow) {
info("Timeouts after this probably mean bug 589954 regressed");
// Dismiss the notification
aPanel.addEventListener("popuphidden", function () {
aPanel.removeEventListener("popuphidden", arguments.callee, false);
// Wait for the complete notification
// Install another
executeSoon(function () {
// Wait for the progress notification
wait_for_notification(function(aPanel) {
let notification = aPanel.childNodes[0];
is(notification.id, "addon-install-complete-notification", "Should have seen the second install complete");
is(notification.id, "addon-progress-notification", "Should have seen the progress notification");
AddonManager.getAllInstalls(function(aInstalls) {
is(aInstalls.length, 1, "Should be one pending installs");
aInstalls[0].cancel();
// Wait for the install confirmation dialog
wait_for_install_dialog(function(aWindow) {
info("Timeouts after this probably mean bug 589954 regressed");
gBrowser.removeTab(gBrowser.selectedTab);
runNextTest();
// Wait for the complete notification
wait_for_notification(function(aPanel) {
let notification = aPanel.childNodes[0];
is(notification.id, "addon-install-complete-notification", "Should have seen the second install complete");
AddonManager.getAllInstalls(function(aInstalls) {
is(aInstalls.length, 1, "Should be one pending installs");
aInstalls[0].cancel();
gBrowser.removeTab(gBrowser.selectedTab);
Services.perms.remove("example.com", "install");
runNextTest();
});
});
aWindow.document.documentElement.acceptDialog();
});
});
aWindow.document.documentElement.acceptDialog();
gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers);
});
}, false);
gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers);
});
}, false);
// hide the panel (this simulates the user dismissing it)
aPanel.hidePopup();
// hide the panel (this simulates the user dismissing it)
aPanel.hidePopup();
});
aWindow.document.documentElement.acceptDialog();
});
});
aWindow.document.documentElement.acceptDialog();
var pm = Services.perms;
pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
var triggers = encodeURIComponent(JSON.stringify({
"XPI": "unsigned.xpi"
}));
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers);
},
function test_cancel_restart() {
// Wait for the progress notification
wait_for_notification(function(aPanel) {
let notification = aPanel.childNodes[0];
is(notification.id, "addon-progress-notification", "Should have seen the progress notification");
let button = document.getAnonymousElementByAttribute(notification, "anonid", "cancel");
// Cancel the download
EventUtils.synthesizeMouse(button, 2, 2, {});
// Downloads cannot be restarted synchronously, bug 611755
executeSoon(function() {
// Notification should have changed to cancelled
notification = aPanel.childNodes[0];
is(notification.id, "addon-install-cancelled-notification", "Should have seen the cancelled notification");
// Restart the download
EventUtils.synthesizeMouse(notification.button, 20, 10, {});
// Should be back to a progress notification
notification = aPanel.childNodes[0];
is(notification.id, "addon-progress-notification", "Should have seen the progress notification");
// Wait for the install confirmation dialog
wait_for_install_dialog(function(aWindow) {
// Wait for the complete notification
wait_for_notification(function(aPanel) {
let notification = aPanel.childNodes[0];
is(notification.id, "addon-install-complete-notification", "Should have seen the install complete");
is(notification.button.label, "Restart Now", "Should have seen the right button");
is(notification.getAttribute("label"),
"XPI Test will be installed after you restart " + gApp + ".",
"Should have seen the right message");
AddonManager.getAllInstalls(function(aInstalls) {
is(aInstalls.length, 1, "Should be one pending install");
aInstalls[0].cancel();
gBrowser.removeTab(gBrowser.selectedTab);
Services.perms.remove("example.com", "install");
runNextTest();
});
});
aWindow.document.documentElement.acceptDialog();
});
});
});
var pm = Services.perms;

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

@ -21,6 +21,7 @@
* Contributor(s):
* Gavin Sharp <gavin@gavinsharp.com>
* Sylvain Pasche <sylvain.pasche@gmail.com>
* Drew Willcoxon <adw@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
@ -92,13 +93,20 @@ function runNextTest() {
info("[Test #" + gTestIndex + "] popup shown");
nextTest.onShown(this);
});
// We allow multiple onHidden functions to be defined in an array. They're
// called in the order they appear.
let onHiddenArray = nextTest.onHidden instanceof Array ?
nextTest.onHidden :
[nextTest.onHidden];
doOnPopupEvent("popuphidden", function () {
info("[Test #" + gTestIndex + "] popup hidden");
nextTest.onHidden(this);
goNext();
});
let onHidden = onHiddenArray.shift();
info("[Test #" + gTestIndex + "] popup hidden (" + onHiddenArray.length + " hides remaining)");
onHidden.call(nextTest, this);
if (!onHiddenArray.length)
goNext();
}, onHiddenArray.length);
info("[Test #" + gTestIndex + "] added listeners; panel state: " + PopupNotifications.isPanelOpen);
}
@ -106,12 +114,16 @@ function runNextTest() {
nextTest.run();
}
function doOnPopupEvent(eventName, callback) {
function doOnPopupEvent(eventName, callback, numExpected) {
gActiveListeners[eventName] = function (event) {
if (event.target != PopupNotifications.panel)
return;
PopupNotifications.panel.removeEventListener(eventName, gActiveListeners[eventName], false);
delete gActiveListeners[eventName];
if (typeof(numExpected) === "number")
numExpected--;
if (!numExpected) {
PopupNotifications.panel.removeEventListener(eventName, gActiveListeners[eventName], false);
delete gActiveListeners[eventName];
}
callback.call(PopupNotifications.panel);
}
@ -335,11 +347,15 @@ var tests = [
"geo anchor shouldn't be visible");
dismissNotification(popup);
},
onHidden: function (popup) {
// Remove the first notification
this.firstNotification.remove();
ok(this.notifyObj.removedCallbackTriggered, "removed callback triggered");
}
onHidden: [
function (popup) {
// Remove the first notification
this.firstNotification.remove();
ok(this.notifyObj.removedCallbackTriggered, "removed callback triggered");
},
// The removal triggers another popuphidden event.
function (popup) {}
],
},
// Test optional params
{ // Test #10

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

@ -1100,6 +1100,218 @@
</implementation>
</binding>
<binding id="addon-progress-notification" extends="chrome://global/content/bindings/notification.xml#popup-notification">
<content align="start">
<xul:image class="popup-notification-icon"
xbl:inherits="popupid"/>
<xul:vbox flex="1">
<xul:description class="popup-notification-description addon-progress-description"
xbl:inherits="xbl:text=label"/>
<xul:spacer flex="1"/>
<xul:hbox align="center">
<xul:progressmeter anonid="progressmeter" flex="1" mode="undetermined" class="popup-progress-meter"/>
<xul:button anonid="cancel" class="popup-progress-cancel" oncommand="document.getBindingParent(this).cancel()"/>
</xul:hbox>
<xul:label anonid="progresstext" class="popup-progress-label"/>
<xul:hbox pack="end">
<xul:button anonid="button"
class="popup-notification-menubutton"
type="menu-button"
xbl:inherits="oncommand=buttoncommand,label=buttonlabel,accesskey=buttonaccesskey">
<xul:menupopup anonid="menupopup"
xbl:inherits="oncommand=menucommand">
<children/>
<xul:menuitem class="menuitem-iconic popup-notification-closeitem"
label="&closeNotificationItem.label;"
xbl:inherits="oncommand=closeitemcommand"/>
</xul:menupopup>
</xul:button>
</xul:hbox>
</xul:vbox>
</content>
<implementation>
<constructor><![CDATA[
this.cancelbtn.setAttribute("tooltiptext", gNavigatorBundle.getString("addonDownloadCancelTooltip"));
this.notification.options.installs.forEach(function(aInstall) {
aInstall.addListener(this);
}, this);
// Calling updateProgress can sometimes cause this notification to be
// removed in the middle of refreshing the notification panel which
// makes the panel get refreshed again. Just initialise to the
// undetermined state.
this.setProgress(0, -1);
]]></constructor>
<destructor><![CDATA[
this.destroy();
]]></destructor>
<field name="progressmeter" readonly="true">
document.getAnonymousElementByAttribute(this, "anonid", "progressmeter");
</field>
<field name="progresstext" readonly="true">
document.getAnonymousElementByAttribute(this, "anonid", "progresstext");
</field>
<field name="cancelbtn" readonly="true">
document.getAnonymousElementByAttribute(this, "anonid", "cancel");
</field>
<field name="DownloadUtils" readonly="true">
let utils = {};
Components.utils.import("resource://gre/modules/DownloadUtils.jsm", utils);
utils.DownloadUtils;
</field>
<method name="destroy">
<body><![CDATA[
this.notification.options.browser = null;
this.notification.options.contentWindow = null;
this.notification.options.sourceURI = null;
this.notification.options.installs.forEach(function(aInstall) {
aInstall.removeListener(this);
}, this);
]]></body>
</method>
<method name="setProgress">
<parameter name="aProgress"/>
<parameter name="aMaxProgress"/>
<body><![CDATA[
if (aMaxProgress == -1) {
this.progressmeter.mode = "undetermined";
}
else {
this.progressmeter.mode = "determined";
this.progressmeter.value = (aProgress * 100) / aMaxProgress;
}
let now = Date.now();
if (!this.notification.lastUpdate) {
this.notification.lastUpdate = now;
this.notification.lastProgress = aProgress;
return;
}
let delta = now - this.notification.lastUpdate;
if ((delta < 400) && (aProgress < aMaxProgress))
return;
delta /= 1000;
// This code is taken from nsDownloadManager.cpp
let speed = (aProgress - this.notification.lastProgress) / delta;
if (this.notification.speed)
speed = speed * 0.9 + this.notification.speed * 0.1;
this.notification.lastUpdate = now;
this.notification.lastProgress = aProgress;
this.notification.speed = speed;
let status = null;
[status, this.notification.last] = this.DownloadUtils.getDownloadStatus(aProgress, aMaxProgress, speed, this.notification.last);
this.progresstext.value = status;
]]></body>
</method>
<method name="cancel">
<body><![CDATA[
// Cache these as cancelling the installs will remove this
// notification and call destroy
let browser = this.notification.browser;
let contentWindow = this.notification.options.contentWindow;
let sourceURI = this.notification.options.sourceURI;
let installs = this.notification.options.installs;
installs.forEach(function(aInstall) {
try {
aInstall.cancel();
}
catch (e) {
// Cancel will throw if the download has already failed
}
}, this);
let anchorID = "addons-notification-icon";
let notificationID = "addon-install-cancelled";
let messageString = gNavigatorBundle.getString("addonDownloadCancelled");
messageString = PluralForm.get(installs.length, messageString);
let buttonText = gNavigatorBundle.getString("addonDownloadRestart");
buttonText = PluralForm.get(installs.length, buttonText);
let action = {
label: buttonText,
accessKey: gNavigatorBundle.getString("addonDownloadRestart.accessKey"),
callback: function() {
let weblistener = Cc["@mozilla.org/addons/web-install-listener;1"].
getService(Ci.amIWebInstallListener);
if (weblistener.onWebInstallRequested(contentWindow, sourceURI,
installs, installs.length)) {
installs.forEach(function(aInstall) {
aInstall.install();
});
}
}
};
PopupNotifications.show(browser, notificationID, messageString,
anchorID, action);
]]></body>
</method>
<method name="updateProgress">
<body><![CDATA[
let downloadingCount = 0;
let progress = 0;
let maxProgress = 0;
this.notification.options.installs.forEach(function(aInstall) {
if (aInstall.maxProgress == -1)
maxProgress = -1;
progress += aInstall.progress;
if (maxProgress >= 0)
maxProgress += aInstall.maxProgress;
if (aInstall.state < AddonManager.STATE_DOWNLOADED)
downloadingCount++;
});
if (downloadingCount == 0) {
this.destroy();
PopupNotifications.remove(this.notification);
}
else {
this.setProgress(progress, maxProgress);
}
]]></body>
</method>
<method name="onDownloadProgress">
<body><![CDATA[
this.updateProgress();
]]></body>
</method>
<method name="onDownloadFailed">
<body><![CDATA[
this.updateProgress();
]]></body>
</method>
<method name="onDownloadCancelled">
<body><![CDATA[
this.updateProgress();
]]></body>
</method>
<method name="onDownloadEnded">
<body><![CDATA[
this.updateProgress();
]]></body>
</method>
</implementation>
</binding>
<binding id="menuitem-tooltip" extends="chrome://global/content/bindings/menu.xml#menuitem">
<implementation>
<constructor><![CDATA[

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

@ -55,17 +55,6 @@ function test() {
let ss = Cc["@mozilla.org/browser/sessionstore;1"].
getService(Ci.nsISessionStore);
function waitForBrowserState(aState, aSetStateCallback) {
let tabsRestored = 0;
gBrowser.tabContainer.addEventListener("SSTabRestored", function() {
if (++tabsRestored == aState.windows[0].tabs.length) {
gBrowser.tabContainer.removeEventListener("SSTabRestored", arguments.callee, true);
executeSoon(aSetStateCallback);
}
}, true);
ss.setBrowserState(JSON.stringify(aState));
}
// This tests the following use case:
// User opens a new tab which gets focus. The user types something into the
// address bar, then crashes or quits.
@ -256,18 +245,20 @@ function test() {
event.initEvent("input", true, false);
gURLBar.dispatchEvent(event);
is(browser.userTypedValue, "example.org",
"userTypedValue was set when changing gURLBar.value");
is(browser.userTypedClear, 0,
"userTypedClear was not changed when changing gURLBar.value");
executeSoon(function() {
is(browser.userTypedValue, "example.org",
"userTypedValue was set when changing gURLBar.value");
is(browser.userTypedClear, 0,
"userTypedClear was not changed when changing gURLBar.value");
// Now make sure ss gets these values too
let newState = JSON.parse(ss.getBrowserState());
is(newState.windows[0].tabs[0].userTypedValue, "example.org",
"sessionstore got correct userTypedValue");
is(newState.windows[0].tabs[0].userTypedClear, 0,
"sessionstore got correct userTypedClear");
runNextTest();
// Now make sure ss gets these values too
let newState = JSON.parse(ss.getBrowserState());
is(newState.windows[0].tabs[0].userTypedValue, "example.org",
"sessionstore got correct userTypedValue");
is(newState.windows[0].tabs[0].userTypedClear, 0,
"sessionstore got correct userTypedClear");
runNextTest();
});
});
}
@ -303,9 +294,14 @@ function test() {
test_getBrowserState_lotsOfTabsOpening,
test_getBrowserState_userTypedValue, test_userTypedClearLoadURI];
let originalState = ss.getBrowserState();
let state = {
windows: [{
tabs: [{ entries: [{ url: "about:blank" }] }]
}]
};
function runNextTest() {
if (tests.length) {
tests.shift()();
waitForBrowserState(state, tests.shift());
} else {
ss.setBrowserState(originalState);
executeSoon(function () {

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

@ -432,7 +432,7 @@ nsMacShellService::OpenApplicationWithURI(nsILocalFile* aApplication, const nsAC
::CFRelease(uri);
return NS_ERROR_OUT_OF_MEMORY;
}
LSLaunchURLSpec launchSpec;
launchSpec.appURL = appURL;
launchSpec.itemURLs = uris;

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

@ -1,3 +1,3 @@
%filter substitution
%define primaryToolbarButtons #back-button, #forward-button, #reload-button, #stop-button, #home-button, #print-button, #downloads-button, #history-button, #bookmarks-button, #bookmarks-menu-button, #new-tab-button, #new-window-button, #cut-button, #copy-button, #paste-button, #fullscreen-button, #zoom-out-button, #zoom-in-button, #sync-button, #feed-button
%define primaryToolbarButtons #back-button, #forward-button, #reload-button, #stop-button, #home-button, #print-button, #downloads-button, #history-button, #bookmarks-button, #bookmarks-menu-button, #new-tab-button, #new-window-button, #cut-button, #copy-button, #paste-button, #fullscreen-button, #zoom-out-button, #zoom-in-button, #sync-button, #feed-button, #alltabs-button, #tabview-button

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

@ -1138,6 +1138,8 @@ toolbar[iconsize="small"] #feed-button {
}
.popup-notification-icon[popupid="xpinstall-disabled"],
.popup-notification-icon[popupid="addon-progress"],
.popup-notification-icon[popupid="addon-install-cancelled"],
.popup-notification-icon[popupid="addon-install-blocked"],
.popup-notification-icon[popupid="addon-install-failed"],
.popup-notification-icon[popupid="addon-install-complete"] {
@ -1146,6 +1148,29 @@ toolbar[iconsize="small"] #feed-button {
height: 32px;
}
.addon-progress-description {
width: 350px;
max-width: 350px;
}
.popup-progress-label,
.popup-progress-meter {
-moz-margin-start: 0;
-moz-margin-end: 0;
}
.popup-progress-cancel {
-moz-appearance: none;
background: transparent;
border: none;
padding: 0;
margin: 0;
-moz-margin-start: 5px;
min-height: 0;
min-width: 0;
list-style-image: url("moz-icon://stock/gtk-cancel?size=menu");
}
.popup-notification-icon[popupid="indexedDB-permissions-prompt"],
.popup-notification-icon[popupid="indexedDB-quota-prompt"] {
list-style-image: url(chrome://global/skin/icons/question-64.png);

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

@ -197,7 +197,6 @@ toolbarbutton.bookmark-item > menupopup {
width: 16px;
min-height: 16px;
max-height: 16px;
padding: 0;
}
.bookmark-item > .toolbarbutton-icon[label]:not([label=""]),
@ -323,12 +322,11 @@ toolbar:not([mode="icons"]) #restore-button {
min-width: 0;
}
.toolbarbutton-1 > .toolbarbutton-icon,
.toolbarbutton-1 > .toolbarbutton-menubutton-button > .toolbarbutton-icon,
#restore-button > .toolbarbutton-icon {
padding: 0;
height: 20px;
width: 20px;
.toolbarbutton-1:not(:-moz-any(@primaryToolbarButtons@)) > .toolbarbutton-icon,
.toolbarbutton-1 > .toolbarbutton-menubutton-button > .toolbarbutton-icon {
margin: 2px;
height: 16px;
width: 16px;
}
.toolbarbutton-1[disabled="true"] > .toolbarbutton-icon,
@ -1762,7 +1760,6 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
.tab-close-button > .toolbarbutton-icon {
-moz-margin-end: 0px !important;
padding: 0;
}
.tab-close-button {
@ -1849,12 +1846,6 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
padding: 0 1px;
}
.tabs-newtab-button > .toolbarbutton-icon,
:-moz-any(#TabsToolbar, #addon-bar) .toolbarbutton-1 > .toolbarbutton-icon,
:-moz-any(#TabsToolbar, #addon-bar) .toolbarbutton-1 > .toolbarbutton-menubutton-button > .toolbarbutton-icon {
padding: 0;
}
.tabbrowser-arrowscrollbox > .scrollbutton-up:not([disabled="true"]):hover,
.tabbrowser-arrowscrollbox > .scrollbutton-down:not([disabled="true"]):hover,
:-moz-any(#TabsToolbar, #addon-bar) .toolbarbutton-1:not([type="menu-button"]):not([disabled]):not([open]):hover,
@ -2065,6 +2056,8 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
}
.popup-notification-icon[popupid="xpinstall-disabled"],
.popup-notification-icon[popupid="addon-progress"],
.popup-notification-icon[popupid="addon-install-cancelled"],
.popup-notification-icon[popupid="addon-install-blocked"],
.popup-notification-icon[popupid="addon-install-failed"],
.popup-notification-icon[popupid="addon-install-complete"] {
@ -2073,6 +2066,37 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
height: 32px;
}
.addon-progress-description {
width: 350px;
max-width: 350px;
}
.popup-progress-label,
.popup-progress-meter {
-moz-margin-start: 0;
-moz-margin-end: 0;
}
.popup-progress-cancel {
-moz-appearance: none;
min-height: 16px;
min-width: 16px;
max-height: 16px;
max-width: 16px;
padding: 0;
margin: 0 1px 0 1px;
list-style-image: url(chrome://mozapps/skin/downloads/buttons.png);
-moz-image-region: rect(0px, 16px, 16px, 0px);
}
.popup-progress-cancel:hover {
-moz-image-region: rect(0px, 32px, 16px, 16px);
}
.popup-progress-cancel:active {
-moz-image-region: rect(0px, 48px, 16px, 32px);
}
#indexedDB-notification-icon {
list-style-image: url(chrome://global/skin/icons/question-16.png);
}

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

@ -111,7 +111,7 @@
}
#placesToolbar > toolbarbutton > .toolbarbutton-icon {
margin: 0 4px;
margin: 1px 4px;
}
#placesToolbar > toolbarbutton > .toolbarbutton-text {

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

@ -1645,14 +1645,6 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
-moz-transition: none;
}
.tabs-newtab-button > .toolbarbutton-icon,
#TabsToolbar > #new-tab-button > .toolbarbutton-icon,
#TabsToolbar > toolbarpaletteitem > #new-tab-button > .toolbarbutton-icon,
#alltabs-button > .toolbarbutton-icon {
width: auto;
height: auto;
}
.tabs-newtab-button > .toolbarbutton-icon {
margin-top: -1px;
margin-bottom: -1px;
@ -1882,6 +1874,8 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] {
}
.popup-notification-icon[popupid="xpinstall-disabled"],
.popup-notification-icon[popupid="addon-progress"],
.popup-notification-icon[popupid="addon-install-cancelled"],
.popup-notification-icon[popupid="addon-install-blocked"],
.popup-notification-icon[popupid="addon-install-failed"],
.popup-notification-icon[popupid="addon-install-complete"] {
@ -1890,6 +1884,37 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] {
height: 32px;
}
.addon-progress-description {
width: 350px;
max-width: 350px;
}
.popup-progress-label,
.popup-progress-meter {
-moz-margin-start: 0;
-moz-margin-end: 0;
}
.popup-progress-cancel {
-moz-appearance: none;
background: transparent;
border: none;
padding: 0;
margin: 0;
min-height: 0;
min-width: 0;
list-style-image: url(chrome://mozapps/skin/downloads/downloadButtons.png);
-moz-image-region: rect(0px, 32px, 16px, 16px);
}
.popup-progress-cancel:hover {
-moz-image-region: rect(16px, 32px, 32px, 16px);
}
.popup-progress-cancel:active {
-moz-image-region: rect(32px, 32px, 48px, 16px);
}
.popup-notification-icon[popupid="indexedDB-permissions-prompt"],
.popup-notification-icon[popupid="indexedDB-quota-prompt"] {
list-style-image: url(chrome://global/skin/icons/question-64.png);

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

@ -867,7 +867,7 @@ user_pref("camino.use_system_proxy_settings", false); // Camino-only, harmless t
# create certificate database for the profile
certificateStatus = self.fillCertificateDB(profileDir, certPath, utilityPath, xrePath)
if certificateStatus != 0:
self.log.info("TEST-UNEXPECTED FAIL | automation.py | Certificate integration failed")
self.log.info("TEST-UNEXPECTED-FAIL | automation.py | Certificate integration failed")
return certificateStatus
# start ssltunnel to provide https:// URLs capability
@ -926,9 +926,11 @@ user_pref("camino.use_system_proxy_settings", false); // Camino-only, harmless t
def installExtension(self, extensionSource, profileDir, extensionID):
if (not os.path.exists(extensionSource)):
self.log.info("INFO | automation.py | Cannot install extension no source at: %s", extensionSource)
return
if (not os.path.exists(profileDir)):
self.log.info("INFO | automation.py | Cannot install extension invalid profileDir at: %s", profileDir)
return
# See if we have an XPI or a directory
if (os.path.isfile(extensionSource)):

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

@ -2177,6 +2177,9 @@ nsScriptSecurityManager::GetFunctionObjectPrincipal(JSContext *cx,
nsresult *rv)
{
NS_PRECONDITION(rv, "Null out param");
*rv = NS_OK;
if (!JS_ObjectIsFunction(cx, obj))
{
// Protect against pseudo-functions (like SJOWs).
@ -2189,8 +2192,6 @@ nsScriptSecurityManager::GetFunctionObjectPrincipal(JSContext *cx,
JSFunction *fun = GET_FUNCTION_PRIVATE(cx, obj);
JSScript *script = JS_GetFunctionScript(cx, fun);
*rv = NS_OK;
if (!script)
{
// A native function: skip it in order to find its scripted caller.

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

@ -5354,10 +5354,7 @@ nsGenericElement::PostHandleEventForLinks(nsEventChainPostVisitor& aVisitor)
case NS_UI_ACTIVATE:
{
nsCOMPtr<nsIContent> targetContent;
aVisitor.mPresContext->EventStateManager()->
GetEventTargetContent(aVisitor.mEvent, getter_AddRefs(targetContent));
if (targetContent == this) {
if (aVisitor.mEvent->originalTarget == this) {
nsAutoString target;
GetLinkTarget(target);
nsContentUtils::TriggerLink(this, aVisitor.mPresContext, absURI, target,

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

@ -453,6 +453,8 @@ _TEST_FILES2 = \
test_treewalker_nextsibling.xml \
test_bug614058.html \
test_bug590771.html \
test_bug622117.html \
test_bug622246.html \
$(NULL)
# This test fails on the Mac for some reason

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

@ -0,0 +1,44 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=622117
-->
<head>
<title>Test for Bug 622117</title>
<script type="application/javascript" src="/MochiKit/packed.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=622117">Mozilla Bug 622117</a>
<p id="display">
<iframe id="testframe"
src="data:text/html,<a href='data:text/plain,PASS' onclick='throw 1'>Click me</a>">
</iframe>
</p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 622117 **/
SimpleTest.waitForExplicitFinish();
const PASSURL = "data:text/plain,PASS";
SimpleTest.waitForFocus(function() {
$("testframe").onload = function() {
is(this.contentDocument.documentElement.textContent, "PASS", "Should have loaded link");
SimpleTest.finish();
};
var win = $("testframe").contentWindow;
var a = win.document.getElementsByTagName("a")[0];
synthesizeMouseAtCenter(a, {}, win);
});
</script>
</pre>
</body>
</html>

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

@ -0,0 +1,44 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=622246
-->
<head>
<title>Test for Bug 622246</title>
<script type="application/javascript" src="/MochiKit/packed.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=622246">Mozilla Bug 622246</a>
<p id="display">
<iframe id="testframe"
src="data:text/html,<span onclick='this.parentNode.removeChild(this)'><a href='data:text/plain,PASS'>Click me</a></span>">
</iframe>
</p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 622246 **/
SimpleTest.waitForExplicitFinish();
const PASSURL = "data:text/plain,PASS";
SimpleTest.waitForFocus(function() {
$("testframe").onload = function() {
is(this.contentDocument.documentElement.textContent, "PASS", "Should have loaded link");
SimpleTest.finish();
};
var win = $("testframe").contentWindow;
var a = win.document.getElementsByTagName("a")[0];
synthesizeMouseAtCenter(a, {}, win);
});
</script>
</pre>
</body>
</html>

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

@ -57,6 +57,7 @@ function testWebSocket () {
}
ws.onclose = function(e) {
is(results.length, 0, "All the messages should have been processed!");
ok(e.wasClean, "Connection closed cleanly");
testWebSocket2();
}
ws.onerror = function(e) {
@ -83,6 +84,7 @@ function testWebSocket2() {
}
ws.onclose = function(e) {
is(messageCount, testCount, "Didn't receive all the messages!");
ok(e.wasClean, "Connection closed cleanly");
testWebSocket3();
}
ws.onerror = function(e) {
@ -113,6 +115,7 @@ function testWebSocket3() {
}
ws.onclose = function(e) {
is(messageCount, testCount, "Didn't receive all the messages!");
ok(e.wasClean, "Connection closed cleanly");
testWebSocket4();
}
ws.onerror = function(e) {
@ -132,6 +135,7 @@ function testWebSocket3() {
function testWebSocket4() {
ws = new WebSocket("ws://mochi.test:8888/tests/content/base/test/file_ws_basic_tests", "test");
// String length = (10,000 - 1) * 23 = 229,977 = almost 225 KiB.
var longString = new Array(10000).join("-huge websocket message");
ws.onopen = function(e) {
is(this, ws, "'this' should point to the WebSocket. (1)");
@ -139,7 +143,7 @@ function testWebSocket4() {
}
ws.onclose = function(e) {
is(this, ws, "'this' should point to the WebSocket. (2)");
//ok(e.wasClean, "Connection should have closed cleanly.");
ok(e.wasClean, "Connection closed cleanly");
testWebSocket5();
}
ws.onerror = function(e) {
@ -148,7 +152,9 @@ function testWebSocket4() {
}
ws.onmessage = function(e) {
is(this, ws, "'this' should point to the WebSocket. (3)");
is(e.data, longString, "Didn't get the huge message back!");
// Do not use |is(e.data, longString, "...");| that results in a _very_ long line.
is(e.data.length, longString.length, "Length of received message");
ok(e.data == longString, "Content of received message");
document.getElementById('log').textContent += "\nReceived the huge message";
this.close();
}
@ -160,7 +166,7 @@ function testWebSocket5() {
this.close();
}
ws.onclose = function(e) {
//ok(e.wasClean, "Connection should have closed cleanly.");
ok(e.wasClean, "Connection closed cleanly");
is(this.bufferedAmount, 0, "Shouldn't have anything buffered");
var msg = "some data";
this.send(msg);

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

@ -2980,7 +2980,8 @@ WebGLContext::ConvertImage(size_t width, size_t height, size_t srcStride, size_t
const PRUint8* src_end = src + height * srcStride;
PRUint8* dst_row = mPixelStoreFlipY ? dst + (height-1) * dstStride : dst;
ptrdiff_t dst_delta = mPixelStoreFlipY ? -dstStride : dstStride;
ptrdiff_t dstStrideSigned(dstStride);
ptrdiff_t dst_delta = mPixelStoreFlipY ? -dstStrideSigned : dstStrideSigned;
while(src_row != src_end) {
memcpy(dst_row, src_row, row_size);

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

@ -43,7 +43,7 @@
DUMMY(NS_NewCanvasRenderingContextWebGL, nsIDOMWebGLRenderingContext)
DOMCI_DATA(CanvasRenderingContextWebGL, void)
DOMCI_DATA(WebGLRenderingContext, void)
DOMCI_DATA(WebGLBuffer, void)
DOMCI_DATA(WebGLTexture, void)
DOMCI_DATA(WebGLProgram, void)
@ -51,3 +51,4 @@ DOMCI_DATA(WebGLShader, void)
DOMCI_DATA(WebGLFramebuffer, void)
DOMCI_DATA(WebGLRenderbuffer, void)
DOMCI_DATA(WebGLUniformLocation, void)
DOMCI_DATA(WebGLActiveInfo, void)

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

@ -301,10 +301,12 @@ void nsAudioStream::ShutdownLibrary()
{
}
nsIThread *
nsAudioStream::GetThread()
{
if (!mAudioPlaybackThread) {
NS_NewThread(getter_AddRefs(mAudioPlaybackThread));
}
return mAudioPlaybackThread;
}
@ -318,6 +320,23 @@ nsAudioStream* nsAudioStream::AllocateStream()
return new nsAudioStreamLocal();
}
class AsyncShutdownPlaybackThread : public nsRunnable
{
public:
AsyncShutdownPlaybackThread(nsIThread* aThread) : mThread(aThread) {}
NS_IMETHODIMP Run() { return mThread->Shutdown(); }
private:
nsCOMPtr<nsIThread> mThread;
};
nsAudioStream::~nsAudioStream()
{
if (mAudioPlaybackThread) {
nsCOMPtr<nsIRunnable> event = new AsyncShutdownPlaybackThread(mAudioPlaybackThread);
NS_DispatchToMainThread(event);
}
}
nsAudioStreamLocal::nsAudioStreamLocal() :
mVolume(1.0),
mAudioHandle(0),
@ -327,12 +346,6 @@ nsAudioStreamLocal::nsAudioStreamLocal() :
mPaused(PR_FALSE),
mInError(PR_FALSE)
{
#ifdef MOZ_IPC
// We only need this thread in the main process.
if (XRE_GetProcessType() == GeckoProcessType_Default) {
NS_NewThread(getter_AddRefs(mAudioPlaybackThread));
}
#endif
}
nsAudioStreamLocal::~nsAudioStreamLocal()

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

@ -54,6 +54,8 @@ public:
FORMAT_FLOAT32
};
virtual ~nsAudioStream();
// Initialize Audio Library. Some Audio backends require initializing the
// library before using it.
static void InitLibrary();
@ -64,7 +66,7 @@ public:
// Thread, usually for MOZ_IPC handling, that is shared between audio streams.
// This may return null in the child process
virtual nsIThread *GetThread();
nsIThread *GetThread();
// AllocateStream will return either a local stream or a remoted stream
// depending on where you call it from. If MOZ_IPC is enabled, and you

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

@ -61,7 +61,7 @@ var _fromByTestLists =
toComp: "40px"}),
],
lengthNoUnitsSVG: [
new AnimTestcaseFromBy("0", "50", { fromComp: "0px", // 0 acts like 0px
new AnimTestcaseFromBy("0", "50", { fromComp: "0",
midComp: "25",
toComp: "50"}),
new AnimTestcaseFromBy("30", "10", { fromComp: "30",
@ -69,9 +69,9 @@ var _fromByTestLists =
toComp: "40"}),
],
lengthPx: [
new AnimTestcaseFromBy("0", "8px", { fromComp: "0px", // 0 acts like 0px
midComp: "4px",
toComp: "8px"}),
new AnimTestcaseFromBy("0px", "8px", { fromComp: "0px",
midComp: "4px",
toComp: "8px"}),
new AnimTestcaseFromBy("1px", "10px", { midComp: "6px", toComp: "11px"}),
],
opacity: [

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

@ -117,21 +117,21 @@ var _fromToTestLists = {
toComp: "80px"}),
],
lengthNoUnitsSVG: [
new AnimTestcaseFromTo("0", "20", { fromComp: "0px", // 0 acts like 0px
new AnimTestcaseFromTo("0", "20", { fromComp: "0",
midComp: "10",
toComp: "20"}),
new AnimTestcaseFromTo("50", "0", { fromComp: "50",
midComp: "25",
toComp: "0px"}), // 0 acts like 0px
toComp: "0"}),
new AnimTestcaseFromTo("30", "80", { fromComp: "30",
midComp: "55",
toComp: "80"}),
],
lengthPx: [
new AnimTestcaseFromTo("0", "12px", { fromComp: "0px", // 0 acts like 0px
midComp: "6px"}),
new AnimTestcaseFromTo("16px", "0", { midComp: "8px",
toComp: "0px"}), // 0 acts like 0px
new AnimTestcaseFromTo("0px", "12px", { fromComp: "0px",
midComp: "6px"}),
new AnimTestcaseFromTo("16px", "0px", { midComp: "8px",
toComp: "0px"}),
new AnimTestcaseFromTo("10px", "20px", { midComp: "15px"}),
new AnimTestcaseFromTo("41px", "1px", { midComp: "21px"}),
],

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

@ -112,7 +112,7 @@ var _pacedTestLists =
new AnimTestcasePaced("2; 0; 4",
{ comp0: "2",
comp1_6: "1",
comp1_3: "0px", // 0 acts like 0px
comp1_3: "0",
comp2_3: "2",
comp1: "4"
}),
@ -125,8 +125,8 @@ var _pacedTestLists =
}),
],
lengthPx : [
new AnimTestcasePaced("0; 2px; 6px",
{ comp0: "0px", // 0 acts like 0px
new AnimTestcasePaced("0px; 2px; 6px",
{ comp0: "0px",
comp1_6: "1px",
comp1_3: "2px",
comp2_3: "4px",

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

@ -85,7 +85,7 @@ SVGAnimatedLengthList::ClearBaseValue(PRUint32 aAttrEnum)
DOMSVGAnimatedLengthList::GetDOMWrapperIfExists(this);
if (domWrapper) {
// We must send this notification *before* changing mBaseVal! (See above.)
domWrapper->InternalAnimValListWillChangeTo(SVGLengthList());
domWrapper->InternalBaseValListWillChangeTo(SVGLengthList());
}
mBaseVal.Clear();
// Caller notifies

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

@ -85,7 +85,7 @@ SVGAnimatedNumberList::ClearBaseValue(PRUint32 aAttrEnum)
DOMSVGAnimatedNumberList::GetDOMWrapperIfExists(this);
if (domWrapper) {
// We must send this notification *before* changing mBaseVal! (See above.)
domWrapper->InternalAnimValListWillChangeTo(SVGNumberList());
domWrapper->InternalBaseValListWillChangeTo(SVGNumberList());
}
mBaseVal.Clear();
// Caller notifies

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

@ -554,9 +554,9 @@ SVGPathData::GetMarkerPositioningData(nsTArray<nsSVGMark> *aMarks) const
case nsIDOMSVGPathSeg::PATHSEG_ARC_ABS:
case nsIDOMSVGPathSeg::PATHSEG_ARC_REL:
{
float rx = mData[i];
float ry = mData[i+1];
float angle = mData[i+2];
double rx = mData[i];
double ry = mData[i+1];
double angle = mData[i+2];
PRBool largeArcFlag = mData[i+3] != 0.0f;
PRBool sweepFlag = mData[i+4] != 0.0f;
if (segType == nsIDOMSVGPathSeg::PATHSEG_ARC_ABS) {
@ -595,46 +595,47 @@ SVGPathData::GetMarkerPositioningData(nsTArray<nsSVGMark> *aMarks) const
// F.6.5.1:
angle = angle * M_PI/180.0;
float x1p = cos(angle) * (segStart.x - segEnd.x) / 2.0
+ sin(angle) * (segStart.y - segEnd.y) / 2.0;
float y1p = -sin(angle) * (segStart.x - segEnd.x) / 2.0
+ cos(angle) *(segStart.y - segEnd.y) / 2.0;
double x1p = cos(angle) * (segStart.x - segEnd.x) / 2.0
+ sin(angle) * (segStart.y - segEnd.y) / 2.0;
double y1p = -sin(angle) * (segStart.x - segEnd.x) / 2.0
+ cos(angle) * (segStart.y - segEnd.y) / 2.0;
// This is the root in F.6.5.2 and the numerator under that root:
float root;
float numerator = rx*rx*ry*ry - rx*rx*y1p*y1p - ry*ry*x1p*x1p;
double root;
double numerator = rx*rx*ry*ry - rx*rx*y1p*y1p - ry*ry*x1p*x1p;
if (numerator < 0.0) {
// F.6.6 step 3 - |numerator < 0.0| is equivalent to the result of
// F.6.6.2 (lamedh) being greater than one. What we have here is radii
// that do not reach between segStart and segEnd, so we need to correct
// them.
float lamedh = 1.0 - numerator/(rx*rx*ry*ry); // equiv to eqn F.6.6.2
float s = sqrt(lamedh);
if (numerator >= 0.0) {
root = sqrt(numerator/(rx*rx*y1p*y1p + ry*ry*x1p*x1p));
if (largeArcFlag == sweepFlag)
root = -root;
} else {
// F.6.6 step 3 - |numerator < 0.0|. This is equivalent to the result
// of F.6.6.2 (lamedh) being greater than one. What we have here is
// ellipse radii that are too small for the ellipse to reach between
// segStart and segEnd. We scale the radii up uniformly so that the
// ellipse is just big enough to fit (i.e. to the point where there is
// exactly one solution).
double lamedh = 1.0 - numerator/(rx*rx*ry*ry); // equiv to eqn F.6.6.2
double s = sqrt(lamedh);
rx *= s; // F.6.6.3
ry *= s;
// rx and ry changed, so we have to recompute numerator
numerator = rx*rx*ry*ry - rx*rx*y1p*y1p - ry*ry*x1p*x1p;
NS_ABORT_IF_FALSE(numerator >= 0,
"F.6.6.3 should prevent this. Will sqrt(-num)!");
root = 0.0;
}
root = sqrt(numerator/(rx*rx*y1p*y1p + ry*ry*x1p*x1p));
if (largeArcFlag == sweepFlag)
root = -root;
float cxp = root * rx * y1p / ry; // F.6.5.2
float cyp = -root * ry * x1p / rx;
double cxp = root * rx * y1p / ry; // F.6.5.2
double cyp = -root * ry * x1p / rx;
float theta, delta;
theta = CalcVectorAngle(1.0, 0.0, (x1p-cxp)/rx, (y1p-cyp)/ry); // F.6.5.5
delta = CalcVectorAngle((x1p-cxp)/rx, (y1p-cyp)/ry,
(-x1p-cxp)/rx, (-y1p-cyp)/ry); // F.6.5.6
double theta, delta;
theta = CalcVectorAngle(1.0, 0.0, (x1p-cxp)/rx, (y1p-cyp)/ry); // F.6.5.5
delta = CalcVectorAngle((x1p-cxp)/rx, (y1p-cyp)/ry,
(-x1p-cxp)/rx, (-y1p-cyp)/ry); // F.6.5.6
if (!sweepFlag && delta > 0)
delta -= 2.0 * M_PI;
else if (sweepFlag && delta < 0)
delta += 2.0 * M_PI;
float tx1, ty1, tx2, ty2;
double tx1, ty1, tx2, ty2;
tx1 = -cos(angle)*rx*sin(theta) - sin(angle)*ry*cos(theta);
ty1 = -sin(angle)*rx*sin(theta) + cos(angle)*ry*cos(theta);
tx2 = -cos(angle)*rx*sin(theta+delta) - sin(angle)*ry*cos(theta+delta);

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

@ -2276,12 +2276,20 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_ENTRY(nsIDOMLocation)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(Navigator, nsIDOMNavigator)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMNavigator)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMNavigatorGeolocation)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMNavigatorDesktopNotification)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMClientInformation)
DOM_CLASSINFO_MAP_END
if (nsNavigator::HasDesktopNotificationSupport()) {
DOM_CLASSINFO_MAP_BEGIN(Navigator, nsIDOMNavigator)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMNavigator)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMNavigatorGeolocation)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMNavigatorDesktopNotification)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMClientInformation)
DOM_CLASSINFO_MAP_END
} else {
DOM_CLASSINFO_MAP_BEGIN(Navigator, nsIDOMNavigator)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMNavigator)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMNavigatorGeolocation)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMClientInformation)
DOM_CLASSINFO_MAP_END
}
DOM_CLASSINFO_MAP_BEGIN(Plugin, nsIDOMPlugin)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMPlugin)

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

@ -7966,7 +7966,7 @@ nsGlobalWindow::GetLocalStorage(nsIDOMStorage ** aLocalStorage)
}
NS_IMETHODIMP
nsGlobalWindow::GetMoz_indexedDB(nsIIDBFactory** _retval)
nsGlobalWindow::GetMozIndexedDB(nsIIDBFactory** _retval)
{
if (!mIndexedDB) {
mIndexedDB = indexedDB::IDBFactory::Create();
@ -10722,6 +10722,12 @@ nsNavigator::RefreshMIMEArray()
return rv;
}
bool
nsNavigator::HasDesktopNotificationSupport()
{
return nsContentUtils::GetBoolPref("notification.feature.enabled", PR_FALSE);
}
//*****************************************************************************
// nsNavigator::nsIDOMClientInformation
//*****************************************************************************

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

@ -1056,6 +1056,8 @@ public:
void LoadingNewDocument();
nsresult RefreshMIMEArray();
static bool HasDesktopNotificationSupport();
protected:
nsRefPtr<nsMimeTypeArray> mMimeTypes;
nsRefPtr<nsPluginArray> mPlugins;

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

@ -101,6 +101,7 @@ BROWSER_TEST_FILES = \
browser_permissionsPrompt.html \
browser_permissionsPromptAllow.js \
browser_permissionsPromptDeny.js \
browser_privateBrowsing.js \
browser_quotaPrompt.html \
browser_quotaPromptAllow.js \
browser_quotaPromptDeny.js \

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

@ -2,7 +2,7 @@
<html>
<head>
<script>
moz_indexedDB.open(parent.location).onsuccess = function(e) {
mozIndexedDB.open(parent.location).onsuccess = function(e) {
var db = e.result;
// This should never be called
db.onversionchange = function(e) {

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

@ -3,7 +3,7 @@
<head>
<script>
var res = {};
moz_indexedDB.open(parent.location).onsuccess = function(e) {
mozIndexedDB.open(parent.location).onsuccess = function(e) {
var db = e.result;
res.version = db.version;
res.storeCount = db.objectStoreNames.length;

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

@ -12,7 +12,7 @@
const name = window.location.pathname;
const description = "My Test Database";
let request = moz_indexedDB.open(name, description);
let request = mozIndexedDB.open(name, description);
request.onerror = grabEventAndContinueHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield;

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

@ -0,0 +1,71 @@
/**
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
const testPageURL = "http://mochi.test:8888/browser/" +
"dom/indexedDB/test/browser_permissionsPrompt.html";
const notificationID = "indexedDB-permissions-prompt";
const exceptionText = "5: A mutation operation was attempted on a database " +
"that did not allow mutations.";
function test()
{
waitForExplicitFinish();
// Avoids the actual prompt
setPermission(testPageURL, "indexedDB");
executeSoon(test2);
}
function test1()
{
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function () {
gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
setFinishedCallback(function(result, exception) {
ok(result instanceof Components.interfaces.nsIIDBDatabase,
"First database creation was successful");
ok(!exception, "No exception");
gBrowser.removeCurrentTab();
executeSoon(test2);
});
}, true);
content.location = testPageURL;
}
function test2()
{
let pb = Cc["@mozilla.org/privatebrowsing;1"].
getService(Ci.nsIPrivateBrowsingService);
pb.privateBrowsingEnabled = true;
executeSoon(test3);
}
function test3()
{
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function () {
gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
setFinishedCallback(function(result, exception) {
ok(!result, "No database");
is(exception, exceptionText, "Correct exception");
gBrowser.removeCurrentTab();
executeSoon(test4);
});
}, true);
content.location = testPageURL;
}
function test4()
{
let pb = Cc["@mozilla.org/privatebrowsing;1"].
getService(Ci.nsIPrivateBrowsingService);
pb.privateBrowsingEnabled = false;
executeSoon(finish);
}

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

@ -55,7 +55,7 @@
window.addEventListener("indexedDB-addMore", onAddMore, true);
window.addEventListener("indexedDB-done", onDone, true);
let request = moz_indexedDB.open(name, description);
let request = mozIndexedDB.open(name, description);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield;

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

@ -56,7 +56,7 @@
.add(uri, "indexedDB",
Components.interfaces.nsIPermissionManager.ALLOW_ACTION);
let request = moz_indexedDB.open(window.location.pathname);
let request = mozIndexedDB.open(window.location.pathname);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield;

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

@ -95,7 +95,7 @@
.add(uri, "indexedDB",
Components.interfaces.nsIPermissionManager.ALLOW_ACTION);
let request = moz_indexedDB.open(window.location.pathname);
let request = mozIndexedDB.open(window.location.pathname);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield;

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

@ -60,7 +60,7 @@
.add(uri, "indexedDB",
Components.interfaces.nsIPermissionManager.ALLOW_ACTION);
let request = moz_indexedDB.open(window.location.pathname);
let request = mozIndexedDB.open(window.location.pathname);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield;

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

@ -16,7 +16,7 @@
const name = window.location.pathname;
const description = "My Test Database";
let request = moz_indexedDB.open(name, description);
let request = mozIndexedDB.open(name, description);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield;

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

@ -16,7 +16,7 @@
const name = window.location.pathname;
const description = "My Test Database";
let request = moz_indexedDB.open(name, description);
let request = mozIndexedDB.open(name, description);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield;

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

@ -19,7 +19,7 @@
const description = "My Test Database";
const entryCount = 1000;
let request = moz_indexedDB.open(name, description);
let request = mozIndexedDB.open(name, description);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield;

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

@ -28,7 +28,7 @@
{ name: "3", keyPath: "value", options: { unique: false } },
];
let request = moz_indexedDB.open(name, description);
let request = mozIndexedDB.open(name, description);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield;

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

@ -32,12 +32,12 @@
{ name: "11", options: { keyPath: "foo", autoIncrement: true } }
];
let request = moz_indexedDB.open(name, description);
let request = mozIndexedDB.open(name, description);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield;
ok(event.source === moz_indexedDB, "event.source is correct");
ok(event.source === mozIndexedDB, "event.source is correct");
let db = event.result;
let count = db.objectStoreNames.length;

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

@ -30,7 +30,7 @@
// Post-add and post-remove data ordered by name.
const objectStoreDataNameSort = [ 1, 4, 5, 2, 3 ];
let request = moz_indexedDB.open(window.location.pathname);
let request = mozIndexedDB.open(window.location.pathname);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield;

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

@ -31,7 +31,7 @@
entry: { data: START_DATA } },
];
let request = moz_indexedDB.open(name, description);
let request = mozIndexedDB.open(name, description);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield;

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

@ -20,7 +20,7 @@
is(keys.length, sortedKeys.length, "Good key setup");
let request = moz_indexedDB.open(name, description);
let request = mozIndexedDB.open(name, description);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield;

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

@ -17,12 +17,12 @@
const description = "My Test Database";
const objectStoreName = "Objects";
var request = moz_indexedDB.open(name, description);
var request = mozIndexedDB.open(name, description);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
var event = yield;
ok(event.source === moz_indexedDB, "correct event.source");
ok(event.source === mozIndexedDB, "correct event.source");
var db = event.result;

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

@ -18,7 +18,7 @@
const values = [ "a", "1", 1, "foo", 300, true, false, 4.5, null ];
let request = moz_indexedDB.open(name, description);
let request = mozIndexedDB.open(name, description);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield;

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

@ -18,7 +18,7 @@
const objectStore = { name: "Objects",
options: { keyPath: "id", autoIncrement: true } };
let request = moz_indexedDB.open(name, description);
let request = mozIndexedDB.open(name, description);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield;
@ -37,7 +37,7 @@
continueToNextStep();
yield;
request = moz_indexedDB.open(name, description);
request = mozIndexedDB.open(name, description);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
event = yield;

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

@ -58,7 +58,7 @@
{ key: "237-23-7734", value: { name: "Ron", height: 73, weight: 180 } }
];
let request = moz_indexedDB.open(name, description);
let request = mozIndexedDB.open(name, description);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield;

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

@ -58,7 +58,7 @@
{ key: "237-23-7734", value: { name: "Ron", height: 73, weight: 180 } }
];
let request = moz_indexedDB.open(name, description);
let request = mozIndexedDB.open(name, description);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield;

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

@ -30,7 +30,7 @@
{ ss: "237-23-7733", name: "Bob", height: 65 }
];
let request = moz_indexedDB.open(window.location.pathname);
let request = mozIndexedDB.open(window.location.pathname);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield;

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

@ -69,7 +69,7 @@
{ key: "237-23-7734", value: { name: "Ron", height: 73, weight: 180 } }
];
let request = moz_indexedDB.open(name, description);
let request = mozIndexedDB.open(name, description);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield;

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

@ -49,7 +49,7 @@
{ key: "237-23-7734", value: { name: "Ron", height: 73, weight: 180 } }
];
let request = moz_indexedDB.open(name, description);
let request = mozIndexedDB.open(name, description);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield;

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

@ -16,7 +16,7 @@
const name = window.location.pathname;
const description = "My Test Database";
let request = moz_indexedDB.open(name, description);
let request = mozIndexedDB.open(name, description);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield;

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

@ -26,7 +26,7 @@
{ name: "b", options: { unique: true } }
];
let request = moz_indexedDB.open(name, description);
let request = mozIndexedDB.open(name, description);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield;

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

@ -19,7 +19,7 @@ function testSteps()
const name = window.location.pathname;
const description = "My Test Database";
var request = moz_indexedDB.open(name, description);
var request = mozIndexedDB.open(name, description);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
var event = yield;

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

@ -19,7 +19,7 @@ function testSteps()
const name = window.location.pathname;
const description = "My Test Database";
var request = moz_indexedDB.open(name, description);
var request = mozIndexedDB.open(name, description);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
var event = yield;

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

@ -13,7 +13,7 @@
<script type="text/javascript;version=1.7">
function testSteps()
{
let request = moz_indexedDB.open(window.location.pathname, "");
let request = mozIndexedDB.open(window.location.pathname, "");
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield;

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

@ -19,7 +19,7 @@
let request;
try {
request = moz_indexedDB.open("", "");
request = mozIndexedDB.open("", "");
ok(false, "Open with empty name should have thrown!");
}
catch(e) {
@ -29,7 +29,7 @@
}
try {
request = moz_indexedDB.open(null, "");
request = mozIndexedDB.open(null, "");
ok(false, "Open with null name should have thrown!");
}
catch(e) {
@ -38,7 +38,7 @@
is(request, undefined, "Shouldn't be set to anything");
}
request = moz_indexedDB.open(name, description);
request = mozIndexedDB.open(name, description);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield;

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

@ -18,7 +18,7 @@
const description = "My Test Database";
const objectStoreName = "Objects";
let request = moz_indexedDB.open(name, description);
let request = mozIndexedDB.open(name, description);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield;

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

@ -19,7 +19,7 @@
const description = "My Test Database";
const objectStores = [ "foo", "bar" ];
let request = moz_indexedDB.open(name, description);
let request = mozIndexedDB.open(name, description);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield;

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

@ -20,7 +20,7 @@
let testString = { key: 0, value: "testString" };
let testInt = { key: 1, value: 1002 };
let request = moz_indexedDB.open(name, description);
let request = mozIndexedDB.open(name, description);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield;

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

@ -20,7 +20,7 @@
let testString = { value: "testString" };
let testInt = { value: 1002 };
let request = moz_indexedDB.open(name, description);
let request = mozIndexedDB.open(name, description);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield;

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

@ -20,7 +20,7 @@
const description = "My Test Database";
const osName = "foo";
let request = moz_indexedDB.open(name, description);
let request = mozIndexedDB.open(name, description);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield;

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

@ -19,7 +19,7 @@
const description = "My Test Database";
const indexName = "My Test Index";
let request = moz_indexedDB.open(name, description);
let request = mozIndexedDB.open(name, description);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield;

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

@ -21,7 +21,7 @@
const description = "My Test Database";
const objectStoreName = "Objects";
let request = moz_indexedDB.open(name, description);
let request = mozIndexedDB.open(name, description);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield;

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

@ -19,7 +19,7 @@
const LOADING = Components.interfaces.nsIIDBRequest.LOADING;
const DONE = Components.interfaces.nsIIDBRequest.DONE;
let request = moz_indexedDB.open(name, description);
let request = mozIndexedDB.open(name, description);
is(request.readyState, LOADING, "Correct readyState");
request.onerror = errorHandler;

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

@ -20,7 +20,7 @@ function testSteps()
const name = window.location.pathname;
const description = "My Test Database";
let request = moz_indexedDB.open(name, description);
let request = mozIndexedDB.open(name, description);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield;

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

@ -20,7 +20,7 @@ function testSteps()
const name = window.location.pathname;
const description = "My Test Database";
let request = moz_indexedDB.open(name, description);
let request = mozIndexedDB.open(name, description);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield;

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

@ -16,7 +16,7 @@
const name = window.location.pathname;
const description = "My Test Database";
let request = moz_indexedDB.open(name, description);
let request = mozIndexedDB.open(name, description);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield;
@ -34,7 +34,7 @@
db1.close();
}, false);
request = moz_indexedDB.open(name, description);
request = mozIndexedDB.open(name, description);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
event = yield;
@ -63,7 +63,7 @@
ok(event.result === event.transaction, "Good result");
is(event.transaction.mode, IDBTransaction.VERSION_CHANGE, "Correct mode");
request = moz_indexedDB.open(name, description);
request = mozIndexedDB.open(name, description);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
event = yield;

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

@ -13,7 +13,7 @@
<script type="text/javascript;version=1.7">
function testSteps()
{
let request = moz_indexedDB.open(window.location.pathname);
let request = mozIndexedDB.open(window.location.pathname);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield;

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

@ -25,7 +25,7 @@
const description = "My Test Database";
let request = moz_indexedDB.open(name, description);
let request = mozIndexedDB.open(name, description);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield;

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

@ -13,7 +13,7 @@
<script type="text/javascript;version=1.7">
function testSteps()
{
let request = moz_indexedDB.open(window.location.pathname);
let request = mozIndexedDB.open(window.location.pathname);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield;

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

@ -13,7 +13,7 @@
<script type="text/javascript;version=1.7">
function testSteps()
{
let request = moz_indexedDB.open(window.location.pathname);
let request = mozIndexedDB.open(window.location.pathname);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield;

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

@ -21,7 +21,7 @@
const name = window.location.pathname;
const description = "My Test Database";
let request = moz_indexedDB.open(name, description);
let request = mozIndexedDB.open(name, description);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield;

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

@ -71,5 +71,5 @@ interface nsIDOMStorageWindow : nsISupports
/**
* Indexed Databases for the current browsing context.
*/
readonly attribute nsIIDBFactory moz_indexedDB;
readonly attribute nsIIDBFactory mozIndexedDB;
};

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

@ -162,9 +162,8 @@ NS_IMPL_RELEASE(TabChild)
NS_IMETHODIMP
TabChild::SetStatus(PRUint32 aStatusType, const PRUnichar* aStatus)
{
NS_NOTREACHED("TabChild::SetStatus not supported in TabChild");
return NS_ERROR_NOT_IMPLEMENTED;
// FIXME/bug 617804: should the platform support this?
return NS_OK;
}
NS_IMETHODIMP
@ -299,9 +298,8 @@ TabChild::GetTitle(PRUnichar** aTitle)
NS_IMETHODIMP
TabChild::SetTitle(const PRUnichar* aTitle)
{
NS_NOTREACHED("TabChild::SetTitle not supported in TabChild");
return NS_ERROR_NOT_IMPLEMENTED;
// FIXME/bug 617804: should the platform support this?
return NS_OK;
}
NS_IMETHODIMP

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

@ -163,6 +163,8 @@ PluginInstanceChild::PluginInstanceChild(const NPPluginFuncs* aPluginIface)
InitPopupMenuHook();
#endif // OS_WIN
#ifdef MOZ_X11
// Maemo flash can render plugin with any provided rectangle and not require this quirk.
#ifndef MOZ_PLATFORM_MAEMO
const char *description = NULL;
mPluginIface->getvalue(GetNPP(), NPPVpluginDescriptionString,
&description);
@ -173,6 +175,7 @@ PluginInstanceChild::PluginInstanceChild(const NPPluginFuncs* aPluginIface)
}
}
#endif
#endif
}
PluginInstanceChild::~PluginInstanceChild()
@ -2289,9 +2292,9 @@ PluginInstanceChild::CreateOptSurface(void)
#endif
// Make common shmem implementation working for any platform
mCurrentSurface = new gfxSharedImageSurface();
return static_cast<gfxSharedImageSurface*>(mCurrentSurface.get())->
Init(this, gfxIntSize(mWindow.width, mWindow.height), format);
mCurrentSurface =
gfxSharedImageSurface::CreateUnsafe(this, gfxIntSize(mWindow.width, mWindow.height), format);
return !!mCurrentSurface;
}
bool
@ -2774,10 +2777,11 @@ PluginInstanceChild::ReadbackDifferenceRect(const nsIntRect& rect)
if (!mBackSurface)
return false;
// We can read safely from XSurface and SharedDIBSurface, because
// PluginHost is not able to modify that surface
// We can read safely from XSurface,SharedDIBSurface and Unsafe SharedMemory,
// because PluginHost is not able to modify that surface
#if defined(MOZ_X11)
if (mBackSurface->GetType() != gfxASurface::SurfaceTypeXlib)
if (mBackSurface->GetType() != gfxASurface::SurfaceTypeXlib &&
!gfxSharedImageSurface::IsSharedImage(mBackSurface))
return false;
#elif defined(XP_WIN)
if (!SharedDIBSurface::IsSharedDIBSurface(mBackSurface))

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

@ -497,7 +497,7 @@ PluginInstanceParent::RecvShow(const NPRect& updatedRect,
NS_WARNING("back surface not readable");
return false;
}
surface = new gfxSharedImageSurface(newSurface.get_Shmem());
surface = gfxSharedImageSurface::Open(newSurface.get_Shmem());
}
#ifdef MOZ_X11
else if (newSurface.type() == SurfaceDescriptor::TSurfaceDescriptorX11) {

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

@ -901,7 +901,12 @@ nsJSChannel::SetLoadFlags(nsLoadFlags aLoadFlags)
}
bogusLoadBackground = !loadGroupIsBackground;
}
// Classifying a javascript: URI doesn't help us, and requires
// NSS to boot, which we don't have in content processes. See
// https://bugzilla.mozilla.org/show_bug.cgi?id=617838.
aLoadFlags &= ~LOAD_CLASSIFY_URI;
// Since the javascript channel is never the actual channel that
// any data is loaded through, don't ever set the
// LOAD_DOCUMENT_URI flag on it, since that could lead to two

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

@ -59,10 +59,10 @@ DIRS += \
storageevent \
$(NULL)
#needs IPC support
ifneq (mobile,$(MOZ_BUILD_APP))
DIRS += notification
endif
#needs IPC support, also tests do not run successfully in Firefox for now
#ifneq (mobile,$(MOZ_BUILD_APP))
#DIRS += notification
#endif
include $(topsrcdir)/config/rules.mk

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

@ -72,3 +72,7 @@ function force_click_on_notification(val) {
prefs.setBoolPref("notification.prompt.testing.click_on_notification", val);
}
function is_feature_enabled() {
var prefs = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
return prefs.getBoolPref("notification.feature.enabled");
}

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

@ -21,27 +21,33 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=573588
<pre id="test">
<script class="testbody" type="text/javascript">
force_prompt(true);
force_click_on_notification(false);
SimpleTest.waitForExplicitFinish();
ok(navigator.mozNotification, "test for notification.");
var notification = navigator.mozNotification.createNotification("test", "test");
ok(notification, "test to ensure we can create a notification");
notification.onclose = function() {
ok(true, "notification was display and is now closing");
reset_prompt();
if (is_feature_enabled() == false) {
SimpleTest.finish();
};
notification.onclick = function() {
ok(false, "Click should not have been called.");
}
else
{
force_prompt(true);
force_click_on_notification(false);
notification.show();
SimpleTest.waitForExplicitFinish();
ok(navigator.mozNotification, "test for notification.");
var notification = navigator.mozNotification.createNotification("test", "test");
ok(notification, "test to ensure we can create a notification");
notification.onclose = function() {
ok(true, "notification was display and is now closing");
reset_prompt();
SimpleTest.finish();
};
notification.onclick = function() {
ok(false, "Click should not have been called.");
}
notification.show();
}
</script>
</pre>

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

@ -21,32 +21,38 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=573588
<pre id="test">
<script class="testbody" type="text/javascript">
click_was_called = false;
force_prompt(true);
force_click_on_notification(true);
SimpleTest.waitForExplicitFinish();
ok(navigator.mozNotification, "test for notification.");
var notification = navigator.mozNotification.createNotification("test", "test");
ok(notification, "test to ensure we can create a notification");
notification.onclose = function() {
ok(true, "notification was display and is now closing");
ok(click_was_called, "was notification clicked?");
reset_prompt();
if (is_feature_enabled() == false) {
SimpleTest.finish();
};
notification.onclick = function() {
ok(true, "Click was called. Good.");
click_was_called = true;
}
else
{
click_was_called = false;
notification.show();
force_prompt(true);
force_click_on_notification(true);
SimpleTest.waitForExplicitFinish();
ok(navigator.mozNotification, "test for notification.");
var notification = navigator.mozNotification.createNotification("test", "test");
ok(notification, "test to ensure we can create a notification");
notification.onclose = function() {
ok(true, "notification was display and is now closing");
ok(click_was_called, "was notification clicked?");
reset_prompt();
SimpleTest.finish();
};
notification.onclick = function() {
ok(true, "Click was called. Good.");
click_was_called = true;
}
notification.show();
}
</script>
</pre>

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

@ -10,16 +10,22 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=605309
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script>
function boom()
{
document.documentElement.focus();
var x = navigator.mozNotification;
document.documentElement.addEventListener('', function(){x}, false);
if (is_feature_enabled() == false) {
SimpleTest.finish();
}
else
{
function boom()
{
document.documentElement.focus();
var x = navigator.mozNotification;
document.documentElement.addEventListener('', function(){x}, false);
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
window.addEventListener("load", boom, false);
SimpleTest.waitForExplicitFinish();
window.addEventListener("load", boom, false);
}
</script>
</head>
<body>

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

@ -123,9 +123,11 @@ abstract public class GeckoApp
try {
unpackComponents();
} catch (FileNotFoundException fnfe) {
Log.e("GeckoApp", "error unpacking components", fnfe);
showErrorDialog(getString(R.string.error_loading_file));
return false;
} catch (IOException ie) {
Log.e("GeckoApp", "error unpacking components", ie);
String msg = ie.getMessage();
if (msg.equalsIgnoreCase("No space left on device"))
showErrorDialog(getString(R.string.no_space_to_start_error));
@ -412,7 +414,7 @@ abstract public class GeckoApp
Log.i("GeckoAppJava", intent.toString());
startActivity(intent);
} catch (Exception e) {
Log.i("GeckoAppJava", e.toString());
Log.i("GeckoAppJava", "error doing restart", e);
}
finish();
}
@ -425,10 +427,16 @@ abstract public class GeckoApp
Log.i("GeckoAppJava", "Checking for an update");
int statusCode = 8; // UNEXPECTED_ERROR
File downloadDir = null;
if (Build.VERSION.SDK_INT >= 8)
downloadDir = getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS);
else
downloadDir = new File(Environment.getExternalStorageDirectory().getPath(), "download");
String updateDir = Environment.getExternalStorageDirectory().getPath() + "/downloads/updates/0/";
File updateFile = new File(updateDir + "update.apk");
File statusFile = new File(updateDir + "update.status");
File updateDir = new File(new File(downloadDir, "updates"),"0");
File updateFile = new File(updateDir, "update.apk");
File statusFile = new File(updateDir, "update.status");
if (!statusFile.exists() || !readUpdateStatus(statusFile).equals("pending"))
return;
@ -453,7 +461,7 @@ abstract public class GeckoApp
statusCode = 7; // WRITE_ERROR
}
} catch (Exception e) {
Log.i("GeckoAppJava", e.toString());
Log.i("GeckoAppJava", "error launching installer to update", e);
}
// Update the status file
@ -466,7 +474,7 @@ abstract public class GeckoApp
outStream.write(buf, 0, buf.length);
outStream.close();
} catch (Exception e) {
Log.i("GeckoAppJava", e.toString());
Log.i("GeckoAppJava", "error writing status file", e);
}
if (statusCode == 0)
@ -480,7 +488,7 @@ abstract public class GeckoApp
status = reader.readLine();
reader.close();
} catch (Exception e) {
Log.i("GeckoAppJava", e.toString());
Log.i("GeckoAppJava", "error reading update status", e);
}
return status;
}
@ -500,7 +508,7 @@ abstract public class GeckoApp
try {
filePickerResult = mFilePickerResult.take();
} catch (InterruptedException e) {
Log.i("GeckoApp", "error: " + e);
Log.i("GeckoApp", "showing file picker ", e);
}
return filePickerResult;
@ -535,13 +543,13 @@ abstract public class GeckoApp
fos.close();
filePickerResult = file.getAbsolutePath();
}catch (Exception e) {
Log.e("GeckoApp", "error : "+ e);
Log.e("GeckoApp", "showing file picker", e);
}
}
try {
mFilePickerResult.put(filePickerResult);
} catch (InterruptedException e) {
Log.i("GeckoApp", "error: " + e);
Log.i("GeckoApp", "error returning file picker result", e);
}
}
}

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

@ -118,8 +118,13 @@ class GeckoAppShell
GeckoAppShell.putenv("TMPDIR=" + f.getPath());
f = Environment.getDownloadCacheDirectory();
GeckoAppShell.putenv("EXTERNAL_STORAGE" + f.getPath());
GeckoAppShell.putenv("EXTERNAL_STORAGE=" + f.getPath());
File downloadDir = null;
if (Build.VERSION.SDK_INT >= 8)
downloadDir = GeckoApp.mAppContext.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS);
else
downloadDir = new File(Environment.getExternalStorageDirectory().getPath(), "download");
GeckoAppShell.putenv("DOWNLOADS_DIRECTORY=" + downloadDir.getPath());
GeckoAppShell.putenv("LANG=" + Locale.getDefault().toString());
loadLibs(apkName);

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше