Backed out changeset 24fb014f1ae3 (bug 1021618) for Linux Memory Leak on a CLOSED TREE

This commit is contained in:
Carsten "Tomcat" Book 2014-06-25 10:03:44 +02:00
parent 51ab717a65
commit 0fedf193db
12 changed files with 11 additions and 532 deletions

View File

@ -61,8 +61,8 @@ var gContentPane = {
params.windowTitle = bundlePreferences.getString("popuppermissionstitle");
params.introText = bundlePreferences.getString("popuppermissionstext");
gSubDialog.open("chrome://browser/content/preferences/permissions.xul",
"resizable=yes", params);
openDialog("chrome://browser/content/preferences/permissions.xul",
"Browser:Permissions", "resizable=yes", params);
},
// FONTS
@ -163,7 +163,8 @@ var gContentPane = {
*/
configureColors: function ()
{
gSubDialog.open("chrome://browser/content/preferences/colors.xul");
openDialog("chrome://browser/content/preferences/colors.xul",
"Browser:ColorPreferences", null);
},
// LANGUAGES
@ -173,7 +174,8 @@ var gContentPane = {
*/
showLanguages: function ()
{
gSubDialog.open("chrome://browser/content/preferences/languages.xul");
openDialog("chrome://browser/content/preferences/languages.xul",
"Browser:LanguagePreferences", null);
},
/**

View File

@ -5,8 +5,6 @@
browser.jar:
content/browser/preferences/in-content/preferences.js
* content/browser/preferences/in-content/preferences.xul
content/browser/preferences/in-content/subdialogs.js
* content/browser/preferences/in-content/main.js
* content/browser/preferences/in-content/privacy.js
* content/browser/preferences/in-content/advanced.js

View File

@ -111,14 +111,8 @@ var gMainPane = {
setHomePageToBookmark: function ()
{
var rv = { urls: null, names: null };
var dialog = gSubDialog.open("chrome://browser/content/preferences/selectBookmark.xul",
"resizable=yes, modal=yes", rv,
this._setHomePageToBookmarkClosed.bind(this, rv));
},
_setHomePageToBookmarkClosed: function(rv, aEvent) {
if (aEvent.detail.button != "accept")
return;
openDialog("chrome://browser/content/preferences/selectBookmark.xul",
"Select Bookmark", "resizable=yes, modal=yes", rv);
if (rv.urls && rv.names) {
var homePage = document.getElementById("browser.startup.homepage");

View File

@ -21,8 +21,6 @@ addEventListener("DOMContentLoaded", function onLoad() {
function init_all() {
document.documentElement.instantApply = true;
gSubDialog.init();
gMainPane.init();
gPrivacyPane.init();
gAdvancedPane.init();
@ -30,7 +28,6 @@ function init_all() {
gContentPane.init();
gSyncPane.init();
gSecurityPane.init();
var initFinished = new CustomEvent("Initialized", {
'bubbles': true,
'cancelable': true

View File

@ -16,7 +16,6 @@
<!DOCTYPE page [
<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
<!ENTITY % globalPreferencesDTD SYSTEM "chrome://global/locale/preferences.dtd">
<!ENTITY % preferencesDTD SYSTEM
"chrome://browser/locale/preferences/preferences.dtd">
<!ENTITY % privacyDTD SYSTEM "chrome://browser/locale/preferences/privacy.dtd">
@ -34,7 +33,6 @@
<!ENTITY % advancedDTD SYSTEM
"chrome://browser/locale/preferences/advanced.dtd">
%brandDTD;
%globalPreferencesDTD;
%preferencesDTD;
%privacyDTD;
%tabsDTD;
@ -68,7 +66,6 @@
src="chrome://browser/content/utilityOverlay.js"/>
<script type="application/javascript"
src="chrome://browser/content/preferences/in-content/preferences.js"/>
<script src="chrome://browser/content/preferences/in-content/subdialogs.js"/>
<stringbundle id="bundleBrand"
src="chrome://branding/locale/brand.properties"/>
@ -80,7 +77,6 @@
src="chrome://browser/locale/preferences/applicationManager.properties"/>
</stringbundleset>
<stack flex="1">
<hbox flex="1">
<!-- category list -->
@ -178,24 +174,4 @@
</vbox>
</hbox>
<vbox id="dialogOverlay" align="center" pack="center">
<groupbox id="dialogBox"
orient="vertical"
pack="end"
role="dialog"
aria-labelledby="dialogTitle">
<caption class="titlebar" flex="1" align="center">
<label id="dialogTitle" class="header" flex="1"></label>
<button id="dialogClose"
class="close-icon"
aria-label="&preferencesCloseButton.label;"/>
</caption>
<browser id="dialogFrame"
name="dialogFrame"
autoscroll="false"
disablehistory="true"/>
</groupbox>
</vbox>
</stack>
</page>

View File

@ -1,130 +0,0 @@
/* - This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this file,
- You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
let gSubDialog = {
_closingCallback: null,
_frame: null,
_overlay: null,
_injectedStyleSheets: ["chrome://mozapps/content/preferences/preferences.css",
"chrome://browser/skin/preferences/preferences.css",
"chrome://browser/skin/preferences/in-content/preferences.css"],
init: function() {
this._frame = document.getElementById("dialogFrame");
this._overlay = document.getElementById("dialogOverlay");
// Make the close button work.
let dialogClose = document.getElementById("dialogClose");
dialogClose.addEventListener("command", this.close.bind(this));
// DOMTitleChanged isn't fired on the frame, only on the chromeEventHandler
let chromeBrowser = window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShell)
.chromeEventHandler;
chromeBrowser.addEventListener("DOMTitleChanged", this.updateTitle.bind(this), true);
// Similarly DOMFrameContentLoaded only fires on the top window
window.addEventListener("DOMFrameContentLoaded", this._onContentLoaded.bind(this), true);
// Wait for the stylesheets injected during DOMContentLoaded to load before showing the dialog
// otherwise there is a flicker of the stylesheet applying.
this._frame.addEventListener("load", this._onLoad.bind(this));
},
updateTitle: function(aEvent) {
if (aEvent.target != this._frame.contentDocument)
return;
document.getElementById("dialogTitle").textContent = this._frame.contentDocument.title;
},
injectXMLStylesheet: function(aStylesheetURL) {
let contentStylesheet = this._frame.contentDocument.createProcessingInstruction(
'xml-stylesheet',
'href="' + aStylesheetURL + '" type="text/css"'
);
this._frame.contentDocument.insertBefore(contentStylesheet,
this._frame.contentDocument.documentElement);
},
open: function(aURL, aFeatures = null, aParams = null, aClosingCallback = null) {
let features = aFeatures || "modal,centerscreen,resizable=no";
let dialog = window.openDialog(aURL, "dialogFrame", features, aParams);
if (aClosingCallback) {
this._closingCallback = aClosingCallback.bind(dialog);
}
return dialog;
},
close: function(aEvent = null) {
if (this._closingCallback) {
try {
this._closingCallback.call(null, aEvent);
} catch (ex) {
Cu.reportError(ex);
}
this._closingCallback = null;
}
this._overlay.style.visibility = "";
// Clear the sizing inline styles.
this._frame.removeAttribute("style");
setTimeout(() => {
// Unload the dialog after the event listeners run so that the load of about:blank isn't
// cancelled by the ESC <key>.
this._frame.loadURI("about:blank");
}, 0);
},
/* Private methods */
_onContentLoaded: function(aEvent) {
if (aEvent.target != this._frame || aEvent.target.contentWindow.location == "about:blank")
return;
for (let styleSheetURL of this._injectedStyleSheets) {
this.injectXMLStylesheet(styleSheetURL);
}
// Make window.close calls work like dialog closing.
let oldClose = this._frame.contentWindow.close;
this._frame.contentWindow.close = function() {
var closingEvent = new CustomEvent("dialogclosing", {
bubbles: true,
detail: { button: null },
});
gSubDialog._frame.contentWindow.dispatchEvent(closingEvent);
oldClose.call(gSubDialog._frame.contentWindow);
};
// XXX: Hack to make focus during the dialog's load functions work. Make the element visible
// sooner in DOMContentLoaded but mostly invisible instead of changing visibility just before
// the dialog's load event.
this._overlay.style.visibility = "visible";
this._overlay.style.opacity = "0.01";
this._frame.contentWindow.addEventListener("dialogclosing", function closingDialog(aEvent) {
gSubDialog._frame.contentWindow.removeEventListener("dialogclosing", closingDialog);
gSubDialog.close(aEvent);
});
},
_onLoad: function(aEvent) {
if (aEvent.target.contentWindow.location == "about:blank")
return;
// Do this on load to wait for the CSS to load and apply before calculating the size.
let docEl = this._frame.contentDocument.documentElement;
this._frame.style.width = docEl.style.width || docEl.scrollWidth + "px";
this._frame.style.height = docEl.style.height || docEl.scrollHeight + "px";
this._overlay.style.visibility = "visible";
this._frame.focus();
this._overlay.style.opacity = ""; // XXX: focus hack continued from _onContentLoaded
},
};

View File

@ -19,5 +19,3 @@ skip-if = !healthreport || (os == 'linux' && debug)
[browser_privacypane_5.js]
[browser_privacypane_8.js]
skip-if = e10s # Bug ?????? - "leaked until shutdown [nsGlobalWindow #99 about:preferences]"
[browser_subdialogs.js]
support-files = subdialog.xul

View File

@ -1,196 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
/**
* Tests for the sub-dialog infrastructure, not for actual sub-dialog functionality.
*/
let gTeardownAfterClose = false;
const gDialogURL = getRootDirectory(gTestPath) + "subdialog.xul";
function test() {
waitForExplicitFinish();
open_preferences((win) => {
Task.spawn(function () {
for (let test of gTests) {
info("STARTING TEST: " + test.desc);
try {
yield test.run();
} finally {
if (test.teardown) {
yield test.teardown();
}
}
}
});
});
}
let gTests = [{
desc: "Check titlebar, focus, return value, title changes, and accepting",
run: function* () {
let rv = { acceptCount: 0 };
let deferredClose = Promise.defer();
let dialogPromise = openAndLoadSubDialog(gDialogURL, null, rv,
(aEvent) => dialogClosingCallback(deferredClose, aEvent));
let dialog = yield dialogPromise;
// Check focus is in the textbox
ise(dialog.document.activeElement.value, "Default text", "Textbox with correct text is focused");
// Titlebar
ise(content.document.getElementById("dialogTitle").textContent, "Sample sub-dialog",
"Dialog title should be correct initially");
let receivedEvent = waitForEvent(gBrowser.selectedBrowser, "DOMTitleChanged");
dialog.document.title = "Updated title";
// Wait for the title change listener
yield receivedEvent;
ise(content.document.getElementById("dialogTitle").textContent, "Updated title",
"Dialog title should be updated with changes");
let closingPromise = promiseDialogClosing(dialog);
// Accept the dialog
dialog.document.documentElement.acceptDialog();
let closingEvent = yield closingPromise;
ise(closingEvent.detail.button, "accept", "closing event should indicate button was 'accept'");
yield deferredClose.promise;
ise(rv.acceptCount, 1, "return value should have been updated");
},
},
{
desc: "Check canceling the dialog",
run: function* () {
let rv = { acceptCount: 0 };
let deferredClose = Promise.defer();
let dialogPromise = openAndLoadSubDialog(gDialogURL, null, rv,
(aEvent) => dialogClosingCallback(deferredClose, aEvent));
let dialog = yield dialogPromise;
let closingPromise = promiseDialogClosing(dialog);
info("cancelling the dialog");
dialog.document.documentElement.cancelDialog();
let closingEvent = yield closingPromise;
ise(closingEvent.detail.button, "cancel", "closing event should indicate button was 'accept'");
yield deferredClose.promise;
ise(rv.acceptCount, 0, "return value should NOT have been updated");
},
},
{
desc: "Check window.close on the dialog",
run: function* () {
let rv = { acceptCount: 0 };
let deferredClose = Promise.defer();
let dialogPromise = openAndLoadSubDialog(gDialogURL, null, rv,
(aEvent) => dialogClosingCallback(deferredClose, aEvent));
let dialog = yield dialogPromise;
let closingPromise = promiseDialogClosing(dialog);
info("window.close called on the dialog");
dialog.window.close();
let closingEvent = yield closingPromise;
ise(closingEvent.detail.button, null, "closing event should indicate no button was clicked");
yield deferredClose.promise;
ise(rv.acceptCount, 0, "return value should NOT have been updated");
},
},
{
desc: "Check clicking the close button on the dialog",
run: function* () {
let rv = { acceptCount: 0 };
let deferredClose = Promise.defer();
let dialogPromise = openAndLoadSubDialog(gDialogURL, null, rv,
(aEvent) => dialogClosingCallback(deferredClose, aEvent));
let dialog = yield dialogPromise;
yield EventUtils.synthesizeMouseAtCenter(content.document.getElementById("dialogClose"), {},
content.window);
yield deferredClose.promise;
ise(rv.acceptCount, 0, "return value should NOT have been updated");
},
},
{
desc: "Hitting escape in the dialog",
run: function* () {
let rv = { acceptCount: 0 };
let deferredClose = Promise.defer();
let dialogPromise = openAndLoadSubDialog(gDialogURL, null, rv,
(aEvent) => dialogClosingCallback(deferredClose, aEvent));
let dialog = yield dialogPromise;
EventUtils.synthesizeKey("VK_ESCAPE", {}, content.window);
yield deferredClose.promise;
ise(rv.acceptCount, 0, "return value should NOT have been updated");
},
},
{
desc: "Check that width and height from the sub-dialog are used to size the <browser>",
run: function* () {
let deferredClose = Promise.defer();
let dialogPromise = openAndLoadSubDialog(gDialogURL, null, null,
(aEvent) => dialogClosingCallback(deferredClose, aEvent));
let dialog = yield dialogPromise;
ise(content.gSubDialog._frame.style.width, "32em", "Width should be set on the frame from the dialog");
ise(content.gSubDialog._frame.style.height, "40em", "Height should be set on the frame from the dialog");
content.gSubDialog.close();
yield deferredClose.promise;
},
},
{
desc: "Check that scrollWidth and scrollHeight from the sub-dialog are used to size the <browser>",
run: function* () {
let deferredClose = Promise.defer();
let dialogPromise = openAndLoadSubDialog(gDialogURL, null, null,
(aEvent) => dialogClosingCallback(deferredClose, aEvent));
content.addEventListener("DOMFrameContentLoaded", function frameLoaded() {
content.removeEventListener("DOMFrameContentLoaded", frameLoaded);
content.gSubDialog._frame.contentDocument.documentElement.style.height = "";
content.gSubDialog._frame.contentDocument.documentElement.style.width = "";
});
let dialog = yield dialogPromise;
ok(content.gSubDialog._frame.style.width.endsWith("px"),
"Width should be set to a px value of the scrollWidth from the dialog");
ok(content.gSubDialog._frame.style.height.endsWith("px"),
"Height should be set to a px value of the scrollHeight from the dialog");
gTeardownAfterClose = true;
content.gSubDialog.close();
yield deferredClose.promise;
},
}];
function promiseDialogClosing(dialog) {
return waitForEvent(dialog, "dialogclosing");
}
function dialogClosingCallback(aPromise, aEvent) {
// Wait for the close handler to unload the page
waitForEvent(content.gSubDialog._frame, "load").then((aEvt) => {
ok(!(aEvt instanceof Error), "Check load event happened");
is_element_hidden(content.gSubDialog._overlay, "Overlay is not visible");
ise(content.gSubDialog._frame.getAttribute("style"), "",
"Check that inline styles were cleared");
ise(content.gSubDialog._frame.contentWindow.location.toString(), "about:blank",
"Check the sub-dialog was unloaded");
if (gTeardownAfterClose) {
content.close();
finish();
}
aPromise.resolve();
});
}

View File

@ -1,11 +1,6 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
Components.utils.import("resource://gre/modules/Promise.jsm");
const kDefaultWait = 2000;
const kDefaultInterval = 50;
function is_hidden(aElement) {
var style = aElement.ownerDocument.defaultView.getComputedStyle(aElement, "");
if (style.display == "none")
@ -38,83 +33,3 @@ function open_preferences(aCallback) {
aCallback(gBrowser.contentWindow);
}, true);
}
function openAndLoadSubDialog(aURL, aFeatures = null, aParams = null, aClosingCallback = null) {
let dialog = content.gSubDialog.open(aURL, aFeatures, aParams, aClosingCallback);
let deferred = Promise.defer();
content.gSubDialog._frame.addEventListener("load", function load(aEvent) {
if (aEvent.target.contentWindow.location == "about:blank")
return;
content.gSubDialog._frame.removeEventListener("load", load);
ise(content.gSubDialog._frame.contentWindow.location.toString(), aURL,
"Check the proper URL is loaded");
// Check visibility
is_element_visible(content.gSubDialog._overlay, "Overlay is visible");
// Check that stylesheets were injected
let expectedStyleSheetURLs = content.gSubDialog._injectedStyleSheets.slice(0);
for (let styleSheet of content.document.styleSheets) {
let i = expectedStyleSheetURLs.indexOf(styleSheet.href);
if (i >= 0) {
info("found " + styleSheet.href);
expectedStyleSheetURLs.splice(i, 1);
}
}
ise(expectedStyleSheetURLs.length, 0, "All expectedStyleSheetURLs should have been found");
deferred.resolve(dialog);
});
return deferred.promise;
}
/**
* Waits a specified number of miliseconds for a specified event to be
* fired on a specified element.
*
* Usage:
* let receivedEvent = waitForEvent(element, "eventName");
* // Do some processing here that will cause the event to be fired
* // ...
* // Now yield until the Promise is fulfilled
* yield receivedEvent;
* if (receivedEvent && !(receivedEvent instanceof Error)) {
* receivedEvent.msg == "eventName";
* // ...
* }
*
* @param aSubject the element that should receive the event
* @param aEventName the event to wait for
* @param aTimeoutMs the number of miliseconds to wait before giving up
* @returns a Promise that resolves to the received event, or to an Error
*/
function waitForEvent(aSubject, aEventName, aTimeoutMs, aTarget) {
let eventDeferred = Promise.defer();
let timeoutMs = aTimeoutMs || kDefaultWait;
let stack = new Error().stack;
let timerID = setTimeout(function wfe_canceller() {
aSubject.removeEventListener(aEventName, listener);
eventDeferred.reject(new Error(aEventName + " event timeout at " + stack));
}, timeoutMs);
var listener = function (aEvent) {
if (aTarget && aTarget !== aEvent.target)
return;
// stop the timeout clock and resume
clearTimeout(timerID);
eventDeferred.resolve(aEvent);
};
function cleanup(aEventOrError) {
// unhook listener in case of success or failure
aSubject.removeEventListener(aEventName, listener);
return aEventOrError;
}
aSubject.addEventListener(aEventName, listener, false);
return eventDeferred.promise.then(cleanup, cleanup);
}

View File

@ -1,27 +0,0 @@
<?xml version="1.0"?>
<!-- Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ -->
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<dialog id="subDialog"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="Sample sub-dialog" style="width: 32em; height: 40em;"
onload="document.getElementById('textbox').focus();"
ondialogaccept="acceptSubdialog();">
<script>
function acceptSubdialog() {
window.arguments[0].acceptCount++;
}
</script>
<description>A sample sub-dialog for testing</description>
<textbox id="textbox" value="Default text" />
<separator class="thin"/>
<button oncommand="close();" icon="close" label="Close" />
</dialog>

View File

@ -5,14 +5,9 @@
%endif
@namespace html "http://www.w3.org/1999/xhtml";
#dialogBox,
dialog,
prefwindow,
.windowDialog,
page {
-moz-appearance: none;
background-color: white;
color: #424E5A;
}
* {
@ -42,6 +37,7 @@ prefpane {
font: message-box;
font-size: 1.25rem;
line-height: 22px;
color: #424E5A;
}
prefpane > .content-box {
@ -74,6 +70,7 @@ tabpanels {
-moz-appearance: none;
font-size: 1.25rem;
line-height: 22px;
color: #424E5A;
border: none;
padding: 0;
background-color: transparent;
@ -187,7 +184,6 @@ button[type="menu"] > .button-box > .button-menu-dropmarker {
background-image: none;
}
.close-icon > .button-box,
.help-button > .button-box {
padding-top: 0;
padding-bottom: 0;
@ -836,41 +832,3 @@ description > html|a {
.indent {
-moz-margin-start: 33px;
}
/**
* Sub-dialog
*/
#dialogOverlay {
background-color: rgba(0,0,0,0.5);
visibility: hidden;
}
#dialogBox {
border: 1px solid #666;
display: -moz-box;
}
.close-icon {
background-color: transparent !important;
border: none;
box-shadow: none;
height: 18px;
padding: 0;
min-width: 18px;
}
#dialogBox > .groupbox-body {
-moz-appearance: none;
padding: 0;
}
#dialogFrame {
/* Default dialog dimensions */
height: 30em;
width: 30em;
}
/**
* End sub-dialog
*/

View File

@ -357,14 +357,8 @@
if (!button.disabled) {
var noCancel = this._fireButtonEvent(aDlgType);
if (noCancel) {
if (aDlgType == "accept" || aDlgType == "cancel") {
var closingEvent = new CustomEvent("dialogclosing", {
bubbles: true,
detail: { button: aDlgType },
});
this.dispatchEvent(closingEvent);
if (aDlgType == "accept" || aDlgType == "cancel")
window.close();
}
}
return noCancel;
}