Merge mozilla-central into tracemonkey
@ -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()
|
||||
{
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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()
|
||||
|
@ -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">
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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)))
|
||||
|
8
browser/base/content/test/alltabslistener.html
Normal 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>
|
196
browser/base/content/test/browser_alltabslistener.js
Normal 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();
|
||||
}
|
@ -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",
|
||||
|
@ -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)
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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 */
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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];
|
||||
}
|
||||
|
||||
|
@ -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, ""));
|
||||
}
|
||||
};
|
@ -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
|
||||
|
||||
|
@ -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!"; } }'));
|
||||
}
|
@ -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) {
|
||||
|
@ -28,7 +28,7 @@ function cp()
|
||||
function looop()
|
||||
{
|
||||
loopCount++;
|
||||
if (loopCount < 20) {
|
||||
if (loopCount < 10) {
|
||||
ap();
|
||||
} else {
|
||||
document.body.textContent = "Done";
|
||||
|
@ -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>
|
||||
|
7
layout/reftests/bugs/464811-1-ref.html
Normal 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>
|
7
layout/reftests/bugs/464811-1.html
Normal 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>
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
|
BIN
toolkit/components/satchel/test/unit/formhistory_apitest.sqlite
Normal file
158
toolkit/components/satchel/test/unit/test_history_api.js
Normal 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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
||||
|
Before Width: | Height: | Size: 565 B After Width: | Height: | Size: 927 B |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.6 KiB |
BIN
toolkit/themes/gnomestripe/mozapps/plugins/pluginDisabled-16.png
Normal file
After Width: | Height: | Size: 732 B |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 759 B After Width: | Height: | Size: 823 B |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 2.1 KiB |
BIN
toolkit/themes/pinstripe/mozapps/plugins/pluginDisabled-16.png
Normal file
After Width: | Height: | Size: 844 B |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 539 B After Width: | Height: | Size: 638 B |
Before Width: | Height: | Size: 544 B After Width: | Height: | Size: 699 B |
BIN
toolkit/themes/winstripe/mozapps/plugins/pluginBlocked-aero.png
Executable file → Normal file
Before Width: | Height: | Size: 971 B After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 895 B After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 654 B |
BIN
toolkit/themes/winstripe/mozapps/plugins/pluginDisabled-16.png
Normal file
After Width: | Height: | Size: 664 B |
BIN
toolkit/themes/winstripe/mozapps/plugins/pluginDisabled-aero.png
Executable file → Normal file
Before Width: | Height: | Size: 971 B After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 895 B After Width: | Height: | Size: 1.3 KiB |
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|