Merge mozilla-central into tracemonkey

This commit is contained in:
Vladimir Vukicevic 2008-11-18 13:54:21 -08:00
commit 7a34f9500d
64 changed files with 997 additions and 625 deletions

View File

@ -1111,6 +1111,7 @@ function prepareForStartup() {
// hook up UI through progress listener
gBrowser.addProgressListener(window.XULBrowserWindow, Components.interfaces.nsIWebProgress.NOTIFY_ALL);
gBrowser.addTabsProgressListener(window.TabsProgressListener);
// setup our common DOMLinkAdded listener
gBrowser.addEventListener("DOMLinkAdded", DOMLinkHandler, false);
@ -1339,6 +1340,7 @@ function BrowserShutdown()
try {
gBrowser.removeProgressListener(window.XULBrowserWindow);
gBrowser.removeTabsProgressListener(window.TabsProgressListener);
} catch (ex) {
}
@ -3796,8 +3798,7 @@ var XULBrowserWindow = {
},
onLinkIconAvailable: function (aBrowser) {
if (gProxyFavIcon && gBrowser.mCurrentBrowser == aBrowser &&
gBrowser.userTypedValue === null)
if (gProxyFavIcon && gBrowser.userTypedValue === null)
PageProxySetIcon(aBrowser.mIconURL); // update the favicon in the URL bar
},
@ -3858,8 +3859,6 @@ var XULBrowserWindow = {
if (aWebProgress.DOMWindow == content) {
if (aRequest)
this.endDocumentLoad(aRequest, aStatus);
if (!gBrowser.mTabbedMode && !gBrowser.mCurrentBrowser.mIconURL)
gBrowser.useDefaultIcon(gBrowser.mCurrentTab);
if (Components.isSuccessCode(aStatus) &&
content.document.documentElement.getAttribute("manifest"))
@ -3996,9 +3995,6 @@ var XULBrowserWindow = {
this.reloadCommand.removeAttribute("disabled");
}
if (!gBrowser.mTabbedMode && aWebProgress.isLoadingDocument)
gBrowser.setIcon(gBrowser.mCurrentTab, null);
if (gURLBar) {
// Strip off "wyciwyg://" and passwords for the location bar
let uri = aLocationURI;
@ -4044,55 +4040,6 @@ var XULBrowserWindow = {
this.updateStatusField();
},
onRefreshAttempted: function (aWebProgress, aURI, aDelay, aSameURI) {
if (gPrefService.getBoolPref("accessibility.blockautorefresh")) {
let brandBundle = document.getElementById("bundle_brand");
let brandShortName = brandBundle.getString("brandShortName");
let refreshButtonText =
gNavigatorBundle.getString("refreshBlocked.goButton");
let refreshButtonAccesskey =
gNavigatorBundle.getString("refreshBlocked.goButton.accesskey");
let message =
gNavigatorBundle.getFormattedString(aSameURI ? "refreshBlocked.refreshLabel"
: "refreshBlocked.redirectLabel",
[brandShortName]);
let topBrowser = getBrowserFromContentWindow(aWebProgress.DOMWindow.top);
let docShell = aWebProgress.DOMWindow
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShell);
let notificationBox = gBrowser.getNotificationBox(topBrowser);
let notification = notificationBox.getNotificationWithValue("refresh-blocked");
if (notification) {
notification.label = message;
notification.refreshURI = aURI;
notification.delay = aDelay;
notification.docShell = docShell;
} else {
let buttons = [{
label: refreshButtonText,
accessKey: refreshButtonAccesskey,
callback: function (aNotification, aButton) {
var refreshURI = aNotification.docShell
.QueryInterface(Ci.nsIRefreshURI);
refreshURI.forceRefreshURI(aNotification.refreshURI,
aNotification.delay, true);
}
}];
notification =
notificationBox.appendNotification(message, "refresh-blocked",
"chrome://browser/skin/Info.png",
notificationBox.PRIORITY_INFO_MEDIUM,
buttons);
notification.refreshURI = aURI;
notification.delay = aDelay;
notification.docShell = docShell;
}
return false;
}
return true;
},
// Properties used to cache security state used to update the UI
_state: null,
_host: undefined,
@ -4159,9 +4106,15 @@ var XULBrowserWindow = {
if (level) {
this.securityButton.setAttribute("level", level);
this.securityButton.hidden = false;
// We don't style the Location Bar based on the the 'level' attribute
// anymore, but still set it for third-party themes.
if (gURLBar)
gURLBar.setAttribute("level", level);
} else {
this.securityButton.hidden = true;
this.securityButton.removeAttribute("level");
if (gURLBar)
gURLBar.removeAttribute("level");
}
if (setHost && this._host)
@ -4244,6 +4197,73 @@ var XULBrowserWindow = {
}
}
var TabsProgressListener = {
onProgressChange: function (aBrowser, aWebProgress, aRequest,
aCurSelfProgress, aMaxSelfProgress,
aCurTotalProgress, aMaxTotalProgress) {
},
onStateChange: function (aBrowser, aWebProgress, aRequest, aStateFlags, aStatus) {
},
onLocationChange: function (aBrowser, aWebProgress, aRequest, aLocationURI) {
},
onStatusChange: function (aBrowser, aWebProgress, aRequest, aStatus, aMessage) {
},
onRefreshAttempted: function (aBrowser, aWebProgress, aURI, aDelay, aSameURI) {
if (gPrefService.getBoolPref("accessibility.blockautorefresh")) {
let brandBundle = document.getElementById("bundle_brand");
let brandShortName = brandBundle.getString("brandShortName");
let refreshButtonText =
gNavigatorBundle.getString("refreshBlocked.goButton");
let refreshButtonAccesskey =
gNavigatorBundle.getString("refreshBlocked.goButton.accesskey");
let message =
gNavigatorBundle.getFormattedString(aSameURI ? "refreshBlocked.refreshLabel"
: "refreshBlocked.redirectLabel",
[brandShortName]);
let docShell = aWebProgress.DOMWindow
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShell);
let notificationBox = gBrowser.getNotificationBox(aBrowser);
let notification = notificationBox.getNotificationWithValue("refresh-blocked");
if (notification) {
notification.label = message;
notification.refreshURI = aURI;
notification.delay = aDelay;
notification.docShell = docShell;
} else {
let buttons = [{
label: refreshButtonText,
accessKey: refreshButtonAccesskey,
callback: function (aNotification, aButton) {
var refreshURI = aNotification.docShell
.QueryInterface(Ci.nsIRefreshURI);
refreshURI.forceRefreshURI(aNotification.refreshURI,
aNotification.delay, true);
}
}];
notification =
notificationBox.appendNotification(message, "refresh-blocked",
"chrome://browser/skin/Info.png",
notificationBox.PRIORITY_INFO_MEDIUM,
buttons);
notification.refreshURI = aURI;
notification.delay = aDelay;
notification.docShell = docShell;
}
return false;
}
return true;
},
onSecurityChange: function (aBrowser, aWebProgress, aRequest, aState) {
}
}
function nsBrowserAccess()
{
}

View File

@ -271,9 +271,9 @@
</tooltip>
<toolbox id="navigator-toolbox" class="toolbox-top" mode="icons"
ondragover="gBrowser._onDragOver(event); event.stopPropagation();"
ondrop="gBrowser._onDrop(event); event.stopPropagation();"
ondragleave="gBrowser._onDragLeave(event); event.stopPropagation();"
ondragover="gBrowser._onDragOver(event);"
ondrop="gBrowser._onDrop(event);"
ondragleave="gBrowser._onDragLeave(event);"
defaultmode="icons">
<!-- Menu -->
<toolbar type="menubar" id="toolbar-menubar" class="chromeclass-menubar" customizable="true"

View File

@ -230,7 +230,10 @@ Sanitizer.prototype = {
var formHistory = Components.classes["@mozilla.org/satchel/form-history;1"]
.getService(Components.interfaces.nsIFormHistory2);
formHistory.removeAllEntries();
if (this.range)
formHistory.removeEntriesByTimeframe(this.range[0], this.range[1]);
else
formHistory.removeAllEntries();
},
get canClear()

View File

@ -197,7 +197,7 @@
<groupbox orient="vertical">
<caption label="&historySection.label;"/>
<hbox id="SanitizeDurationBox">
<hbox id="SanitizeDurationBox" align="center">
<label value="&clearDuration.label;" control="sanitizeDurationChoice" id="sanitizeDurationLabel"/>
<menulist id="sanitizeDurationChoice"
preference="privacy.sanitize.timeSpan">

View File

@ -69,18 +69,18 @@
<xul:tabbox anonid="tabbox" flex="1" eventnode="document" xbl:inherits="handleCtrlPageUpDown"
onselect="if (!('updateCurrentBrowser' in this.parentNode) || event.target.localName != 'tabpanels') return; this.parentNode.updateCurrentBrowser();">
<xul:hbox class="tab-drop-indicator-bar" collapsed="true" chromedir="&locale.dir;"
ondragover="this.parentNode.parentNode._onDragOver(event); event.stopPropagation();"
ondragleave="this.parentNode.parentNode._onDragLeave(event); event.stopPropagation();"
ondrop="this.parentNode.parentNode._onDrop(event); event.stopPropagation();">
ondragover="this.parentNode.parentNode._onDragOver(event);"
ondragleave="this.parentNode.parentNode._onDragLeave(event);"
ondrop="this.parentNode.parentNode._onDrop(event);">
<xul:hbox class="tab-drop-indicator" mousethrough="always"/>
</xul:hbox>
<xul:hbox class="tabbrowser-strip" collapsed="true" tooltip="_child" context="_child"
anonid="strip"
ondragstart="this.parentNode.parentNode._onDragStart(event); event.stopPropagation();"
ondragover="this.parentNode.parentNode._onDragOver(event); event.stopPropagation();"
ondrop="this.parentNode.parentNode._onDrop(event); event.stopPropagation();"
ondragend="this.parentNode.parentNode._onDragEnd(event); event.stopPropagation();"
ondragleave="this.parentNode.parentNode._onDragLeave(event); event.stopPropagation();">
ondragstart="this.parentNode.parentNode._onDragStart(event);"
ondragover="this.parentNode.parentNode._onDragOver(event);"
ondrop="this.parentNode.parentNode._onDrop(event);"
ondragend="this.parentNode.parentNode._onDragEnd(event);"
ondragleave="this.parentNode.parentNode._onDragLeave(event);">
<xul:tooltip onpopupshowing="return this.parentNode.parentNode.parentNode.createTooltip(event);"/>
<xul:menupopup anonid="tabContextMenu" onpopupshowing="this.parentNode.parentNode.parentNode.updatePopupMenu(this);">
<xul:menuitem id="context_newTab" label="&newTab.label;" accesskey="&newTab.accesskey;"
@ -194,14 +194,19 @@
<field name="mProgressListeners">
[]
</field>
<field name="mTabsProgressListeners">
[]
</field>
<field name="mTabListeners">
new Array()
[]
</field>
<field name="mTabFilters">
new Array()
[]
</field>
<!-- This field is obsolete and will be removed in a future release
FIXME: Remove for Firefox 4 -->
<field name="mTabbedMode">
false
true
</field>
<field name="mIsBusy">
false
@ -303,7 +308,12 @@
aCurSelfProgress, aMaxSelfProgress,
aCurTotalProgress, aMaxTotalProgress)
{
if (!this.mBlank && this.mTabBrowser.mCurrentTab == this.mTab) {
this.mTotalProgress = aMaxTotalProgress ? aCurTotalProgress / aMaxTotalProgress : 0;
if (this.mBlank)
return;
if (this.mTabBrowser.mCurrentTab == this.mTab) {
for (var i = 0; i < this.mTabBrowser.mProgressListeners.length; i++) {
var p = this.mTabBrowser.mProgressListeners[i];
if (p)
@ -318,7 +328,18 @@
}
}
this.mTotalProgress = aMaxTotalProgress ? aCurTotalProgress / aMaxTotalProgress : 0;
for (var i = 0; i < this.mTabBrowser.mTabsProgressListeners.length; i++) {
var p = this.mTabBrowser.mTabsProgressListeners[i];
if (p)
try {
p.onProgressChange(this.mBrowser, aWebProgress, aRequest,
aCurSelfProgress, aMaxSelfProgress,
aCurTotalProgress, aMaxTotalProgress);
} catch (e) {
// don't inhibit other listeners or following code
Components.utils.reportError(e);
}
}
},
onProgressChange64 : function (aWebProgress, aRequest,
@ -427,6 +448,17 @@
}
}
for (var i = 0; i < this.mTabBrowser.mTabsProgressListeners.length; i++) {
var p = this.mTabBrowser.mTabsProgressListeners[i];
if (p)
try {
p.onStateChange(this.mBrowser, aWebProgress, aRequest, aStateFlags, aStatus);
} catch (e) {
// don't inhibit other listeners or following code
Components.utils.reportError(e);
}
}
if (aStateFlags & (nsIWebProgressListener.STATE_START |
nsIWebProgressListener.STATE_STOP)) {
// reset cached temporary values at beginning and end
@ -450,7 +482,10 @@
// changing location, clear out the missing plugins list
this.mBrowser.missingPlugins = null;
if (!this.mBlank && this.mTabBrowser.mCurrentTab == this.mTab) {
if (this.mBlank)
return;
if (this.mTabBrowser.mCurrentTab == this.mTab) {
for (var i = 0; i < this.mTabBrowser.mProgressListeners.length; i++) {
var p = this.mTabBrowser.mProgressListeners[i];
if (p)
@ -462,6 +497,17 @@
}
}
}
for (var i = 0; i < this.mTabBrowser.mTabsProgressListeners.length; i++) {
var p = this.mTabBrowser.mTabsProgressListeners[i];
if (p)
try {
p.onLocationChange(this.mBrowser, aWebProgress, aRequest, aLocation);
} catch (e) {
// don't inhibit other listeners
Components.utils.reportError(e);
}
}
},
onStatusChange : function(aWebProgress, aRequest, aStatus, aMessage)
@ -482,6 +528,17 @@
}
}
for (var i = 0; i < this.mTabBrowser.mTabsProgressListeners.length; i++) {
var p = this.mTabBrowser.mTabsProgressListeners[i];
if (p)
try {
p.onStatusChange(this.mBrowser, aWebProgress, aRequest, aStatus, aMessage);
} catch (e) {
// don't inhibit other listeners or following code
Components.utils.reportError(e);
}
}
this.mMessage = aMessage;
},
@ -499,26 +556,52 @@
}
}
}
for (var i = 0; i < this.mTabBrowser.mTabsProgressListeners.length; i++) {
var p = this.mTabBrowser.mTabsProgressListeners[i];
if (p)
try {
p.onSecurityChange(this.mBrowser, aWebProgress, aRequest, aState);
} catch (e) {
// don't inhibit other listeners
Components.utils.reportError(e);
}
}
},
onRefreshAttempted : function(aWebProgress, aURI, aDelay, aSameURI)
{
var allowRefresh = true;
if (this.mTabBrowser.mCurrentTab == this.mTab) {
for (var i = 0; i < this.mTabBrowser.mProgressListeners.length; i++) {
var p = this.mTabBrowser.mProgressListeners[i];
if (p && "onRefreshAttempted" in p) {
try {
if (!p.onRefreshAttempted(aWebProgress, aURI, aDelay, aSameURI))
allowRefresh = false;
} catch (e) {
// don't inhibit other listeners or following code
Components.utils.reportError(e);
}
}
}
}
for (var i = 0; i < this.mTabBrowser.mTabsProgressListeners.length; i++) {
var p = this.mTabBrowser.mTabsProgressListeners[i];
if (p && "onRefreshAttempted" in p) {
try {
if (!p.onRefreshAttempted(this.mBrowser, aWebProgress, aURI, aDelay, aSameURI))
allowRefresh = false;
} catch (e) {
// don't inhibit other listeners or following code
Components.utils.reportError(e);
}
}
}
return allowRefresh;
},
onRefreshAttempted : function(aWebProgress, aURI, aDelay, aSameURI)
{
var allowRefresh = true;
for (var i = 0; i < this.mTabBrowser.mProgressListeners.length; i++) {
var p = this.mTabBrowser.mProgressListeners[i];
if (p && "onRefreshAttempted" in p) {
try {
if (!p.onRefreshAttempted(aWebProgress, aURI, aDelay, aSameURI))
allowRefresh = false;
} catch (e) {
// don't inhibit other listeners or following code
Components.utils.reportError(e);
}
}
}
return allowRefresh;
},
QueryInterface : function(aIID)
{
if (aIID.equals(Components.interfaces.nsIWebProgressListener) ||
@ -553,8 +636,21 @@
this.updateIcon(aTab);
for (var i = 0; i < this.mProgressListeners.length; i++) {
var p = this.mProgressListeners[i];
if (browser == this.mCurrentBrowser) {
for (var i = 0; i < this.mProgressListeners.length; i++) {
var p = this.mProgressListeners[i];
if ('onLinkIconAvailable' in p)
try {
p.onLinkIconAvailable(browser);
} catch (e) {
// don't inhibit other listeners
Components.utils.reportError(e);
}
}
}
for (var i = 0; i < this.mTabsProgressListeners.length; i++) {
var p = this.mTabsProgressListeners[i];
if ('onLinkIconAvailable' in p)
try {
p.onLinkIconAvailable(browser);
@ -1007,8 +1103,6 @@
// XXXdwh temporary unclean dependency on specific menu items in navigator.xul
document.getElementById("menu_closeWindow").hidden = false;
document.getElementById("menu_close").setAttribute("label", this.mStringBundle.getString("tabs.closeTab"));
if (!this.mTabbedMode)
this.enterTabbedMode();
}
else {
// XXXdwh temporary unclean dependency on specific menu items in navigator.xul
@ -1025,50 +1119,12 @@
</body>
</method>
<!-- This method is obsolete and will be removed in a future release
FIXME: Remove for Firefox 4 -->
<method name="enterTabbedMode">
<body>
<![CDATA[
this.mTabbedMode = true; // Welcome to multi-tabbed mode.
// Get the first tab all hooked up with a title listener and popup blocking listener.
this.mCurrentBrowser.addEventListener("DOMTitleChanged", this.onTitleChanged, true);
if (XULBrowserWindow.isBusy) {
this.mCurrentTab.setAttribute("busy", "true");
this.mIsBusy = true;
this.setTabTitleLoading(this.mCurrentTab);
this.updateIcon(this.mCurrentTab);
} else {
this.setTabTitle(this.mCurrentTab);
this.setIcon(this.mCurrentTab, this.mCurrentBrowser.mIconURL);
}
var filter;
if (this.mTabFilters.length > 0) {
// Use the filter hooked up in our addProgressListener
filter = this.mTabFilters[0];
} else {
// create a filter and hook it up to our first browser
filter = Components.classes["@mozilla.org/appshell/component/browser-status-filter;1"]
.createInstance(Components.interfaces.nsIWebProgress);
this.mTabFilters[0] = filter;
this.mCurrentBrowser.webProgress.addProgressListener(filter, Components.interfaces.nsIWebProgress.NOTIFY_ALL);
}
// Remove all our progress listeners from the active browser's filter.
for (var i = 0; i < this.mProgressListeners.length; i++) {
var p = this.mProgressListeners[i];
if (p)
filter.removeProgressListener(p);
}
// Wire up a progress listener to our filter.
const listener = this.mTabProgressListener(this.mCurrentTab,
this.mCurrentBrowser,
false);
filter.addProgressListener(listener, Components.interfaces.nsIWebProgress.NOTIFY_ALL);
this.mTabListeners[0] = listener;
]]>
Application.console.log("enterTabbedMode is an obsolete method and " +
"will be removed in a future release.");
</body>
</method>
@ -1146,9 +1202,6 @@
<![CDATA[
this._browsers = null; // invalidate cache
if (!this.mTabbedMode)
this.enterTabbedMode();
// if we're adding tabs, we're past interrupt mode, ditch the owner
if (this.mCurrentTab.owner)
this.mCurrentTab.owner = null;
@ -1685,30 +1738,7 @@
this.setStripVisibilityTo(true);
}
if (!this.mTabbedMode && this.mProgressListeners.length == 1) {
// If we are adding a 2nd progress listener, we need to enter tabbed mode
// because the browser status filter can only handle one progress listener.
// In tabbed mode, mTabProgressListener is used which will iterate over all listeners.
this.enterTabbedMode();
}
this.mProgressListeners.push(aListener);
if (!this.mTabbedMode) {
// If someone does this:
// addProgressListener, removeProgressListener, addProgressListener
// don't create a new filter; reuse the existing filter.
if (this.mTabFilters.length == 0) {
// hook a filter up to our first browser
const filter = Components.classes["@mozilla.org/appshell/component/browser-status-filter;1"]
.createInstance(Components.interfaces.nsIWebProgress);
this.mTabFilters[0] = filter;
this.mCurrentBrowser.webProgress.addProgressListener(filter, Components.interfaces.nsIWebProgress.NOTIFY_ALL);
}
// Directly hook the listener up to the filter for better performance
this.mTabFilters[0].addProgressListener(aListener, aMask);
}
]]>
</body>
</method>
@ -1723,14 +1753,28 @@
break;
}
}
if (!this.mTabbedMode)
// Don't forget to remove it from the filter we hooked it up to
this.mTabFilters[0].removeProgressListener(aListener);
]]>
</body>
</method>
<method name="addTabsProgressListener">
<parameter name="aListener"/>
<body>
this.mTabsProgressListeners.push(aListener);
</body>
</method>
<method name="removeTabsProgressListener">
<parameter name="aListener"/>
<body>
<![CDATA[
var pos = this.mTabsProgressListeners.indexOf(aListener);
if (pos >= 0)
this.mTabsProgressListeners.splice(pos, 1);
]]>
</body>
</method>
<method name="getBrowserForTab">
<parameter name="aTab"/>
<body>
@ -1798,6 +1842,10 @@
<parameter name="aEvent"/>
<body>
<![CDATA[
// don't interfere with toolbar customization
if (gNavToolbox.customizing)
return;
var target = aEvent.target;
if (target.localName == "tab" &&
aEvent.originalTarget.localName != "toolbarbutton") {
@ -1808,6 +1856,7 @@
var canvas = tabPreviews.capture(target, false);
dt.setDragImage(canvas, 0, 0);
aEvent.stopPropagation();
}
]]>
</body>
@ -1821,10 +1870,13 @@
]]></field>
<field name="_cachedTargetInToolbox">null</field>
<field name="_draggingOnItself">false</field>
<method name="_setEffectAllowedForDataTransfer">
<parameter name="aEvent"/>
<body>
<![CDATA[
this._draggingOnItself = false;
// Find out if the we're dragged over the toolbox
var target = aEvent.target;
var isInToolbox = target == this._cachedTargetInToolbox;
@ -1837,10 +1889,12 @@
target = target.parentNode;
}
// NOTE: within the toolbox, we don't touch effectAllowed for
// anything but tabs
var dt = aEvent.dataTransfer;
// Disallow dropping multiple items
if (dt.mozItemCount > 1)
return dt.effectAllowed = "none";
return isInToolbox ? "" : dt.effectAllowed = "none";
var types = dt.mozTypesAt(0);
var sourceNode = null;
@ -1856,6 +1910,7 @@
(aEvent.screenX >= sourceNode.boxObject.screenX &&
aEvent.screenX <= (sourceNode.boxObject.screenX +
sourceNode.boxObject.width))) {
this._draggingOnItself = true;
return dt.effectAllowed = "none";
}
@ -1869,9 +1924,9 @@
}
}
// only tab-drags are taken care off within the toolbox
if (!isInToolbox)
return dt.effectAllowed = "none";
// only tab-drags are taken care of within the toolbox
if (isInToolbox)
return ""; // see note above the tab-drags block
for (var i=0; i < this._supportedLinkDropTypes.length; i++) {
if (types.contains(this._supportedLinkDropTypes[i])) {
@ -1888,14 +1943,19 @@
<parameter name="aEvent"/>
<body>
<![CDATA[
// don't interfere with toolbar customization
if (gNavToolbox.customizing)
return;
var effects = this._setEffectAllowedForDataTransfer(aEvent);
var ib = this.mTabDropIndicatorBar;
if (effects == "none") {
if (effects == "" || effects == "none") {
ib.collapsed = "true";
return;
}
aEvent.preventDefault();
aEvent.stopPropagation();
var tabStrip = this.mTabContainer.mTabstrip;
var ltr = (window.getComputedStyle(this.parentNode, null).direction
@ -1989,16 +2049,22 @@
<parameter name="aEvent"/>
<body>
<![CDATA[
// don't interfere with toolbar customization
if (gNavToolbox.customizing)
return;
var dt = aEvent.dataTransfer;
var dropEffect = dt.dropEffect;
var draggedTab;
if (dropEffect != "link") { // copy or move
draggedTab = dt.mozGetDataAt("application/x-moz-tabbrowser-tab", 0);
NS_ASSERT(draggedTab && draggedTab.localName == "tab",
"copy or move action without a tab");
// not our drop then
if (!draggedTab)
return;
}
this.mTabDropIndicatorBar.collapsed = true;
aEvent.stopPropagation();
if (draggedTab && (dropEffect == "copy" ||
draggedTab.parentNode == this.mTabContainer)) {
@ -2107,10 +2173,11 @@
return;
var dt = aEvent.dataTransfer;
if (dt.dropEffect == "none") {
if (dt.dropEffect == "none" && !this._draggingOnItself) {
var draggedTab = dt.mozGetDataAt("application/x-moz-tabbrowser-tab", 0);
this._replaceTabWithWindow(draggedTab);
}
aEvent.stopPropagation();
]]>
</body>
</method>
@ -2145,6 +2212,8 @@
return;
this.mTabDropIndicatorBar.collapsed = true;
this._draggingOnItself = false;
aEvent.stopPropagation();
]]>
</body>
</method>
@ -2622,6 +2691,16 @@
this._autoScrollPopup = this.mCurrentBrowser._createAutoScrollPopup();
this.appendChild(this._autoScrollPopup);
this.mCurrentBrowser.setAttribute("autoscrollpopup", this._autoScrollPopup.id);
// Hook up the event listeners to the first browser
this.mCurrentBrowser.addEventListener("DOMTitleChanged", this.onTitleChanged, true);
var tabListener = this.mTabProgressListener(this.mCurrentTab, this.mCurrentBrowser, true);
const filter = Components.classes["@mozilla.org/appshell/component/browser-status-filter;1"]
.createInstance(Components.interfaces.nsIWebProgress);
filter.addProgressListener(tabListener, Components.interfaces.nsIWebProgress.NOTIFY_ALL);
this.mCurrentBrowser.webProgress.addProgressListener(filter, Components.interfaces.nsIWebProgress.NOTIFY_ALL);
this.mTabListeners[0] = tabListener;
this.mTabFilters[0] = filter;
]]>
</constructor>

View File

@ -78,6 +78,8 @@ _BROWSER_FILES = browser_bug321000.js \
plugin_test.html \
plugin_both.html \
plugin_both2.html \
browser_alltabslistener.js \
alltabslistener.html \
$(NULL)
ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))

View File

@ -0,0 +1,8 @@
<html>
<head>
<title>Test page for bug 463387</title>
</head>
<body>
<p>Test page for bug 463387</p>
</body>
</html>

View File

@ -0,0 +1,196 @@
const Ci = Components.interfaces;
const gCompleteState = Ci.nsIWebProgressListener.STATE_STOP +
Ci.nsIWebProgressListener.STATE_IS_NETWORK;
var gFrontProgressListener = {
onProgressChange: function (aWebProgress, aRequest,
aCurSelfProgress, aMaxSelfProgress,
aCurTotalProgress, aMaxTotalProgress) {
},
onStateChange: function (aWebProgress, aRequest, aStateFlags, aStatus) {
var state = "onStateChange";
ok(gFrontNotificationsPos < gFrontNotifications.length, "Got an expected notification for the front notifications listener");
is(state, gFrontNotifications[gFrontNotificationsPos], "Got a notification for the front notifications listener");
gFrontNotificationsPos++;
},
onLocationChange: function (aWebProgress, aRequest, aLocationURI) {
var state = "onLocationChange";
ok(gFrontNotificationsPos < gFrontNotifications.length, "Got an expected notification for the front notifications listener");
is(state, gFrontNotifications[gFrontNotificationsPos], "Got a notification for the front notifications listener");
gFrontNotificationsPos++;
},
onStatusChange: function (aWebProgress, aRequest, aStatus, aMessage) {
},
onSecurityChange: function (aWebProgress, aRequest, aState) {
var state = "onSecurityChange";
ok(gFrontNotificationsPos < gFrontNotifications.length, "Got an expected notification for the front notifications listener");
is(state, gFrontNotifications[gFrontNotificationsPos], "Got a notification for the front notifications listener");
gFrontNotificationsPos++;
}
}
var gAllProgressListener = {
onProgressChange: function (aBrowser, aWebProgress, aRequest,
aCurSelfProgress, aMaxSelfProgress,
aCurTotalProgress, aMaxTotalProgress) {
},
onStateChange: function (aBrowser, aWebProgress, aRequest, aStateFlags, aStatus) {
var state = "onStateChange";
ok(aBrowser == gTestBrowser, state + " notification came from the correct browser");
ok(gAllNotificationsPos < gAllNotifications.length, "Got an expected notification for the all notifications listener");
is(state, gAllNotifications[gAllNotificationsPos], "Got a notification for the all notifications listener");
gAllNotificationsPos++;
if ((aStateFlags & gCompleteState) == gCompleteState) {
ok(gAllNotificationsPos == gAllNotifications.length, "Saw the expected number of notifications");
ok(gFrontNotificationsPos == gFrontNotifications.length, "Saw the expected number of frontnotifications");
executeSoon(gNextTest);
}
},
onLocationChange: function (aBrowser, aWebProgress, aRequest, aLocationURI) {
var state = "onLocationChange";
ok(aBrowser == gTestBrowser, state + " notification came from the correct browser");
ok(gAllNotificationsPos < gAllNotifications.length, "Got an expected notification for the all notifications listener");
is(state, gAllNotifications[gAllNotificationsPos], "Got a notification for the all notifications listener");
gAllNotificationsPos++;
},
onStatusChange: function (aBrowser, aWebProgress, aRequest, aStatus, aMessage) {
var state = "onStatusChange";
ok(aBrowser == gTestBrowser, state + " notification came from the correct browser");
},
onSecurityChange: function (aBrowser, aWebProgress, aRequest, aState) {
var state = "onSecurityChange";
ok(aBrowser == gTestBrowser, state + " notification came from the correct browser");
ok(gAllNotificationsPos < gAllNotifications.length, "Got an expected notification for the all notifications listener");
is(state, gAllNotifications[gAllNotificationsPos], "Got a notification for the all notifications listener");
gAllNotificationsPos++;
}
}
var gFrontNotifications, gAllNotifications, gFrontNotificationsPos, gAllNotificationsPos;
var gBackgroundTab, gForegroundTab, gBackgroundBrowser, gForegroundBrowser, gTestBrowser;
var gTestPage = "/browser/browser/base/content/test/alltabslistener.html";
var gNextTest;
function test() {
waitForExplicitFinish();
gBackgroundTab = gBrowser.addTab("about:blank");
gForegroundTab = gBrowser.addTab("about:blank");
gBackgroundBrowser = gBrowser.getBrowserForTab(gBackgroundTab);
gForegroundBrowser = gBrowser.getBrowserForTab(gForegroundTab);
gBrowser.selectedTab = gForegroundTab;
// We must wait until the about:blank page has completed loading before
// starting tests or we get notifications from that
gForegroundBrowser.addEventListener("load", startTests, true);
}
function runTest(browser, url, next) {
gFrontNotificationsPos = 0;
gAllNotificationsPos = 0;
gNextTest = next;
gTestBrowser = browser;
browser.loadURI(url);
}
function startTests() {
gForegroundBrowser.removeEventListener("load", startTests, true);
executeSoon(startTest1);
}
function startTest1() {
gBrowser.addProgressListener(gFrontProgressListener);
gBrowser.addTabsProgressListener(gAllProgressListener);
gAllNotifications = [
"onStateChange",
"onLocationChange",
"onSecurityChange",
"onStateChange"
];
gFrontNotifications = gAllNotifications;
runTest(gForegroundBrowser, "http://example.org" + gTestPage, startTest2);
}
function startTest2() {
gAllNotifications = [
"onStateChange",
"onLocationChange",
"onSecurityChange",
"onSecurityChange",
"onStateChange"
];
gFrontNotifications = gAllNotifications;
runTest(gForegroundBrowser, "https://example.com" + gTestPage, startTest3);
}
function startTest3() {
gAllNotifications = [
"onStateChange",
"onLocationChange",
"onSecurityChange",
"onStateChange"
];
gFrontNotifications = [];
runTest(gBackgroundBrowser, "http://example.org" + gTestPage, startTest4);
}
function startTest4() {
gAllNotifications = [
"onStateChange",
"onLocationChange",
"onSecurityChange",
"onSecurityChange",
"onStateChange"
];
gFrontNotifications = [];
runTest(gBackgroundBrowser, "https://example.com" + gTestPage, startTest5);
}
function startTest5() {
// Switch the foreground browser
[gForegroundBrowser, gBackgroundBrowser] = [gBackgroundBrowser, gForegroundBrowser];
[gForegroundTab, gBackgroundTab] = [gBackgroundTab, gForegroundTab];
// Avoid the onLocationChange this will fire
gBrowser.removeProgressListener(gFrontProgressListener);
gBrowser.selectedTab = gForegroundTab;
gBrowser.addProgressListener(gFrontProgressListener);
gAllNotifications = [
"onStateChange",
"onLocationChange",
"onSecurityChange",
"onStateChange"
];
gFrontNotifications = gAllNotifications;
runTest(gForegroundBrowser, "http://example.org" + gTestPage, startTest6);
}
function startTest6() {
gAllNotifications = [
"onStateChange",
"onLocationChange",
"onSecurityChange",
"onStateChange"
];
gFrontNotifications = [];
runTest(gBackgroundBrowser, "http://example.org" + gTestPage, finishTest);
}
function finishTest() {
gBrowser.removeProgressListener(gFrontProgressListener);
gBrowser.removeTabsProgressListener(gAllProgressListener);
gBrowser.removeTab(gBackgroundTab);
gBrowser.removeTab(gForegroundTab);
finish();
}

View File

@ -4,6 +4,7 @@ var now_uSec = Date.now() * 1000;
const dm = Cc["@mozilla.org/download-manager;1"].getService(Ci.nsIDownloadManager);
const bhist = Cc["@mozilla.org/browser/global-history;2"].getService(Ci.nsIBrowserHistory);
const iosvc = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
const formhist = Cc["@mozilla.org/satchel/form-history;1"].getService(Ci.nsIFormHistory2);
Cc["@mozilla.org/moz/jssubscript-loader;1"].getService(Components.interfaces.mozIJSSubScriptLoader)
.loadSubScript("chrome://browser/content/sanitize.js");
@ -13,6 +14,7 @@ function test() {
var hoursSinceMidnight = new Date().getHours();
setupHistory();
setupFormHistory();
setupDownloads();
// Should test cookies here, but nsICookieManager/nsICookieService
@ -28,7 +30,7 @@ function test() {
itemPrefs.setBoolPref("downloads", true);
itemPrefs.setBoolPref("cache", false);
itemPrefs.setBoolPref("cookies", false);
itemPrefs.setBoolPref("formdata", false);
itemPrefs.setBoolPref("formdata", true);
itemPrefs.setBoolPref("offlineApps", false);
itemPrefs.setBoolPref("passwords", false);
itemPrefs.setBoolPref("sessions", false);
@ -46,6 +48,13 @@ function test() {
ok(bhist.isVisited(uri("http://today.com")), "Pretend visit to today.com should still exist");
ok(bhist.isVisited(uri("http://before-today.com")), "Pretend visit to before-today.com should still exist");
ok(!formhist.nameExists("1hour"), "1hour form entry should be deleted");
ok(formhist.nameExists("2hour"), "2hour form entry should still exist");
ok(formhist.nameExists("4hour"), "4hour form entry should still exist");
if(hoursSinceMidnight > 1)
ok(formhist.nameExists("today"), "today form entry should still exist");
ok(formhist.nameExists("b4today"), "b4today form entry should still exist");
ok(!downloadExists(5555551), "<1 hour download should now be deleted");
ok(downloadExists(5555550), "Year old download should still be present");
ok(downloadExists(5555552), "<2 hour old download should still be present");
@ -64,6 +73,13 @@ function test() {
ok(bhist.isVisited(uri("http://today.com")), "Pretend visit to today.com should still exist");
ok(bhist.isVisited(uri("http://before-today.com")), "Pretend visit to before-today.com should still exist");
ok(!formhist.nameExists("2hour"), "2hour form entry should be deleted");
ok(formhist.nameExists("4hour"), "4hour form entry should still exist");
if(hoursSinceMidnight > 2)
ok(formhist.nameExists("today"), "today form entry should still exist");
ok(formhist.nameExists("b4today"), "b4today form entry should still exist");
ok(formhist.nameExists("b4today"), "b4today form entry should still exist");
ok(!downloadExists(5555552), "<2 hour old download should now be deleted");
ok(downloadExists(5555550), "Year old download should still be present");
ok(downloadExists(5555553), "<4 hour old download should still be present");
@ -79,6 +95,11 @@ function test() {
ok(bhist.isVisited(uri("http://today.com")), "Pretend visit to today.com should still exist");
ok(bhist.isVisited(uri("http://before-today.com")), "Pretend visit to before-today.com should still exist");
ok(!formhist.nameExists("4hour"), "4hour form entry should be deleted");
if(hoursSinceMidnight > 4)
ok(formhist.nameExists("today"), "today form entry should still exist");
ok(formhist.nameExists("b4today"), "b4today form entry should still exist");
ok(!downloadExists(5555553), "<4 hour old download should now be deleted");
ok(downloadExists(5555550), "Year old download should still be present");
if(hoursSinceMidnight > 4)
@ -91,6 +112,9 @@ function test() {
ok(!bhist.isVisited(uri("http://today.com")), "Pretend visit to today.com should now be deleted");
ok(bhist.isVisited(uri("http://before-today.com")), "Pretend visit to before-today.com should still exist");
ok(!formhist.nameExists("today"), "today form entry should be deleted");
ok(formhist.nameExists("b4today"), "b4today form entry should still exist");
ok(!downloadExists(5555554), "'Today' download should now be deleted");
ok(downloadExists(5555550), "Year old download should still be present");
@ -99,6 +123,8 @@ function test() {
s.sanitize();
ok(!bhist.isVisited(uri("http://before-today.com")), "Pretend visit to before-today.com should now be deleted");
ok(!formhist.nameExists("b4today"), "b4today form entry should be deleted");
ok(!downloadExists(5555550), "Year old download should now be deleted");
@ -116,7 +142,7 @@ function setupHistory() {
bhist.addPageWithDetails(uri("http://today.com/"), "Today", today.valueOf() * 1000);
let lastYear = new Date();
lastYear.setFullYear(lastYear.year - 1);
lastYear.setFullYear(lastYear.getFullYear() - 1);
bhist.addPageWithDetails(uri("http://before-today.com/"), "Before Today", lastYear.valueOf() * 1000);
// Confirm everything worked
@ -127,6 +153,51 @@ function setupHistory() {
ok(bhist.isVisited(uri("http://before-today.com")), "Pretend visit to before-today.com should exist");
}
function setupFormHistory() {
// Make sure we've got a clean DB to start with.
formhist.removeAllEntries();
// Add the entries we'll be testing.
formhist.addEntry("1hour", "1h");
formhist.addEntry("2hour", "2h");
formhist.addEntry("4hour", "4h");
formhist.addEntry("today", "1d");
formhist.addEntry("b4today", "1y");
// Artifically age the entries to the proper vintage.
let db = formhist.DBConnection;
let timestamp = now_uSec - 45*60*1000000;
db.executeSimpleSQL("UPDATE moz_formhistory SET firstUsed = " +
timestamp + " WHERE fieldname = '1hour'");
timestamp = now_uSec - 90*60*1000000;
db.executeSimpleSQL("UPDATE moz_formhistory SET firstUsed = " +
timestamp + " WHERE fieldname = '2hour'");
timestamp = now_uSec - 180*60*1000000;
db.executeSimpleSQL("UPDATE moz_formhistory SET firstUsed = " +
timestamp + " WHERE fieldname = '4hour'");
let today = new Date();
today.setHours(0);
today.setMinutes(0);
today.setSeconds(1);
timestamp = today.valueOf() * 1000;
db.executeSimpleSQL("UPDATE moz_formhistory SET firstUsed = " +
timestamp + " WHERE fieldname = 'today'");
let lastYear = new Date();
lastYear.setFullYear(lastYear.getFullYear() - 1);
timestamp = lastYear.valueOf() * 1000;
db.executeSimpleSQL("UPDATE moz_formhistory SET firstUsed = " +
timestamp + " WHERE fieldname = 'b4today'");
// Sanity check.
ok(formhist.nameExists("1hour"), "Checking for 1hour form history entry creation");
ok(formhist.nameExists("2hour"), "Checking for 2hour form history entry creation");
ok(formhist.nameExists("4hour"), "Checking for 4hour form history entry creation");
ok(formhist.nameExists("today"), "Checking for today form history entry creation");
ok(formhist.nameExists("b4today"), "Checking for b4today form history entry creation");
}
function setupDownloads() {
// Add within-1-hour download to DB
@ -226,7 +297,7 @@ function setupDownloads() {
// Add "before today" download
let lastYear = new Date();
lastYear.setFullYear(lastYear.year - 1);
lastYear.setFullYear(lastYear.getFullYear() - 1);
data = {
id: "5555550",
name: "fakefile-old",

View File

@ -539,27 +539,32 @@ BrowserGlue.prototype = {
// ensurePlacesDefaultQueriesInitialized() is called by import.
this._prefs.setIntPref("browser.places.smartBookmarksVersion", 0);
// Get bookmarks folder
// Get bookmarks.html file location
var dirService = Cc["@mozilla.org/file/directory_service;1"].
getService(Ci.nsIProperties);
var bookmarksFile = dirService.get("BMarks", Ci.nsILocalFile);
// User wants to restore default bookmarks
if (restoreDefaultBookmarks || !bookmarksFile.exists()) {
// get bookmarks.html file from default profile folder
bookmarksFile = dirService.get("profDef", Ci.nsILocalFile);
bookmarksFile.append("bookmarks.html");
var bookmarksFile = null;
if (restoreDefaultBookmarks) {
// User wants to restore bookmarks.html file from default profile folder
bookmarksFile = dirService.get("profDef", Ci.nsILocalFile)
.append("bookmarks.html");
}
else
bookmarksFile = dirService.get("BMarks", Ci.nsILocalFile);
// import the file
try {
var importer = Cc["@mozilla.org/browser/places/import-export-service;1"].
getService(Ci.nsIPlacesImportExportService);
importer.importHTMLFromFile(bookmarksFile, true /* overwrite existing */);
} catch (err) {
// Report the error, but ignore it.
Cu.reportError(err);
if (bookmarksFile.exists()) {
// import the file
try {
var importer = Cc["@mozilla.org/browser/places/import-export-service;1"].
getService(Ci.nsIPlacesImportExportService);
importer.importHTMLFromFile(bookmarksFile, true /* overwrite existing */);
} catch (err) {
// Report the error, but ignore it.
Cu.reportError("Bookmarks.html file could be corrupt. " + err);
}
}
else
Cu.reportError("Unable to find bookmarks.html file.");
// Reset preferences, so we won't try to import again at next run
if (importBookmarksHTML)

View File

@ -154,6 +154,7 @@
newMarginTop += sbo.y - this._scrollBox.boxObject.y;
this._indicatorBar.firstChild.style.marginTop = newMarginTop + "px";
this._indicatorBar.hidden = false;
aEvent.stopPropagation();
]]></body>
</method>
@ -212,6 +213,7 @@
this._rootView._controller.setDataTransfer(aEvent);
this.setAttribute("dragstart", "true");
aEvent.stopPropagation();
]]></body>
</method>
@ -228,6 +230,7 @@
return;
PlacesControllerDragHelper.onDrop(dropPoint.ip);
aEvent.stopPropagation();
]]></body>
</method>
@ -521,7 +524,7 @@
window.XULBrowserWindow.setOverLink("", null);
]]></handler>
<handler event="draggesture" action="if (event.target.node) nsDragAndDrop.startDrag(event, this);"/>
<handler event="dragdrop" action="nsDragAndDrop.drop(event, this);"/>
<handler event="drop" action="nsDragAndDrop.drop(event, this);"/>
<handler event="dragover" action="nsDragAndDrop.dragOver(event, this);"/>
<handler event="dragexit" action="nsDragAndDrop.dragExit(event, this);"/>
</handlers>

View File

@ -1022,6 +1022,7 @@
this.focus();
this._controller.setDataTransfer(event);
event.stopPropagation();
]]></handler>
<handler event="dragover"><![CDATA[
@ -1029,6 +1030,7 @@
var dt = PlacesControllerDragHelper.currentDataTransfer =
event.dataTransfer;
var ib = this._dropIndicatorBar;
var ip = this.insertionPoint;
if (!ip || !PlacesControllerDragHelper.canDrop(ip)) {
ib.removeAttribute("dragging");
@ -1044,7 +1046,6 @@
this._ibTimer = null;
}
var ib = this._dropIndicatorBar;
if (dropPoint.folderNode ||
event.originalTarget == this._chevron) {
// Dropping over a menubutton or chevron button
@ -1101,21 +1102,31 @@
dt.effectAllowed = "all";
event.preventDefault();
event.stopPropagation();
]]></handler>
<handler event="drop"><![CDATA[
// If the data-transfer isn't cached, it's not ours
// This happens when dropping tabs
if (event.dataTransfer != PlacesControllerDragHelper.currentDataTransfer)
PlacesControllerDragHelper.currentDataTransfer = event.dataTransfer;
PlacesControllerDragHelper.currentDropTarget = event.target;
var ip = this.insertionPoint;
if (!ip || !PlacesControllerDragHelper.canDrop(ip))
return;
var dropPoint = this._getDropPoint(event);
if (!dropPoint)
return;
PlacesControllerDragHelper.onDrop(dropPoint.ip);
event.stopPropagation();
]]></handler>
<handler event="dragleave"><![CDATA[
// Only handle dragleaves for the toolbar itself (and not for its child
// nodes)
if (event.target != this)
return;
PlacesControllerDragHelper.currentDropTarget = null;
PlacesControllerDragHelper.currentDataTransfer = null;

View File

@ -1953,11 +1953,16 @@ SessionStoreService.prototype = {
return;
}
// always call this before injecting content into a document!
function hasExpectedURL(aDocument, aURL)
!aURL || aURL.replace(/#.*/, "") == aDocument.location.href.replace(/#.*/, "");
// restore text data saved by Firefox 2.0/3.0
var textArray = this.__SS_restore_text ? this.__SS_restore_text.split(" ") : [];
function restoreTextData(aContent, aPrefix) {
function restoreTextData(aContent, aPrefix, aURL) {
textArray.forEach(function(aEntry) {
if (/^((?:\d+\|)*)(#?)([^\s=]+)=(.*)$/.test(aEntry) && RegExp.$1 == aPrefix) {
if (/^((?:\d+\|)*)(#?)([^\s=]+)=(.*)$/.test(aEntry) &&
RegExp.$1 == aPrefix && hasExpectedURL(aContent.document, aURL)) {
var document = aContent.document;
var node = RegExp.$2 ? document.getElementById(RegExp.$3) : document.getElementsByName(RegExp.$3)[0] || null;
if (node && "value" in node) {
@ -1971,8 +1976,11 @@ SessionStoreService.prototype = {
});
}
function restoreFormData(aDocument, aData) {
function restoreFormData(aDocument, aData, aURL) {
for (let key in aData) {
if (!hasExpectedURL(aDocument, aURL))
return;
let node = key.charAt(0) == "#" ? aDocument.getElementById(key.slice(1)) :
XPathHelper.resolve(aDocument, key);
if (!node)
@ -2002,18 +2010,19 @@ SessionStoreService.prototype = {
}
let selectedPageStyle = this.__SS_restore_pageStyle;
let window = this.ownerDocument.defaultView;
function restoreTextDataAndScrolling(aContent, aData, aPrefix) {
if (aData.formdata)
restoreFormData(aContent.document, aData.formdata);
restoreFormData(aContent.document, aData.formdata, aData.url);
else
restoreTextData(aContent, aPrefix);
restoreTextData(aContent, aPrefix, aData.url);
if (aData.innerHTML) {
aContent.setTimeout(
function(aHTML) {
if (aContent.document.designMode == "on") {
aContent.document.body.innerHTML = aHTML;
}
}, 0, aData.innerHTML);
window.setTimeout(function() {
if (aContent.document.designMode == "on" &&
hasExpectedURL(aContent.document, aData.url)) {
aContent.document.body.innerHTML = aData.innerHTML;
}
}, 0);
}
if (aData.scroll && /(\d+),(\d+)/.test(aData.scroll)) {
aContent.scrollTo(RegExp.$1, RegExp.$2);
@ -2022,7 +2031,8 @@ SessionStoreService.prototype = {
aSS.disabled = aSS.title && aSS.title != selectedPageStyle;
});
for (var i = 0; i < aContent.frames.length; i++) {
if (aData.children && aData.children[i]) {
if (aData.children && aData.children[i] &&
hasExpectedURL(aContent.document, aData.url)) {
restoreTextDataAndScrolling(aContent.frames[i], aData.children[i], aPrefix + i + "|");
}
}
@ -2030,8 +2040,7 @@ SessionStoreService.prototype = {
// don't restore text data and scrolling state if the user has navigated
// away before the loading completed (except for in-page navigation)
if (!this.__SS_restore_data.url || this.currentURI.spec.replace(/#.*/, "") ==
this.__SS_restore_data.url.replace(/#.*/, "")) {
if (hasExpectedURL(aEvent.originalTarget, this.__SS_restore_data.url)) {
var content = aEvent.originalTarget.defaultView;
if (this.currentURI.spec == "about:config") {
// unwrap the document for about:config because otherwise the properties

View File

@ -584,6 +584,7 @@ components/nsXmlRpcClient.js
components/nsInterfaceInfoToIDL.js
components/nsScriptableIO.js
chrome/chromelist.txt
modules/JSON.jsm
#ifdef XP_MACOSX
LICENSE
extensions/inspector@mozilla.org/chrome/chromelist.txt

View File

@ -5306,7 +5306,7 @@ fi
dnl ========================================================
dnl = Disable Wave decoder support
dnl ========================================================
MOZ_ARG_ENABLE_BOOL(wave,
MOZ_ARG_DISABLE_BOOL(wave,
[ --disable-wave Disable Wave decoder support],
MOZ_WAVE=,
MOZ_WAVE=1)

View File

@ -63,7 +63,9 @@ class imgIContainer;
class nsDOMDataTransfer;
// mac uses click-hold context menus, a holdover from 4.x
#ifdef XP_MACOSX
// touch screens (like hildon) could use this also,
// perhaps we should move to NS_TOUCHSCREEN
#if defined(XP_MACOSX) || defined(NS_HILDON)
#define CLICK_HOLD_CONTEXT_MENUS 1
#endif

View File

@ -333,7 +333,7 @@ class nsOggDecoder : public nsMediaDecoder
// Called if the media file encounters a network error.
// Call on the main thread only.
void NetworkError();
virtual void NetworkError();
// Call from any thread safely. Return PR_TRUE if we are currently
// seeking in the media resource.
@ -348,21 +348,20 @@ class nsOggDecoder : public nsMediaDecoder
// Return PR_TRUE if seeking is supported.
virtual PRBool GetSeekable();
// Returns the channel reader.
nsChannelReader* GetReader() { return mReader; }
protected:
// Change to a new play state. This updates the mState variable and
// notifies any thread blocking on this objects monitor of the
// change. Can be called on any thread.
void ChangeState(PlayState aState);
// Returns the monitor for other threads to synchronise access to
// state
// state.
PRMonitor* GetMonitor()
{
return mMonitor;
}
// Return the current state. The caller must have entered the
// monitor.
// Return the current state. Can be called on any thread. If called from
// a non-main thread, the decoder monitor must be held.
PlayState GetState()
{
return mPlayState;
@ -373,6 +372,11 @@ protected:
* thread.
******/
// Change to a new play state. This updates the mState variable and
// notifies any thread blocking on this object's monitor of the
// change. Call on the main thread only.
void ChangeState(PlayState aState);
// Called when the metadata from the Ogg file has been read.
// Call on the main thread only.
void MetadataLoaded();
@ -486,7 +490,7 @@ private:
// the decoder thread, and the state machine for that thread keeps
// a pointer to this reader. This is safe as the only methods called
// are threadsafe (via the threadsafe nsMediaStream).
nsChannelReader* mReader;
nsAutoPtr<nsChannelReader> mReader;
// Monitor for detecting when the video play state changes. A call
// to Wait on this monitor will block the thread until the next
@ -499,11 +503,16 @@ private:
// must call NotifyAll on the monitor so the decode thread can wake up.
PlayState mPlayState;
// The state to change to after a seek or load operation. It is
// protected by the monitor mMonitor. This monitor must be acquired
// when reading or writing the state. Any change to the state must
// call NotifyAll on the monitor.
PlayState mNextState;
// The state to change to after a seek or load operation. It must only
// be changed from the main thread. The decoder monitor must be acquired
// when writing to the state, or when reading from a non-main thread.
// Any change to the state must call NotifyAll on the monitor.
PlayState mNextState;
// Flags if we've called Stop(). Prevents multiple events being
// sent to call Shutdown(). Accessed on the main thread
// only.
PRPackedBool mIsStopping;
};
#endif

View File

@ -71,7 +71,6 @@ OggPlayErrorCode nsChannelReader::initialise(int aBlock)
OggPlayErrorCode nsChannelReader::destroy()
{
mStream.Close();
return E_OGGPLAY_OK;
}
@ -113,9 +112,7 @@ static OggPlayErrorCode oggplay_channel_reader_initialise(OggPlayReader* aReader
static OggPlayErrorCode oggplay_channel_reader_destroy(OggPlayReader* aReader)
{
nsChannelReader* me = static_cast<nsChannelReader*>(aReader);
OggPlayErrorCode result = me->destroy();
delete me;
return result;
return me->destroy();
}
static size_t oggplay_channel_reader_io_read(void* aReader, void* aBuffer, size_t aCount)

View File

@ -128,13 +128,12 @@ nsresult nsDefaultStreamStrategy::Close()
if (mChannel) {
mChannel->Cancel(NS_BINDING_ABORTED);
mChannel = nsnull;
}
if (mPipeInput) {
mPipeInput->Close();
mPipeInput = nsnull;
mListener = nsnull;
}
mListener = nsnull;
return NS_OK;
}
@ -466,13 +465,12 @@ nsresult nsHttpStreamStrategy::Close()
if (mChannel) {
mChannel->Cancel(NS_BINDING_ABORTED);
mChannel = nsnull;
}
if (mPipeInput) {
mPipeInput->Close();
mPipeInput = nsnull;
mListener = nsnull;
}
mListener = nsnull;
return NS_OK;
}

View File

@ -215,7 +215,7 @@ public:
DECODER_STATE_SHUTDOWN
};
nsOggDecodeStateMachine(nsOggDecoder* aDecoder, nsChannelReader* aReader);
nsOggDecodeStateMachine(nsOggDecoder* aDecoder);
~nsOggDecodeStateMachine();
// Cause state transitions. These methods obtain the decoder monitor
@ -389,13 +389,6 @@ private:
PRInt32 mAudioChannels;
PRInt32 mAudioTrack;
// Channel Reader. Originally created by the mDecoder object, it is
// destroyed when we close the mPlayer handle in the
// destructor. Used to obtain download and playback rate information
// for buffering. Synchronisation for those methods are handled by
// nsMediaStream.
nsChannelReader* mReader;
// Time that buffering started. Used for buffering timeout and only
// accessed in the decoder thread.
PRIntervalTime mBufferingStart;
@ -461,7 +454,7 @@ private:
PRPackedBool mPositionChangeQueued;
};
nsOggDecodeStateMachine::nsOggDecodeStateMachine(nsOggDecoder* aDecoder, nsChannelReader* aReader) :
nsOggDecodeStateMachine::nsOggDecodeStateMachine(nsOggDecoder* aDecoder) :
mDecoder(aDecoder),
mPlayer(0),
mPlayStartTime(0),
@ -474,7 +467,6 @@ nsOggDecodeStateMachine::nsOggDecodeStateMachine(nsOggDecoder* aDecoder, nsChann
mAudioRate(0),
mAudioChannels(0),
mAudioTrack(-1),
mReader(aReader),
mBufferingStart(0),
mBufferingBytes(0),
mLastFrameTime(0),
@ -494,11 +486,9 @@ nsOggDecodeStateMachine::~nsOggDecodeStateMachine()
while (!mDecodedFrames.IsEmpty()) {
delete mDecodedFrames.Pop();
}
oggplay_close(mPlayer);
}
OggPlayErrorCode nsOggDecodeStateMachine::DecodeFrame()
{
NS_ASSERTION(mState > DECODER_STATE_DECODING_METADATA, "DecodeFrame() called during invalid state");
@ -853,6 +843,8 @@ void nsOggDecodeStateMachine::Seek(float aTime)
nsresult nsOggDecodeStateMachine::Run()
{
nsChannelReader* reader = mDecoder->GetReader();
NS_ENSURE_TRUE(reader, NS_ERROR_NULL_POINTER);
while (PR_TRUE) {
nsAutoMonitor mon(mDecoder->GetMonitor());
switch(mState) {
@ -902,8 +894,8 @@ nsresult nsOggDecodeStateMachine::Run()
case DECODER_STATE_DECODING:
{
// Before decoding check if we should buffer more data
if (mReader->DownloadRate() >= 0 &&
mReader->Available() < mReader->PlaybackRate() * BUFFERING_SECONDS_LOW_WATER_MARK) {
if (reader->DownloadRate() >= 0 &&
reader->Available() < reader->PlaybackRate() * BUFFERING_SECONDS_LOW_WATER_MARK) {
if (mDecoder->GetState() == nsOggDecoder::PLAY_STATE_PLAYING) {
if (mPlaying) {
StopPlayback();
@ -911,7 +903,7 @@ nsresult nsOggDecodeStateMachine::Run()
}
mBufferingStart = PR_IntervalNow();
mBufferingBytes = PRUint32(BUFFERING_RATE(mReader->PlaybackRate()) * BUFFERING_WAIT);
mBufferingBytes = PRUint32(BUFFERING_RATE(reader->PlaybackRate()) * BUFFERING_WAIT);
mState = DECODER_STATE_BUFFERING;
nsCOMPtr<nsIRunnable> event =
@ -1009,11 +1001,11 @@ nsresult nsOggDecodeStateMachine::Run()
case DECODER_STATE_BUFFERING:
if ((PR_IntervalToMilliseconds(PR_IntervalNow() - mBufferingStart) < BUFFERING_WAIT*1000) &&
mReader->DownloadRate() >= 0 &&
mReader->Available() < mBufferingBytes) {
reader->DownloadRate() >= 0 &&
reader->Available() < mBufferingBytes) {
LOG(PR_LOG_DEBUG,
("Buffering data until %d bytes available or %d milliseconds",
mBufferingBytes - mReader->Available(),
mBufferingBytes - reader->Available(),
BUFFERING_WAIT*1000 - (PR_IntervalToMilliseconds(PR_IntervalNow() - mBufferingStart))));
mon.Wait(PR_MillisecondsToInterval(1000));
if (mState == DECODER_STATE_SHUTDOWN)
@ -1069,7 +1061,7 @@ nsresult nsOggDecodeStateMachine::Run()
void nsOggDecodeStateMachine::LoadOggHeaders()
{
LOG(PR_LOG_DEBUG, ("Loading Ogg Headers"));
mPlayer = oggplay_open_with_reader(mReader);
mPlayer = oggplay_open_with_reader(mDecoder->GetReader());
if (mPlayer) {
LOG(PR_LOG_DEBUG, ("There are %d tracks", oggplay_get_num_tracks(mPlayer)));
@ -1184,7 +1176,8 @@ nsOggDecoder::nsOggDecoder() :
mReader(0),
mMonitor(0),
mPlayState(PLAY_STATE_PAUSED),
mNextState(PLAY_STATE_PAUSED)
mNextState(PLAY_STATE_PAUSED),
mIsStopping(PR_FALSE)
{
MOZ_COUNT_CTOR(nsOggDecoder);
}
@ -1239,6 +1232,10 @@ nsOggDecoder::~nsOggDecoder()
nsresult nsOggDecoder::Load(nsIURI* aURI, nsIChannel* aChannel,
nsIStreamListener** aStreamListener)
{
// Reset Stop guard flag flag, else shutdown won't occur properly when
// reusing decoder.
mIsStopping = PR_FALSE;
if (aStreamListener) {
*aStreamListener = nsnull;
}
@ -1270,7 +1267,7 @@ nsresult nsOggDecoder::Load(nsIURI* aURI, nsIChannel* aChannel,
rv = NS_NewThread(getter_AddRefs(mDecodeThread));
NS_ENSURE_SUCCESS(rv, rv);
mDecodeStateMachine = new nsOggDecodeStateMachine(this, mReader);
mDecodeStateMachine = new nsOggDecodeStateMachine(this);
{
nsAutoMonitor mon(mMonitor);
mDecodeStateMachine->SetContentLength(mContentLength);
@ -1326,6 +1323,13 @@ nsresult nsOggDecoder::PlaybackRateChanged()
void nsOggDecoder::Stop()
{
NS_ASSERTION(NS_IsMainThread(),
"nsOggDecoder::Stop called on non-main thread");
if (mIsStopping)
return;
mIsStopping = PR_TRUE;
ChangeState(PLAY_STATE_ENDED);
StopProgress();
@ -1334,7 +1338,6 @@ void nsOggDecoder::Stop()
// to prevent shutdown from deadlocking.
if (mReader) {
mReader->Cancel();
mReader = nsnull;
}
// Shutdown must be on called the mDecodeStateMachine before deleting.
@ -1353,6 +1356,7 @@ void nsOggDecoder::Stop()
}
mDecodeStateMachine = nsnull;
mReader = nsnull;
UnregisterShutdownObserver();
}
@ -1549,6 +1553,8 @@ void nsOggDecoder::UnregisterShutdownObserver()
void nsOggDecoder::ChangeState(PlayState aState)
{
NS_ASSERTION(NS_IsMainThread(),
"nsOggDecoder::ChangeState called on non-main thread");
nsAutoMonitor mon(mMonitor);
if (mNextState == aState) {

View File

@ -1025,7 +1025,7 @@ nsDOMWorker::CompileGlobalObject(JSContext* aCx)
NS_ASSERTION(!JS_GetGlobalObject(aCx), "Global object should be unset!");
nsRefPtr<nsDOMWorkerScope> scope = new nsDOMWorkerScope(this);
NS_ENSURE_TRUE(scope, NS_ERROR_OUT_OF_MEMORY);
NS_ENSURE_TRUE(scope, PR_FALSE);
nsISupports* scopeSupports = NS_ISUPPORTS_CAST(nsIWorkerScope*, scope);

View File

@ -45,10 +45,12 @@
<script type="application/x-javascript" src="chrome://reporter/content/reporterOverlay.js"/>
<!-- Firefox -->
<!-- Firefox and SeaMonkey -->
<broadcasterset id="mainBroadcasterSet">
<broadcaster id="reporterItemsBroadcaster" disabled="true"/>
</broadcasterset>
<!-- Firefox -->
<menupopup id="menu_HelpPopup">
<menuitem id="menu_HelpPopup_reportertoolmenu"
label="&reporterMenu2.title;"
@ -59,9 +61,6 @@
</menupopup>
<!-- SeaMonkey -->
<broadcasterset id="navBroadcasters">
<broadcaster id="reporterItemsBroadcaster" disabled="true"/>
</broadcasterset>
<menupopup id="helpPopup">
<menuseparator insertbefore="menu_HelpAboutSeparator"/>
<menuitem id="helpPopup_reportertoolmenu"

View File

@ -2796,8 +2796,6 @@ js_TraceStackFrame(JSTracer *trc, JSStackFrame *fp)
* Don't mark what has not been pushed yet, or what has been
* popped already.
*/
JS_ASSERT((size_t) (fp->regs->sp - fp->slots) <=
fp->script->nslots);
nslots = (uintN) (fp->regs->sp - fp->slots);
TRACE_JSVALS(trc, nslots, fp->slots, "slot");
}
@ -3677,7 +3675,7 @@ out:
goto restart;
}
if (rt->shapeGen & SHAPE_OVERFLOW_BIT) {
if (rt->shapeGen >= SHAPE_OVERFLOW_BIT - 1) {
/*
* FIXME bug 440834: The shape id space has overflowed. Currently we
* cope badly with this. Every call to js_GenerateShape does GC, and

View File

@ -85,17 +85,22 @@
#if !JS_LONE_INTERPRET ^ defined jsinvoke_cpp___
uint32
js_GenerateShape(JSContext *cx, JSBool gcLocked)
js_GenerateShape(JSContext *cx, JSBool gcLocked, JSScopeProperty *sprop)
{
JSRuntime *rt;
uint32 shape;
JSTempValueRooter tvr;
rt = cx->runtime;
shape = JS_ATOMIC_INCREMENT(&rt->shapeGen);
JS_ASSERT(shape != 0);
if (shape & SHAPE_OVERFLOW_BIT) {
rt->gcPoke = JS_TRUE;
if (sprop)
JS_PUSH_TEMP_ROOT_SPROP(cx, sprop, &tvr);
js_GC(cx, gcLocked ? GC_LOCK_HELD : GC_NORMAL);
if (sprop)
JS_POP_TEMP_ROOT(cx, &tvr);
shape = JS_ATOMIC_INCREMENT(&rt->shapeGen);
JS_ASSERT(shape != 0);
JS_ASSERT_IF(shape & SHAPE_OVERFLOW_BIT,

View File

@ -198,8 +198,12 @@ typedef struct JSInlineFrame {
#define SHAPE_OVERFLOW_BIT JS_BIT(32 - PCVCAP_TAGBITS)
/*
* When sprop is not null and the shape generation triggers the GC due to a
* shape overflow, the functions roots sprop.
*/
extern uint32
js_GenerateShape(JSContext *cx, JSBool gcLocked);
js_GenerateShape(JSContext *cx, JSBool gcLocked, JSScopeProperty *sprop);
struct JSPropCacheEntry {
jsbytecode *kpc; /* pc if vcap tag is <= 1, else atom */

View File

@ -4987,7 +4987,6 @@ js_DecompileValueGenerator(JSContext *cx, intN spindex, jsval v,
* it that caused exception, see bug 328664.
*/
stackBase = StackBase(fp);
JS_ASSERT((size_t) (regs->sp - stackBase) <= StackDepth(script));
sp = regs->sp;
do {
if (sp == stackBase) {
@ -4998,9 +4997,10 @@ js_DecompileValueGenerator(JSContext *cx, intN spindex, jsval v,
if (sp >= stackBase + pcdepth) {
/*
* This happens when the value comes from a temporary slot
* that the interpreter uses for GC roots. Assume that it is
* fp->pc that caused the exception.
* The value comes from a temporary slot that the interpreter
* uses for GC roots or when JSOP_APPLY extended the stack to
* fit the argument array elements. Assume that it is the
* current PC that caused the exception.
*/
pc = fp->imacpc ? fp->imacpc : regs->pc;
} else {

View File

@ -809,6 +809,7 @@ GetPropertyTreeChild(JSContext *cx, JSScopeProperty *parent,
JSScopeProperty *sprop;
PropTreeKidsChunk *chunk;
uintN i, n;
uint32 shape;
rt = cx->runtime;
if (!parent) {
@ -895,6 +896,12 @@ GetPropertyTreeChild(JSContext *cx, JSScopeProperty *parent,
}
locked_not_found:
/*
* Call js_GenerateShape before the allocation to prevent collecting the
* new property when the shape generation triggers the GC.
*/
shape = js_GenerateShape(cx, JS_TRUE, NULL);
sprop = NewScopeProperty(rt);
if (!sprop)
goto out_of_memory;
@ -907,7 +914,7 @@ locked_not_found:
sprop->flags = child->flags;
sprop->shortid = child->shortid;
sprop->parent = sprop->kids = NULL;
sprop->shape = js_GenerateShape(cx, JS_TRUE);
sprop->shape = shape;
if (!parent) {
entry->child = sprop;

View File

@ -221,7 +221,7 @@ JS_STATIC_ASSERT(offsetof(JSScope, title) == sizeof(JSObjectMap));
#define OBJ_SHAPE(obj) (OBJ_SCOPE(obj)->shape)
#define SCOPE_MAKE_UNIQUE_SHAPE(cx,scope) \
((scope)->shape = js_GenerateShape((cx), JS_FALSE))
((scope)->shape = js_GenerateShape((cx), JS_FALSE, NULL))
#define SCOPE_EXTEND_SHAPE(cx,scope,sprop) \
JS_BEGIN_MACRO \
@ -229,7 +229,7 @@ JS_STATIC_ASSERT(offsetof(JSScope, title) == sizeof(JSObjectMap));
(scope)->shape == (scope)->lastProp->shape) { \
(scope)->shape = (sprop)->shape; \
} else { \
(scope)->shape = js_GenerateShape((cx), JS_FALSE); \
(scope)->shape = js_GenerateShape((cx), JS_FALSE, sprop); \
} \
JS_END_MACRO

View File

@ -879,7 +879,6 @@ js_NativeStackSlots(JSContext *cx, unsigned callDepth)
#endif
for (;;) {
unsigned operands = fp->regs->sp - StackBase(fp);
JS_ASSERT(operands <= unsigned(fp->script->nslots - fp->script->nfixed));
slots += operands;
if (fp->callee)
slots += fp->script->nfixed;
@ -4018,7 +4017,6 @@ jsval&
TraceRecorder::stackval(int n) const
{
jsval* sp = cx->fp->regs->sp;
JS_ASSERT(size_t((sp + n) - StackBase(cx->fp)) < StackDepth(cx->fp->script));
return sp[n];
}

View File

@ -1,178 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla code.
*
* The Initial Developer of the Original Code is
* Simon Bünzli <zeniko@gmail.com>
* Portions created by the Initial Developer are Copyright (C) 2006-2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* 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 ***** */
/**
* Utilities for JavaScript code to handle JSON content.
* See http://www.json.org/ for comprehensive information about JSON.
*
* Import this module through
*
* Components.utils.import("resource://gre/modules/JSON.jsm");
*
* Usage:
*
* var newJSONString = JSONModule.toString( GIVEN_JAVASCRIPT_OBJECT );
* var newJavaScriptObject = JSONModule.fromString( GIVEN_JSON_STRING );
*
* Note: For your own safety, Objects/Arrays returned by
* JSONModule.fromString aren't instanceof Object/Array.
*/
var EXPORTED_SYMBOLS = ["JSONModule"];
// The following code is a loose adaption of Douglas Crockford's code
// from http://www.json.org/json.js (public domain'd)
// Notable differences:
// * Unserializable values such as |undefined| or functions aren't
// silently dropped but always lead to a TypeError.
// * An optional key blacklist has been added to JSON.toString
var JSONModule = {
/**
* Converts a JavaScript object into a JSON string.
*
* @param aJSObject is the object to be converted
* @param aKeysToDrop is an optional array of keys which will be
* ignored in all objects during the serialization
* @return the object's JSON representation
*
* Note: aJSObject MUST not contain cyclic references.
*/
toString: function JSON_toString(aJSObject, aKeysToDrop) {
// we use a single string builder for efficiency reasons
var pieces = [];
// this recursive function walks through all objects and appends their
// JSON representation (in one or several pieces) to the string builder
function append_piece(aObj) {
if (typeof aObj == "string") {
aObj = aObj.replace(/[\\"\x00-\x1F\u0080-\uFFFF]/g, function($0) {
// use the special escape notation if one exists, otherwise
// produce a general unicode escape sequence
switch ($0) {
case "\b": return "\\b";
case "\t": return "\\t";
case "\n": return "\\n";
case "\f": return "\\f";
case "\r": return "\\r";
case '"': return '\\"';
case "\\": return "\\\\";
}
return "\\u" + ("0000" + $0.charCodeAt(0).toString(16)).slice(-4);
});
pieces.push('"' + aObj + '"')
}
else if (typeof aObj == "boolean") {
pieces.push(aObj ? "true" : "false");
}
else if (typeof aObj == "number" && isFinite(aObj)) {
// there is no representation for infinite numbers or for NaN!
pieces.push(aObj.toString());
}
else if (aObj === null) {
pieces.push("null");
}
// if it looks like an array, treat it as such - this is required
// for all arrays from either outside this module or a sandbox
else if (aObj instanceof Array ||
typeof aObj == "object" && "length" in aObj &&
(aObj.length === 0 || aObj[aObj.length - 1] !== undefined)) {
pieces.push("[");
for (var i = 0; i < aObj.length; i++) {
arguments.callee(aObj[i]);
pieces.push(",");
}
if (aObj.length > 0)
pieces.pop(); // drop the trailing colon
pieces.push("]");
}
else if (typeof aObj == "object") {
pieces.push("{");
for (var key in aObj) {
// allow callers to pass objects containing private data which
// they don't want the JSON string to contain (so they don't
// have to manually pre-process the object)
if (aKeysToDrop && aKeysToDrop.indexOf(key) != -1)
continue;
arguments.callee(key.toString());
pieces.push(":");
arguments.callee(aObj[key]);
pieces.push(",");
}
if (pieces[pieces.length - 1] == ",")
pieces.pop(); // drop the trailing colon
pieces.push("}");
}
else {
throw new TypeError("No JSON representation for this object!");
}
}
append_piece(aJSObject);
return pieces.join("");
},
/**
* Converts a JSON string into a JavaScript object.
*
* @param aJSONString is the string to be converted
* @return a JavaScript object for the given JSON representation
*/
fromString: function JSON_fromString(aJSONString) {
if (!this.isMostlyHarmless(aJSONString))
throw new SyntaxError("No valid JSON string!");
var s = new Components.utils.Sandbox("about:blank");
return Components.utils.evalInSandbox("(" + aJSONString + ")", s);
},
/**
* Checks whether the given string contains potentially harmful
* content which might be executed during its evaluation
* (no parser, thus not 100% safe! Best to use a Sandbox for evaluation)
*
* @param aString is the string to be tested
* @return a boolean
*/
isMostlyHarmless: function JSON_isMostlyHarmless(aString) {
const maybeHarmful = /[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/;
const jsonStrings = /"(\\.|[^"\\\n\r])*"/g;
return !maybeHarmful.test(aString.replace(jsonStrings, ""));
}
};

View File

@ -56,7 +56,7 @@ REQUIRES = xpcom \
CPPSRCS = mozJSComponentLoader.cpp mozJSSubScriptLoader.cpp
EXTRA_JS_MODULES = XPCOMUtils.jsm JSON.jsm ISO8601DateUtils.jsm
EXTRA_JS_MODULES = XPCOMUtils.jsm ISO8601DateUtils.jsm
include $(topsrcdir)/config/rules.mk

View File

@ -1,131 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Simon Bünzli <zeniko@gmail.com>
* Portions created by the Initial Developer are Copyright (C) 2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* 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 ***** */
function run_test() {
// converts an object to a JSON string and tests its integrity
function toJSONString(a) {
var res = JSONModule.toString(a);
if (!JSONModule.isMostlyHarmless(res))
throw new SyntaxError("Invalid JSON string: " + res);
return res;
}
// ensures that an object can't be converted to a JSON string
function isInvalidType(a) {
try {
JSONModule.toString(a);
return false;
} catch (ex) {
return ex.name == "TypeError";
}
}
// ensures that a string can't be converted back to a JavaScript object
function isInvalidSyntax(a) {
try {
JSONModule.fromString(a);
return false;
} catch (ex) {
return ex.name == "SyntaxError";
}
}
Components.utils.import("resource://gre/modules/JSON.jsm");
do_check_eq(typeof(JSONModule), "object");
// some of the tests are adapted from /testing/mochitest/tests/test_Base.js
do_check_eq(toJSONString(true), "true");
do_check_eq(toJSONString(false), "false");
do_check_eq(toJSONString(1), "1");
do_check_eq(toJSONString(1.23), "1.23");
do_check_eq(toJSONString(1.23e-45), "1.23e-45");
do_check_true(isInvalidType(Infinity));
do_check_true(isInvalidType(NaN));
//XXXzeniko: using € instead of \u20ac fails because of encoding issues
do_check_eq(toJSONString("Foo-Bar \b\t\n\f\r\"\\ \x01\u20ac"),
'"Foo-Bar \\b\\t\\n\\f\\r\\"\\\\ \\u0001\\u20ac"');
do_check_eq(toJSONString(null), "null");
do_check_true(isInvalidType(undefined));
do_check_eq(toJSONString([1, "2", 3.3]), '[1,"2",3.3]');
// duck-typed Array (since we'll never really get something instanceof Array)
do_check_eq(toJSONString({ 0: 0, 1: "1", 2: -2.2, length: 3 }), '[0,"1",-2.2]');
var obj = { a: 1, b: "2", c: [-3e+30] };
do_check_eq(toJSONString(obj), '{"a":1,"b":"2","c":[-3e+30]}');
do_check_eq(JSONModule.toString(obj, ["b", "c"] /* keys to drop */), '{"a":1}');
do_check_true(isInvalidType(function() { }));
// make sure that toJSONString actually works...
do_check_eq(toJSONString(obj), JSONModule.toString(obj));
do_check_eq(JSONModule.fromString("true"), true);
do_check_eq(JSONModule.fromString("false"), false);
do_check_eq(JSONModule.fromString("1"), 1);
do_check_eq(JSONModule.fromString('"2.2"'), "2.2");
do_check_eq(JSONModule.fromString("1.23e-45"), 1.23e-45);
do_check_true(isInvalidSyntax("NaN"));
do_check_eq(JSONModule.fromString('"Foo-Bar \\b\\t\\n\\f\\r\\"\\\\ \\u0001\\u20ac"'),
"Foo-Bar \b\t\n\f\r\"\\ \x01\u20ac");
do_check_true(isInvalidSyntax('"multi\nline"'));
do_check_eq(JSONModule.fromString("null"), null);
do_check_true(isInvalidSyntax("."));
var res = JSONModule.fromString('[1,"2",3.3]');
do_check_eq(res.length, 3);
do_check_eq(res[2], 3.3);
// res is an instance of the sandbox's array
do_check_false(res instanceof Array);
res = JSONModule.fromString(toJSONString(obj));
do_check_eq(res.a, obj.a);
do_check_eq(res.b, obj.b);
do_check_eq(res.c.length, obj.c.length);
do_check_eq(res.c[0], obj.c[0]);
// those would throw on JSONModule.fromString if there's no object |a|
do_check_true(JSONModule.isMostlyHarmless("a"));
do_check_true(JSONModule.isMostlyHarmless("a[0]"));
do_check_true(JSONModule.isMostlyHarmless('a["alert(\\"P0wn3d!\\");"]'));
do_check_false(JSONModule.isMostlyHarmless('(function() { alert("P0wn3d!"); })()'));
do_check_false(JSONModule.isMostlyHarmless('{ get a() { return "P0wn3d!"; } }'));
}

View File

@ -2662,6 +2662,14 @@ nsLayoutUtils::GetClosestLayer(nsIFrame* aFrame)
return aFrame->PresContext()->PresShell()->FrameManager()->GetRootFrame();
}
/**
* Given an image being drawn into an appunit coordinate system, and
* a point in that coordinate system, map the point back into image
* pixel space.
* @param aSize the size of the image, in pixels
* @param aDest the rectangle that the image is being mapped into
* @param aPt a point in the same coordinate system as the rectangle
*/
static gfxPoint
MapToFloatImagePixels(const nsIntSize& aSize,
const nsRect& aDest, const nsPoint& aPt)
@ -2670,6 +2678,22 @@ MapToFloatImagePixels(const nsIntSize& aSize,
(gfxFloat(aPt.y - aDest.y)*aSize.height)/aDest.height);
}
/**
* Given an image being drawn into an pixel-based coordinate system, and
* a point in image space, map the point into the pixel-based coordinate
* system.
* @param aSize the size of the image, in pixels
* @param aDest the rectangle that the image is being mapped into
* @param aPt a point in image space
*/
static gfxPoint
MapToFloatUserPixels(const nsIntSize& aSize,
const gfxRect& aDest, const gfxPoint& aPt)
{
return gfxPoint(aPt.x*aDest.size.width/aSize.width + aDest.pos.x,
aPt.y*aDest.size.height/aSize.height + aDest.pos.y);
}
/* static */ nsresult
nsLayoutUtils::DrawImage(nsIRenderingContext* aRenderingContext,
imgIContainer* aImage,
@ -2733,15 +2757,22 @@ nsLayoutUtils::DrawImage(nsIRenderingContext* aRenderingContext,
// device unit!
gfxPoint anchorPoint(aAnchor.x/appUnitsPerDevPixel,
aAnchor.y/appUnitsPerDevPixel);
gfxPoint imageSpaceAnchorPoint =
MapToFloatImagePixels(imageSize, aDest, aAnchor);
gfxMatrix currentMatrix = ctx->CurrentMatrix();
gfxRect finalFillRect = fill;
if (didSnap) {
NS_ASSERTION(!currentMatrix.HasNonAxisAlignedTransform(),
"How did we snap, then?");
anchorPoint.x = fill.pos.x +
(anchorPoint.x - devPixelFill.pos.x)*fill.size.width/devPixelFill.size.width;
anchorPoint.y = fill.pos.y +
(anchorPoint.y - devPixelFill.pos.y)*fill.size.height/devPixelFill.size.height;
imageSpaceAnchorPoint.Round();
anchorPoint = imageSpaceAnchorPoint;
gfxRect devPixelDest(aDest.x/appUnitsPerDevPixel,
aDest.y/appUnitsPerDevPixel,
aDest.width/appUnitsPerDevPixel,
aDest.height/appUnitsPerDevPixel);
anchorPoint = MapToFloatUserPixels(imageSize, devPixelDest, anchorPoint);
anchorPoint = currentMatrix.Transform(anchorPoint);
anchorPoint.Round();
// This form of Transform is safe to call since non-axis-aligned
@ -2759,9 +2790,6 @@ nsLayoutUtils::DrawImage(nsIRenderingContext* aRenderingContext,
// to be aligned perfectly with pixel boundaries or the choice of
// dirty rect will affect the values of rendered pixels.
gfxPoint imageSpaceAnchorPoint =
MapToFloatImagePixels(imageSize, aDest, aAnchor);
imageSpaceAnchorPoint.Round();
gfxFloat scaleX = imageSize.width*appUnitsPerDevPixel/aDest.width;
gfxFloat scaleY = imageSize.height*appUnitsPerDevPixel/aDest.height;
if (didSnap) {

View File

@ -28,7 +28,7 @@ function cp()
function looop()
{
loopCount++;
if (loopCount < 20) {
if (loopCount < 10) {
ap();
} else {
document.body.textContent = "Done";

View File

@ -28,8 +28,8 @@
<div>
<div class="cell"><p>32 x 32</p><div style="width:32px; background-position:-16px -16px;" class="image"></div></div>
<div class="cell"><p>32.1 x 32</p><div style="width:32px; background-position:-16px -16px;" class="image"></div></div>
<div class="cell"><p>32.5 x 32</p><div style="width:33px; background-position:-15px -16px;" class="image"></div></div>
<div class="cell"><p>32.8 x 32</p><div style="width:33px; background-position:-15px -16px;" class="image"></div></div>
<div class="cell"><p>32.5 x 32</p><div style="width:33px; background-position:-16px -16px;" class="image"></div></div>
<div class="cell"><p>32.8 x 32</p><div style="width:33px; background-position:-16px -16px;" class="image"></div></div>
</div>
<div>
@ -42,8 +42,8 @@
<div>
<div class="cell"><p>32 x 32 </p><div style="height:32px; background-position:-16px -16px;" class="image"></div></div>
<div class="cell"><p>32 x 32.1 </p><div style="height:32px; background-position:-16px -16px;" class="image"></div></div>
<div class="cell"><p>32 x 32.5 </p><div style="height:33px; background-position:-16px -15px;" class="image"></div></div>
<div class="cell"><p>32 x 32.8 </p><div style="height:33px; background-position:-16px -15px;" class="image"></div></div>
<div class="cell"><p>32 x 32.5 </p><div style="height:33px; background-position:-16px -16px;" class="image"></div></div>
<div class="cell"><p>32 x 32.8 </p><div style="height:33px; background-position:-16px -16px;" class="image"></div></div>
</div>
</body></html>

View File

@ -0,0 +1,7 @@
<!DOCTYPE HTML>
<html>
<body>
<div style="background:url(mozilla-banner.gif); width:600px; height:58px;"></div>
<div style="margin-left: 100px; background:url(mozilla-banner.gif) -100px 0px; width:1px; height:58px;"></div>
</body>
</html>

View File

@ -0,0 +1,7 @@
<!DOCTYPE HTML>
<html>
<body>
<div style="background:url(mozilla-banner.gif); width:600px; height:58px;"></div>
<div style="margin-left: 100.4px; background:url(mozilla-banner.gif) -100.4px 0px; width:0.2px; height:58px;"></div>
</body>
</html>

View File

@ -960,3 +960,4 @@ fails-if(MOZ_WIDGET_TOOLKIT=="cocoa") == 456147.xul 456147-ref.html # bug 456147
fails == 461512-1.html 461512-1-ref.html # Bug 461512
== 463204-1.html 463204-1-ref.html
== 463217-1.xul 463217-1-ref.xul
== 464811-1.html 464811-1-ref.html

View File

@ -376,15 +376,8 @@ nsJAR::GetCertificatePrincipal(const char* aFilename, nsIPrincipal** aPrincipal)
return NS_ERROR_NULL_POINTER;
*aPrincipal = nsnull;
//-- Get the signature verifier service
nsresult rv;
nsCOMPtr<nsISignatureVerifier> verifier =
do_GetService(SIGNATURE_VERIFIER_CONTRACTID, &rv);
if (NS_FAILED(rv)) // No signature verifier available
return NS_OK;
//-- Parse the manifest
rv = ParseManifest(verifier);
nsresult rv = ParseManifest();
if (NS_FAILED(rv)) return rv;
if (mGlobalStatus == JAR_NO_MANIFEST)
return NS_OK;
@ -525,7 +518,7 @@ nsJAR::ReadLine(const char** src)
#define JAR_SF_HEADER (const char*)"Signature-Version: 1.0"
nsresult
nsJAR::ParseManifest(nsISignatureVerifier* verifier)
nsJAR::ParseManifest()
{
//-- Verification Step 1
if (mParsedManifest)
@ -612,6 +605,16 @@ nsJAR::ParseManifest(nsISignatureVerifier* verifier)
return NS_OK;
}
//-- Get the signature verifier service
nsCOMPtr<nsISignatureVerifier> verifier =
do_GetService(SIGNATURE_VERIFIER_CONTRACTID, &rv);
if (NS_FAILED(rv)) // No signature verifier available
{
mGlobalStatus = JAR_NO_MANIFEST;
mParsedManifest = PR_TRUE;
return NS_OK;
}
//-- Verify that the signature file is a valid signature of the SF file
PRInt32 verifyError;
rv = verifier->VerifySignature(sigBuffer, sigLen, manifestBuffer, manifestLen,

View File

@ -154,7 +154,7 @@ class nsJAR : public nsIZipReader, public nsIJAR
//-- Private functions
PRFileDesc* OpenFile();
nsresult ParseManifest(nsISignatureVerifier* verifier);
nsresult ParseManifest();
void ReportError(const char* aFilename, PRInt16 errorCode);
nsresult LoadEntry(const char* aFilename, char** aBuf,
PRUint32* aBufLen = nsnull);

View File

@ -50,7 +50,7 @@ interface mozIStorageConnection;
* autocomplete matches.
*/
[scriptable, uuid(d73f5924-3e39-4c67-8f4a-290b85448480)]
[scriptable, uuid(5d7d84d1-9798-4016-bf61-a32acf09b29d)]
interface nsIFormHistory2 : nsISupports
{
/**
@ -88,6 +88,16 @@ interface nsIFormHistory2 : nsISupports
*/
boolean entryExists(in AString name, in AString value);
/**
* Removes entries that were created between the specified times.
*
* @param aBeginTime
* The beginning of the timeframe, in microseconds
* @param aEndTime
* The end of the timeframe, in microseconds
*/
void removeEntriesByTimeframe(in long long aBeginTime, in long long aEndTime);
/**
* Returns the underlying DB connection the form history module is using.
*/

View File

@ -215,6 +215,12 @@ nsFormHistory::RemoveAllEntries()
return rv;
}
NS_IMETHODIMP
nsFormHistory::RemoveEntriesByTimeframe(PRInt64 aStartTime, PRInt64 aEndTime)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsFormHistory::GetDBConnection()
{

View File

@ -412,6 +412,27 @@ nsFormHistory::RemoveAllEntries()
}
NS_IMETHODIMP
nsFormHistory::RemoveEntriesByTimeframe(PRInt64 aStartTime, PRInt64 aEndTime)
{
nsCOMPtr<mozIStorageStatement> stmt;
nsresult rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
"DELETE FROM moz_formhistory "
"WHERE firstUsed >= ?1 "
"AND firstUsed <= ?2"), getter_AddRefs(stmt));
NS_ENSURE_SUCCESS(rv, rv);
// Bind the times and execute statement.
rv = stmt->BindInt64Parameter(0, aStartTime);
NS_ENSURE_SUCCESS(rv, rv);
rv = stmt->BindInt64Parameter(1, aEndTime);
NS_ENSURE_SUCCESS(rv, rv);
rv = stmt->Execute();
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
NS_IMETHODIMP
nsFormHistory::GetDBConnection(mozIStorageConnection **aResult)
{

View File

@ -0,0 +1,158 @@
/* ***** 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 Satchel Test Code.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2008
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Justin Dolske <dolske@mozilla.com> (Original Author)
*
* 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 ***** */
var testnum = 0;
var fh;
function run_test()
{
try {
// ===== test init =====
var testfile = do_get_file("toolkit/components/satchel/test/unit/formhistory_apitest.sqlite");
var profileDir = dirSvc.get("ProfD", Ci.nsIFile);
// Cleanup from any previous tests or failures.
var destFile = profileDir.clone();
destFile.append("formhistory.sqlite");
if (destFile.exists())
destFile.remove(false);
testfile.copyTo(profileDir, "formhistory.sqlite");
fh = Cc["@mozilla.org/satchel/form-history;1"].
getService(Ci.nsIFormHistory2);
// ===== 1 =====
// Check initial state is as expected
testnum++;
do_check_true(fh.hasEntries);
do_check_true(fh.nameExists("name-A"));
do_check_true(fh.nameExists("name-B"));
do_check_true(fh.nameExists("name-C"));
do_check_true(fh.nameExists("name-D"));
do_check_true(fh.entryExists("name-A", "value-A"));
do_check_true(fh.entryExists("name-B", "value-B1"));
do_check_true(fh.entryExists("name-B", "value-B2"));
do_check_true(fh.entryExists("name-C", "value-C"));
do_check_true(fh.entryExists("name-D", "value-D"));
// time-A/B/C/D checked below.
// ===== 2 =====
// Test looking for non-existant / bogus data.
testnum++;
do_check_false(fh.nameExists("blah"));
do_check_false(fh.nameExists(""));
do_check_false(fh.nameExists(null));
do_check_false(fh.entryExists("name-A", "blah"));
do_check_false(fh.entryExists("name-A", ""));
do_check_false(fh.entryExists("name-A", null));
do_check_false(fh.entryExists("blah", "value-A"));
do_check_false(fh.entryExists("", "value-A"));
do_check_false(fh.entryExists(null, "value-A"));
// ===== 3 =====
// Test removeEntriesForName with a single matching value
testnum++;
fh.removeEntriesForName("name-A");
do_check_false(fh.entryExists("name-A", "value-A"));
do_check_true(fh.entryExists("name-B", "value-B1"));
do_check_true(fh.entryExists("name-B", "value-B2"));
do_check_true(fh.entryExists("name-C", "value-C"));
do_check_true(fh.entryExists("name-D", "value-D"));
// ===== 4 =====
// Test removeEntriesForName with multiple matching values
testnum++;
fh.removeEntriesForName("name-B");
do_check_false(fh.entryExists("name-A", "value-A"));
do_check_false(fh.entryExists("name-B", "value-B1"));
do_check_false(fh.entryExists("name-B", "value-B2"));
do_check_true(fh.entryExists("name-C", "value-C"));
do_check_true(fh.entryExists("name-D", "value-D"));
// ===== 5 =====
// Test removing by time range (single entry, not surrounding entries)
testnum++;
do_check_true(fh.nameExists("time-A")); // firstUsed=1000, lastUsed=1000
do_check_true(fh.nameExists("time-B")); // firstUsed=1000, lastUsed=1099
do_check_true(fh.nameExists("time-C")); // firstUsed=1099, lastUsed=1099
do_check_true(fh.nameExists("time-D")); // firstUsed=2001, lastUsed=2001
fh.removeEntriesByTimeframe(1050, 2000);
do_check_true(fh.nameExists("time-A"));
do_check_true(fh.nameExists("time-B"));
do_check_false(fh.nameExists("time-C"));
do_check_true(fh.nameExists("time-D"));
// ===== 6 =====
// Test removing by time range (multiple entries)
testnum++;
fh.removeEntriesByTimeframe(1000, 2000);
do_check_false(fh.nameExists("time-A"));
do_check_false(fh.nameExists("time-B"));
do_check_false(fh.nameExists("time-C"));
do_check_true(fh.nameExists("time-D"));
// ===== 7 =====
// test removeAllEntries
testnum++;
fh.removeAllEntries();
do_check_false(fh.hasEntries);
do_check_false(fh.nameExists("name-C"));
do_check_false(fh.nameExists("name-D"));
do_check_false(fh.entryExists("name-C", "value-C"));
do_check_false(fh.entryExists("name-D", "value-D"));
// ===== 8 =====
// Add a single entry back
testnum++;
fh.addEntry("newname-A", "newvalue-A");
do_check_true(fh.hasEntries);
do_check_true(fh.entryExists("newname-A", "newvalue-A"));
// ===== 9 =====
// Remove the single entry
testnum++;
fh.removeEntry("newname-A", "newvalue-A");
do_check_false(fh.hasEntries);
do_check_false(fh.entryExists("newname-A", "newvalue-A"));
} catch (e) {
throw "FAILED in test #" + testnum + " -- " + e;
}
}

View File

@ -204,6 +204,8 @@ var gUpdates = {
bnf.hidden = !nextFinishButtonString;
be1.hidden = !extra1ButtonString;
be2.hidden = !extra2ButtonString;
// Hide the back button each time setButtons is called (see bug 464765)
this.wiz.getButton("back").hidden = true;
},
getAUSString: function(key, strings) {
@ -328,7 +330,6 @@ var gUpdates = {
this._cacheButtonStrings("extra1");
this._cacheButtonStrings("extra2");
this.wiz.getButton("back").hidden = true;
this.wiz.getButton("cancel").hidden = true;
// Advance to the Start page.
@ -740,7 +741,6 @@ var gUpdatesAvailablePage = {
updateTypeElement.setAttribute("severity", severity);
var moreInfoContent = document.getElementById("moreInfoContent");
var moreInfoURL = document.getElementById("moreInfoURL");
var intro;
if (severity == "major") {
// for major updates, use the brandName and the version for the intro
@ -754,8 +754,8 @@ var gUpdatesAvailablePage = {
remoteContent.update_version = gUpdates.update.version;
remoteContent.url = gUpdates.update.detailsURL;
moreInfoURL.hidden = true;
moreInfoContent.hidden = false;
document.getElementById("moreInfoURL").hidden = true;
document.getElementById("updateName").hidden = true;
document.getElementById("updateNameSep").hidden = true;
document.getElementById("upgradeEvangelism").hidden = true;
@ -778,9 +778,8 @@ var gUpdatesAvailablePage = {
// This element when hidden still receives focus events which will
// cause assertions with debug builds so remove it if it isn't used.
moreInfoContent.parentNode.removeChild(moreInfoContent);
var moreInfoURL = document.getElementById("updateMoreInfoURL");
moreInfoURL.setAttribute("url", gUpdates.update.detailsURL);
moreInfoURL.hidden = false;
var updateMoreInfoURL = document.getElementById("updateMoreInfoURL");
updateMoreInfoURL.setAttribute("url", gUpdates.update.detailsURL);
}
updateTypeElement.textContent = intro;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 565 B

After

Width:  |  Height:  |  Size: 927 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 732 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 759 B

After

Width:  |  Height:  |  Size: 823 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 844 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 539 B

After

Width:  |  Height:  |  Size: 638 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 544 B

After

Width:  |  Height:  |  Size: 699 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 971 B

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 895 B

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 654 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 664 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 971 B

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 895 B

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -7882,7 +7882,7 @@ nsWindow :: DealWithPopups ( HWND inWnd, UINT inMsg, WPARAM inWParam, LPARAM inL
inMsg == WM_MOUSEACTIVATE ||
inMsg == WM_ACTIVATEAPP ||
inMsg == WM_MENUSELECT ||
// Non-toplevel windows normally don't get WM_GETMINMAXINFO.
// Non-toplevel windows normally don't get WM_GETMINMAXINFO.
// Therefore if a non-toplevel window gets this message, we should ignore it.
(inMsg == WM_GETMINMAXINFO && !::GetParent(inWnd))
#endif
@ -7944,6 +7944,9 @@ nsWindow :: DealWithPopups ( HWND inWnd, UINT inMsg, WPARAM inWParam, LPARAM inL
else
#endif
if ( rollup ) {
// gRollupConsumeRollupEvent may be modified by
// nsIRollupListener::Rollup.
PRBool consumeRollupEvent = gRollupConsumeRollupEvent;
// only need to deal with the last rollup for left mouse down events.
gRollupListener->Rollup(inMsg == WM_LBUTTONDOWN ? &mLastRollup : nsnull);
@ -7956,7 +7959,7 @@ nsWindow :: DealWithPopups ( HWND inWnd, UINT inMsg, WPARAM inWParam, LPARAM inL
// false allows the event to be dispatched
//
// So if we are NOT supposed to be consuming events, let it go through
if (gRollupConsumeRollupEvent && inMsg != WM_RBUTTONDOWN) {
if (consumeRollupEvent && inMsg != WM_RBUTTONDOWN) {
*outResult = TRUE;
return TRUE;
}

View File

@ -91,6 +91,7 @@
#include "nsAppShellCID.h"
#include "nsReadableUtils.h"
#include "nsStyleConsts.h"
#include "nsPresContext.h"
#include "nsWebShellWindow.h" // get rid of this one, too...
@ -577,8 +578,14 @@ NS_IMETHODIMP nsXULWindow::SetSize(PRInt32 aCX, PRInt32 aCY, PRBool aRepaint)
mWindow->SetSizeMode(nsSizeMode_Normal);
mIntrinsicallySized = PR_FALSE;
PRInt32 devX = NSAppUnitsToIntPixels(nsPresContext::CSSPixelsToAppUnits(aCX),
float(mWindow->GetDeviceContext()->
AppUnitsPerDevPixel()));
PRInt32 devY = NSAppUnitsToIntPixels(nsPresContext::CSSPixelsToAppUnits(aCY),
float(mWindow->GetDeviceContext()->
AppUnitsPerDevPixel()));
NS_ENSURE_SUCCESS(mWindow->Resize(aCX, aCY, aRepaint), NS_ERROR_FAILURE);
NS_ENSURE_SUCCESS(mWindow->Resize(devX, devY, aRepaint), NS_ERROR_FAILURE);
PersistentAttributesDirty(PAD_SIZE);
SavePersistentAttributes();
return NS_OK;