mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 13:51:41 +00:00
Merge m-c to bs.
This commit is contained in:
commit
225c13b333
@ -306,7 +306,7 @@ already_AddRefed<nsRootAccessible> nsAccessNode::GetRootAccessible()
|
||||
}
|
||||
|
||||
nsIFrame*
|
||||
nsAccessNode::GetFrame()
|
||||
nsAccessNode::GetFrame() const
|
||||
{
|
||||
return mContent ? mContent->GetPrimaryFrame() : nsnull;
|
||||
}
|
||||
|
@ -135,10 +135,10 @@ public:
|
||||
*/
|
||||
virtual void Shutdown();
|
||||
|
||||
/**
|
||||
* Return frame for the given access node object.
|
||||
*/
|
||||
virtual nsIFrame* GetFrame();
|
||||
/**
|
||||
* Return frame for the given access node object.
|
||||
*/
|
||||
virtual nsIFrame* GetFrame() const;
|
||||
|
||||
/**
|
||||
* Return DOM node associated with this accessible.
|
||||
|
@ -359,6 +359,8 @@ public:
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Downcasting
|
||||
|
||||
inline bool IsApplication() const { return mFlags & eApplicationAccessible; }
|
||||
|
||||
inline bool IsHyperText() const { return mFlags & eHyperTextAccessible; }
|
||||
nsHyperTextAccessible* AsHyperText();
|
||||
|
||||
@ -505,8 +507,9 @@ protected:
|
||||
* @note keep these flags in sync with ChildrenFlags
|
||||
*/
|
||||
enum AccessibleTypes {
|
||||
eHyperTextAccessible = 1 << 2,
|
||||
eTextLeafAccessible = 1 << 3
|
||||
eApplicationAccessible = 1 << 2,
|
||||
eHyperTextAccessible = 1 << 3,
|
||||
eTextLeafAccessible = 1 << 4
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -55,6 +55,7 @@
|
||||
nsApplicationAccessible::nsApplicationAccessible() :
|
||||
nsAccessibleWrap(nsnull, nsnull)
|
||||
{
|
||||
mFlags |= eApplicationAccessible;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -681,7 +681,7 @@ nsDocAccessible::Shutdown()
|
||||
}
|
||||
|
||||
nsIFrame*
|
||||
nsDocAccessible::GetFrame()
|
||||
nsDocAccessible::GetFrame() const
|
||||
{
|
||||
nsCOMPtr<nsIPresShell> shell(do_QueryReferent(mWeakShell));
|
||||
|
||||
|
@ -108,7 +108,7 @@ public:
|
||||
// nsAccessNode
|
||||
virtual PRBool Init();
|
||||
virtual void Shutdown();
|
||||
virtual nsIFrame* GetFrame();
|
||||
virtual nsIFrame* GetFrame() const;
|
||||
virtual PRBool IsDefunct();
|
||||
virtual nsINode* GetNode() const { return mDocument; }
|
||||
virtual nsIDocument* GetDocumentNode() const { return mDocument; }
|
||||
|
@ -871,7 +871,7 @@ nsHTMLComboboxListAccessible::
|
||||
// nsHTMLComboboxAccessible: nsAccessNode
|
||||
|
||||
nsIFrame*
|
||||
nsHTMLComboboxListAccessible::GetFrame()
|
||||
nsHTMLComboboxListAccessible::GetFrame() const
|
||||
{
|
||||
nsIFrame* frame = nsHTMLSelectListAccessible::GetFrame();
|
||||
|
||||
|
@ -228,7 +228,7 @@ public:
|
||||
virtual ~nsHTMLComboboxListAccessible() {}
|
||||
|
||||
// nsAccessNode
|
||||
virtual nsIFrame* GetFrame();
|
||||
virtual nsIFrame* GetFrame() const;
|
||||
virtual bool IsPrimaryForNode() const;
|
||||
|
||||
// nsAccessible
|
||||
|
@ -215,11 +215,13 @@ __try {
|
||||
}
|
||||
|
||||
nsAccessible* xpParentAcc = GetParent();
|
||||
NS_ASSERTION(xpParentAcc,
|
||||
"No parent accessible where we're not direct child of window");
|
||||
if (!xpParentAcc) {
|
||||
if (IsApplication())
|
||||
return S_OK;
|
||||
|
||||
if (!xpParentAcc)
|
||||
NS_ERROR("No parent accessible. Should we really assert here?");
|
||||
return E_UNEXPECTED;
|
||||
}
|
||||
|
||||
*ppdispParent = NativeAccessible(xpParentAcc);
|
||||
|
||||
@ -1370,12 +1372,7 @@ __try {
|
||||
if (IsDefunct())
|
||||
return E_FAIL;
|
||||
|
||||
void *handle = nsnull;
|
||||
nsresult rv = GetOwnerWindow(&handle);
|
||||
if (NS_FAILED(rv))
|
||||
return GetHRESULT(rv);
|
||||
|
||||
*aWindowHandle = reinterpret_cast<HWND>(handle);
|
||||
*aWindowHandle = GetHWNDFor(this);
|
||||
return S_OK;
|
||||
|
||||
} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
|
||||
@ -1532,6 +1529,7 @@ NS_IMETHODIMP nsAccessibleWrap::GetNativeInterface(void **aOutAccessible)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsAccessible
|
||||
|
||||
nsresult
|
||||
@ -1543,6 +1541,9 @@ nsAccessibleWrap::HandleAccEvent(AccEvent* aEvent)
|
||||
return FirePlatformEvent(aEvent);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsAccessibleWrap
|
||||
|
||||
nsresult
|
||||
nsAccessibleWrap::FirePlatformEvent(AccEvent* aEvent)
|
||||
{
|
||||
@ -1622,11 +1623,35 @@ PRInt32 nsAccessibleWrap::GetChildIDFor(nsAccessible* aAccessible)
|
||||
HWND
|
||||
nsAccessibleWrap::GetHWNDFor(nsAccessible *aAccessible)
|
||||
{
|
||||
if (!aAccessible)
|
||||
return 0;
|
||||
if (aAccessible) {
|
||||
// Popup lives in own windows, use its HWND until the popup window is
|
||||
// hidden to make old JAWS versions work with collapsed comboboxes (see
|
||||
// discussion in bug 379678).
|
||||
nsIFrame* frame = aAccessible->GetFrame();
|
||||
if (frame) {
|
||||
nsIWidget* widget = frame->GetNearestWidget();
|
||||
PRBool isVisible = PR_FALSE;
|
||||
widget->IsVisible(isVisible);
|
||||
if (isVisible) {
|
||||
nsCOMPtr<nsIPresShell> shell(aAccessible->GetPresShell());
|
||||
nsIViewManager* vm = shell->GetViewManager();
|
||||
if (vm) {
|
||||
nsCOMPtr<nsIWidget> rootWidget;
|
||||
vm->GetRootWidget(getter_AddRefs(rootWidget));
|
||||
// Make sure the accessible belongs to popup. If not then use
|
||||
// document HWND (which might be different from root widget in the
|
||||
// case of window emulation).
|
||||
if (rootWidget != widget)
|
||||
return static_cast<HWND>(widget->GetNativeData(NS_NATIVE_WINDOW));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsDocAccessible* document = aAccessible->GetDocAccessible();
|
||||
return document ? static_cast<HWND>(document->GetNativeWindow()) : 0;
|
||||
nsDocAccessible* document = aAccessible->GetDocAccessible();
|
||||
if (document)
|
||||
return static_cast<HWND>(document->GetNativeWindow());
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
|
@ -60,15 +60,15 @@ let TabView = {
|
||||
// ----------
|
||||
set firstUseExperienced(val) {
|
||||
if (val != this._firstUseExperienced)
|
||||
Services.prefs.setBoolPref("browser.panorama.experienced_first_use", val);
|
||||
Services.prefs.setBoolPref("browser.panorama.experienced_first_run", val);
|
||||
},
|
||||
|
||||
// ----------
|
||||
init: function TabView_init() {
|
||||
if (!Services.prefs.prefHasUserValue("browser.panorama.experienced_first_use") ||
|
||||
!Services.prefs.getBoolPref("browser.panorama.experienced_first_use")) {
|
||||
if (!Services.prefs.prefHasUserValue("browser.panorama.experienced_first_run") ||
|
||||
!Services.prefs.getBoolPref("browser.panorama.experienced_first_run")) {
|
||||
Services.prefs.addObserver(
|
||||
"browser.panorama.experienced_first_use", this, false);
|
||||
"browser.panorama.experienced_first_run", this, false);
|
||||
} else {
|
||||
this._firstUseExperienced = true;
|
||||
|
||||
@ -104,7 +104,7 @@ let TabView = {
|
||||
observe: function TabView_observe(subject, topic, data) {
|
||||
if (topic == "nsPref:changed") {
|
||||
Services.prefs.removeObserver(
|
||||
"browser.panorama.experienced_first_use", this);
|
||||
"browser.panorama.experienced_first_run", this);
|
||||
this._firstUseExperienced = true;
|
||||
this._addToolbarButton();
|
||||
}
|
||||
@ -115,7 +115,7 @@ let TabView = {
|
||||
uninit: function TabView_uninit() {
|
||||
if (!this._firstUseExperienced) {
|
||||
Services.prefs.removeObserver(
|
||||
"browser.panorama.experienced_first_use", this);
|
||||
"browser.panorama.experienced_first_run", this);
|
||||
}
|
||||
if (this._tabShowEventListener) {
|
||||
gBrowser.tabContainer.removeEventListener(
|
||||
|
@ -472,7 +472,13 @@ statuspanel:-moz-locale-dir(rtl):not([mirror]) {
|
||||
}
|
||||
|
||||
statuspanel[type=status] {
|
||||
min-width: 25%;
|
||||
min-width: 23em;
|
||||
}
|
||||
|
||||
@media all and (max-width: 800px) {
|
||||
statuspanel[type=status] {
|
||||
min-width: 33%;
|
||||
}
|
||||
}
|
||||
|
||||
statuspanel[type=overLink] {
|
||||
|
@ -8399,13 +8399,13 @@ var LightWeightThemeWebInstaller = {
|
||||
* @param aURI
|
||||
* URI to search for
|
||||
* @param aOpenNew
|
||||
* True to open a new tab and switch to it, if no existing tab is found
|
||||
* True to open a new tab and switch to it, if no existing tab is found.
|
||||
* If no suitable window is found, a new one will be opened.
|
||||
* @return True if an existing tab was found, false otherwise
|
||||
*/
|
||||
function switchToTabHavingURI(aURI, aOpenNew) {
|
||||
// This will switch to the tab in aWindow having aURI, if present.
|
||||
function switchIfURIInWindow(aWindow) {
|
||||
if (!("gBrowser" in aWindow))
|
||||
return false;
|
||||
let browsers = aWindow.gBrowser.browsers;
|
||||
for (let i = 0; i < browsers.length; i++) {
|
||||
let browser = browsers[i];
|
||||
@ -8421,10 +8421,12 @@ function switchToTabHavingURI(aURI, aOpenNew) {
|
||||
|
||||
// This can be passed either nsIURI or a string.
|
||||
if (!(aURI instanceof Ci.nsIURI))
|
||||
aURI = makeURI(aURI);
|
||||
aURI = Services.io.newURI(aURI, null, null);
|
||||
|
||||
let isBrowserWindow = !!window.gBrowser;
|
||||
|
||||
// Prioritise this window.
|
||||
if (switchIfURIInWindow(window))
|
||||
if (isBrowserWindow && switchIfURIInWindow(window))
|
||||
return true;
|
||||
|
||||
let winEnum = Services.wm.getEnumerator("navigator:browser");
|
||||
@ -8440,7 +8442,7 @@ function switchToTabHavingURI(aURI, aOpenNew) {
|
||||
|
||||
// No opened tab has that url.
|
||||
if (aOpenNew) {
|
||||
if (isTabEmpty(gBrowser.selectedTab))
|
||||
if (isBrowserWindow && isTabEmpty(gBrowser.selectedTab))
|
||||
gBrowser.selectedBrowser.loadURI(aURI.spec);
|
||||
else
|
||||
openUILinkIn(aURI.spec, "tab");
|
||||
|
@ -3086,7 +3086,16 @@
|
||||
]]></handler>
|
||||
|
||||
<handler event="dblclick"><![CDATA[
|
||||
// See hack note in the tabbrowser-close-button binding
|
||||
#ifdef MOZ_WIDGET_GTK2
|
||||
// Disable this on GTK2 when the menubar is draggable, since (a)
|
||||
// the menubar and tabbbar have unified appearance and should
|
||||
// thus not have different behavior (though this condition alone
|
||||
// applies to more cases) and (b) it interacts badly with the
|
||||
// drag handling that we use for dragging either one.
|
||||
if (this.parentNode._dragBindingAlive)
|
||||
return;
|
||||
#endif
|
||||
// See hack note in the tabbrowser-close-tab-button binding
|
||||
if (!this._blockDblClick && event.button == 0 &&
|
||||
event.originalTarget.localName == "box")
|
||||
BrowserOpenTab();
|
||||
|
@ -742,6 +742,10 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
this.$undoContainer = null;
|
||||
this.droppable(true);
|
||||
|
||||
GroupItems.setActiveGroupItem(this);
|
||||
if (this._activeTab)
|
||||
UI.setActiveTab(this._activeTab);
|
||||
|
||||
iQ(this.container).show().animate({
|
||||
"-moz-transform": "scale(1)",
|
||||
"opacity": 1
|
||||
@ -806,7 +810,7 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
toClose.forEach(function(child) {
|
||||
child.removeSubscriber(self, "close");
|
||||
|
||||
let removed = child.close();
|
||||
let removed = child.close(true);
|
||||
if (removed) {
|
||||
shouldRemoveTabItems.push(child);
|
||||
} else {
|
||||
@ -1094,7 +1098,7 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
let closed = options.dontClose ? false : this.closeIfEmpty();
|
||||
if (closed)
|
||||
this._makeClosestTabActive();
|
||||
else if (!options.dontArrage)
|
||||
else if (!options.dontArrange)
|
||||
this.arrange({animate: !options.immediately});
|
||||
|
||||
this._sendToSubscribers("childRemoved",{ groupItemId: this.id, item: item });
|
||||
@ -1126,7 +1130,6 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
let $icon = iQ(icon);
|
||||
if ($icon.data("xulTab") == event.target) {
|
||||
$icon.attr("src", Utils.defaultFaviconURL);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
@ -541,8 +541,24 @@ TabItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
// Function: close
|
||||
// Closes this item (actually closes the tab associated with it, which automatically
|
||||
// closes the item.
|
||||
// Parameters:
|
||||
// groupClose - true if this method is called by group close action.
|
||||
// Returns true if this tab is removed.
|
||||
close: function TabItem_close() {
|
||||
close: function TabItem_close(groupClose) {
|
||||
// When the last tab is closed, put a new tab into closing tab's group. If
|
||||
// closing tab doesn't belong to a group and no empty group, create a new
|
||||
// one for the new tab.
|
||||
if (!groupClose && gBrowser.tabs.length == 1) {
|
||||
if (this.tab._tabViewTabItem.parent) {
|
||||
group = this.tab._tabViewTabItem.parent;
|
||||
} else {
|
||||
let emptyGroups = GroupItems.groupItems.filter(function (groupItem) {
|
||||
return (!groupItem.getChildren().length);
|
||||
});
|
||||
group = (emptyGroups.length ? emptyGroups[0] : GroupItems.newGroup());
|
||||
}
|
||||
group.newTab();
|
||||
}
|
||||
// when "TabClose" event is fired, the browser tab is about to close and our
|
||||
// item "close" is fired before the browser tab actually get closed.
|
||||
// Therefore, we need "tabRemoved" event below.
|
||||
@ -628,8 +644,7 @@ TabItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
GroupItems.setActiveOrphanTab(this);
|
||||
}
|
||||
|
||||
this.shouldHideCachedData = true;
|
||||
TabItems._update(this.tab);
|
||||
TabItems._update(this.tab, {force: true});
|
||||
|
||||
// Zoom in!
|
||||
let tab = this.tab;
|
||||
@ -697,11 +712,15 @@ TabItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
complete();
|
||||
};
|
||||
|
||||
this.shouldHideCachedData = true;
|
||||
TabItems._update(this.tab);
|
||||
TabItems._update(this.tab, {force: true});
|
||||
|
||||
$tab.addClass("front");
|
||||
|
||||
// If we're in a stacked group, make sure we become the
|
||||
// topChild now so that we show the zoom animation correctly.
|
||||
if (this.parent && this.parent.isStacked())
|
||||
this.parent.setTopChild(this);
|
||||
|
||||
let animateZoom = gPrefBranch.getBoolPref("animate_zoom");
|
||||
if (animateZoom) {
|
||||
// The scaleCheat of 2 here is a clever way to speed up the zoom-out
|
||||
@ -938,7 +957,14 @@ let TabItems = {
|
||||
// ----------
|
||||
// Function: _update
|
||||
// Takes in a xul:tab.
|
||||
_update: function TabItems__update(tab) {
|
||||
//
|
||||
// Parameters:
|
||||
// tab - a xul tab to update
|
||||
// options - an object with additional parameters, see below
|
||||
//
|
||||
// Possible options:
|
||||
// force - true to always update the tab item even if it's incomplete
|
||||
_update: function TabItems__update(tab, options) {
|
||||
try {
|
||||
if (this._pauseUpdateForTest)
|
||||
return;
|
||||
@ -986,7 +1012,7 @@ let TabItems = {
|
||||
}
|
||||
|
||||
// ___ Make sure the tab is complete and ready for updating.
|
||||
if (!this.isComplete(tab)) {
|
||||
if (!this.isComplete(tab) && (!options || !options.force)) {
|
||||
// If it's incomplete, stick it on the end of the queue
|
||||
this._tabsWaitingForUpdate.push(tab);
|
||||
return;
|
||||
|
@ -258,6 +258,7 @@ _BROWSER_FILES += \
|
||||
$(NULL)
|
||||
else
|
||||
_BROWSER_FILES += \
|
||||
browser_bug565667.js \
|
||||
browser_customize.js \
|
||||
$(NULL)
|
||||
|
||||
|
92
browser/base/content/test/browser_bug565667.js
Normal file
92
browser/base/content/test/browser_bug565667.js
Normal file
@ -0,0 +1,92 @@
|
||||
/* ***** 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 bug 565667 test.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Paul O’Shannessy <paul@oshannessy.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
let fm = Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager);
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
// Open the javascript console. It has the mac menu overlay, so browser.js is
|
||||
// loaded in it.
|
||||
let consoleWin = window.open("chrome://global/content/console.xul", "_blank",
|
||||
"chrome,extrachrome,menubar,resizable,scrollbars,status,toolbar");
|
||||
testWithOpenWindow(consoleWin);
|
||||
}
|
||||
|
||||
function testWithOpenWindow(consoleWin) {
|
||||
// Add a tab so we don't open the url into the current tab
|
||||
let newTab = gBrowser.addTab("http://example.com");
|
||||
gBrowser.selectedTab = newTab;
|
||||
|
||||
let numTabs = gBrowser.tabs.length;
|
||||
|
||||
waitForFocus(function() {
|
||||
// Sanity check
|
||||
is(fm.activeWindow, consoleWin,
|
||||
"the console window is focused");
|
||||
|
||||
gBrowser.tabContainer.addEventListener("TabOpen", function(aEvent) {
|
||||
gBrowser.tabContainer.removeEventListener("TabOpen", arguments.callee, true);
|
||||
let browser = aEvent.originalTarget.linkedBrowser;
|
||||
browser.addEventListener("pageshow", function(event) {
|
||||
if (event.target.location.href != "about:addons")
|
||||
return;
|
||||
browser.removeEventListener("pageshow", arguments.callee, true);
|
||||
|
||||
is(fm.activeWindow, window,
|
||||
"the browser window was focused");
|
||||
is(browser.currentURI.spec, "about:addons",
|
||||
"about:addons was loaded in the window");
|
||||
is(gBrowser.tabs.length, numTabs + 1,
|
||||
"a new tab was added");
|
||||
|
||||
// Cleanup.
|
||||
executeSoon(function() {
|
||||
consoleWin.close();
|
||||
gBrowser.removeTab(gBrowser.selectedTab);
|
||||
gBrowser.removeTab(newTab);
|
||||
finish();
|
||||
});
|
||||
}, true);
|
||||
}, true);
|
||||
|
||||
// Open the addons manager, uses switchToTabHavingURI.
|
||||
consoleWin.BrowserOpenAddonsMgr();
|
||||
}, consoleWin);
|
||||
}
|
||||
|
||||
// Ideally we'd also check that the case for no open windows works, but we can't
|
||||
// due to limitations with the testing framework.
|
@ -44,16 +44,25 @@ function load_page(aURL, aCanHide, aCallback) {
|
||||
is_chrome_visible();
|
||||
|
||||
if (aURL == "about:addons") {
|
||||
gNewBrowser.contentDocument.addEventListener("Initialized", function() {
|
||||
gNewBrowser.contentDocument.removeEventListener("Initialized", arguments.callee, false);
|
||||
|
||||
function check_after_init() {
|
||||
if (aCanHide)
|
||||
is_chrome_hidden();
|
||||
else
|
||||
is_chrome_visible();
|
||||
|
||||
aCallback();
|
||||
}, false);
|
||||
}
|
||||
|
||||
if (gNewBrowser.contentWindow.gIsInitializing) {
|
||||
gNewBrowser.contentDocument.addEventListener("Initialized", function() {
|
||||
gNewBrowser.contentDocument.removeEventListener("Initialized", arguments.callee, false);
|
||||
|
||||
check_after_init();
|
||||
}, false);
|
||||
}
|
||||
else {
|
||||
check_after_init();
|
||||
}
|
||||
}
|
||||
else {
|
||||
executeSoon(aCallback);
|
||||
|
@ -114,9 +114,11 @@ _BROWSER_FILES = \
|
||||
browser_tabview_bug630102.js \
|
||||
browser_tabview_bug630157.js \
|
||||
browser_tabview_bug631662.js \
|
||||
browser_tabview_bug633788.js \
|
||||
browser_tabview_bug634077.js \
|
||||
browser_tabview_bug634085.js \
|
||||
browser_tabview_bug634158.js \
|
||||
browser_tabview_bug635696.js \
|
||||
browser_tabview_dragdrop.js \
|
||||
browser_tabview_exit_button.js \
|
||||
browser_tabview_expander.js \
|
||||
|
@ -1,61 +1,21 @@
|
||||
/* ***** 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 a test for bug 616729.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Tim Taubert <tim.taubert@gmx.de>
|
||||
*
|
||||
* 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 ***** */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function test() {
|
||||
let cw;
|
||||
|
||||
let createGroupItem = function () {
|
||||
let bounds = new cw.Rect(20, 20, 400, 200);
|
||||
let groupItem = new cw.GroupItem([], {bounds: bounds, immediately: true});
|
||||
cw.GroupItems.setActiveGroupItem(groupItem);
|
||||
|
||||
for (let i=0; i<5; i++)
|
||||
gBrowser.loadOneTab('about:blank', {inBackground: true});
|
||||
|
||||
return groupItem;
|
||||
return createGroupItemWithBlankTabs(window, 400, 200, 0, 5);
|
||||
}
|
||||
|
||||
let assertCorrectItemOrder = function (items) {
|
||||
for (let i=1; i<items.length; i++) {
|
||||
if (items[i-1].tab._tPos > items[i].tab._tPos) {
|
||||
ok(false, 'tabs were correctly reordered');
|
||||
break;
|
||||
return;
|
||||
}
|
||||
}
|
||||
ok(true, 'tabs were correctly reordered');
|
||||
}
|
||||
|
||||
let testVariousTabOrders = function () {
|
||||
@ -132,19 +92,11 @@ function test() {
|
||||
assertCorrectItemOrder(groupItem2.getChildren());
|
||||
|
||||
// cleanup
|
||||
groupItem.addSubscriber(groupItem, 'groupHidden', function () {
|
||||
groupItem.removeSubscriber(groupItem, 'groupHidden');
|
||||
groupItem.closeHidden();
|
||||
groupItem2.closeAll();
|
||||
closeGroupItem(groupItem, function () {
|
||||
closeGroupItem(groupItem2, function () {
|
||||
hideTabView(finish);
|
||||
});
|
||||
});
|
||||
|
||||
groupItem2.addSubscriber(groupItem, 'groupHidden', function () {
|
||||
groupItem2.removeSubscriber(groupItem, 'groupHidden');
|
||||
groupItem2.closeHidden();
|
||||
hideTabView(finish);
|
||||
});
|
||||
|
||||
groupItem.closeAll();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@ function test() {
|
||||
|
||||
// disable the first run pref
|
||||
prefsBranch = Services.prefs.getBranch("browser.panorama.");
|
||||
prefsBranch.setBoolPref("experienced_first_use", false);
|
||||
prefsBranch.setBoolPref("experienced_first_run", false);
|
||||
|
||||
let win =
|
||||
window.openDialog(getBrowserURL(), "_blank", "all,dialog=no", "about:blank");
|
||||
@ -67,7 +67,7 @@ function test2(win) {
|
||||
// move a tab to another group including iframe initialization. Then,
|
||||
// use the key combination to change to the next group.
|
||||
function test3(win) {
|
||||
prefsBranch.setBoolPref("experienced_first_use", true);
|
||||
prefsBranch.setBoolPref("experienced_first_run", true);
|
||||
|
||||
let newTab = win.gBrowser.addTab("about:blank");
|
||||
|
||||
|
@ -0,0 +1,31 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
showTabView(function () {
|
||||
is(gBrowser.tabs.length, 1, "There is only one tab");
|
||||
|
||||
let tab = gBrowser.tabs[0];
|
||||
let tabItem = tab._tabViewTabItem;
|
||||
ok(tabItem.parent, "The tab item belongs to a group");
|
||||
let groupId = tabItem.parent.id;
|
||||
|
||||
tab._tabViewTabItem.close();
|
||||
|
||||
whenTabViewIsHidden(function() {
|
||||
// a new tab with group should be opened
|
||||
is(gBrowser.tabs.length, 1, "There is still one tab");
|
||||
isnot(gBrowser.selectedTab, tab, "The tab is different");
|
||||
|
||||
tab = gBrowser.tabs[0];
|
||||
tabItem = tab._tabViewTabItem;
|
||||
ok(tabItem.parent, "This new tab item belongs to a group");
|
||||
|
||||
is(tabItem.parent.id, groupId, "The group is different");
|
||||
|
||||
finish();
|
||||
});
|
||||
});
|
||||
}
|
106
browser/base/content/test/tabview/browser_tabview_bug635696.js
Normal file
106
browser/base/content/test/tabview/browser_tabview_bug635696.js
Normal file
@ -0,0 +1,106 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function test() {
|
||||
let cw;
|
||||
|
||||
let createGroupItem = function () {
|
||||
let groupItem = createGroupItemWithBlankTabs(window, 200, 200, 10, 1);
|
||||
|
||||
let groupItemId = groupItem.id;
|
||||
registerCleanupFunction(function() {
|
||||
let groupItem = cw.GroupItems.groupItem(groupItemId);
|
||||
if (groupItem)
|
||||
groupItem.close();
|
||||
});
|
||||
|
||||
return groupItem;
|
||||
}
|
||||
|
||||
let createOrphan = function () {
|
||||
let tab = gBrowser.loadOneTab('about:blank', {inBackground: true});
|
||||
registerCleanupFunction(function () {
|
||||
if (gBrowser.tabs.length > 1)
|
||||
gBrowser.removeTab(gBrowser.tabs[1])
|
||||
});
|
||||
|
||||
let tabItem = tab._tabViewTabItem;
|
||||
tabItem.parent.remove(tabItem);
|
||||
|
||||
return tabItem;
|
||||
}
|
||||
|
||||
let testSingleGroupItem = function () {
|
||||
let groupItem = cw.GroupItems.groupItems[0];
|
||||
is(cw.GroupItems.getActiveGroupItem(), groupItem, "groupItem is active");
|
||||
|
||||
let tabItem = groupItem.getChild(0);
|
||||
is(cw.UI.getActiveTab(), tabItem, "tabItem is active");
|
||||
|
||||
hideGroupItem(groupItem, function () {
|
||||
is(cw.GroupItems.getActiveGroupItem(), null, "groupItem is not active");
|
||||
unhideGroupItem(groupItem, function () {
|
||||
is(cw.GroupItems.getActiveGroupItem(), groupItem, "groupItem is active again");
|
||||
is(cw.UI.getActiveTab(), tabItem, "tabItem is still active");
|
||||
next();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
let testTwoGroupItems = function () {
|
||||
let groupItem = cw.GroupItems.groupItems[0];
|
||||
let tabItem = groupItem.getChild(0);
|
||||
|
||||
let groupItem2 = createGroupItem();
|
||||
let tabItem2 = groupItem2.getChild(0);
|
||||
|
||||
hideGroupItem(groupItem, function () {
|
||||
is(cw.UI.getActiveTab(), tabItem2, "tabItem2 is active");
|
||||
unhideGroupItem(groupItem, function () {
|
||||
cw.UI.setActiveTab(tabItem);
|
||||
closeGroupItem(groupItem2, next);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
let testOrphanTab = function () {
|
||||
let groupItem = cw.GroupItems.groupItems[0];
|
||||
let tabItem = groupItem.getChild(0);
|
||||
let tabItem2 = createOrphan();
|
||||
|
||||
hideGroupItem(groupItem, function () {
|
||||
is(cw.UI.getActiveTab(), tabItem2, "tabItem2 is active");
|
||||
unhideGroupItem(groupItem, function () {
|
||||
cw.UI.setActiveTab(tabItem);
|
||||
tabItem2.close();
|
||||
next();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
let tests = [testSingleGroupItem, testTwoGroupItems, testOrphanTab];
|
||||
|
||||
let next = function () {
|
||||
let test = tests.shift();
|
||||
if (test)
|
||||
test();
|
||||
else
|
||||
hideTabView(finishTest);
|
||||
}
|
||||
|
||||
let finishTest = function () {
|
||||
is(cw.GroupItems.groupItems.length, 1, "there is one groupItem");
|
||||
is(gBrowser.tabs.length, 1, "there is one tab");
|
||||
ok(!TabView.isVisible(), "tabview is hidden");
|
||||
|
||||
finish();
|
||||
}
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
showTabView(function () {
|
||||
registerCleanupFunction(function () TabView.hide());
|
||||
cw = TabView.getContentWindow();
|
||||
next();
|
||||
});
|
||||
}
|
@ -201,3 +201,31 @@ function whenTabViewIsShown(callback, win) {
|
||||
callback();
|
||||
}, false);
|
||||
}
|
||||
|
||||
// ----------
|
||||
function hideGroupItem(groupItem, callback) {
|
||||
if (groupItem.hidden) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
|
||||
groupItem.addSubscriber(groupItem, "groupHidden", function () {
|
||||
groupItem.removeSubscriber(groupItem, "groupHidden");
|
||||
callback();
|
||||
});
|
||||
groupItem.closeAll();
|
||||
}
|
||||
|
||||
// ----------
|
||||
function unhideGroupItem(groupItem, callback) {
|
||||
if (!groupItem.hidden) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
|
||||
groupItem.addSubscriber(groupItem, "groupShown", function () {
|
||||
groupItem.removeSubscriber(groupItem, "groupShown");
|
||||
callback();
|
||||
});
|
||||
groupItem._unhide();
|
||||
}
|
||||
|
@ -206,7 +206,7 @@ function openLinkIn(url, where, params) {
|
||||
|
||||
var w = getTopWin();
|
||||
if ((where == "tab" || where == "tabshifted") &&
|
||||
w.document.documentElement.getAttribute("chromehidden")) {
|
||||
w && w.document.documentElement.getAttribute("chromehidden")) {
|
||||
w = getTopWin(true);
|
||||
aRelatedToCurrent = false;
|
||||
}
|
||||
|
@ -39,9 +39,6 @@
|
||||
* Tests the bookmarks Properties dialog.
|
||||
*/
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
// DOM ids of Places sidebar trees.
|
||||
const SIDEBAR_HISTORY_TREE_ID = "historyTree";
|
||||
const SIDEBAR_BOOKMARKS_TREE_ID = "bookmarks-view";
|
||||
|
@ -39,10 +39,6 @@
|
||||
* Bug 392497 - search in history sidebar loses sort
|
||||
*/
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cr = Components.results;
|
||||
|
||||
var hs = Cc["@mozilla.org/browser/nav-history-service;1"].
|
||||
getService(Ci.nsINavHistoryService);
|
||||
var bh = hs.QueryInterface(Ci.nsIBrowserHistory);
|
||||
|
@ -39,9 +39,6 @@
|
||||
* Tests middle-clicking items in the Library.
|
||||
*/
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
const ENABLE_HISTORY_PREF = "places.history.enabled";
|
||||
|
||||
var gLibrary = null;
|
||||
|
@ -39,9 +39,6 @@
|
||||
* Tests Library Left pane view for liveupdate.
|
||||
*/
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
var gLibrary = null;
|
||||
|
||||
function test() {
|
||||
|
@ -6,9 +6,6 @@
|
||||
* Tests that visits across frames are correctly represented in the database.
|
||||
*/
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
const BASE_URL = "http://mochi.test:8888/browser/browser/components/places/tests/browser";
|
||||
const PAGE_URL = BASE_URL + "/framedPage.html";
|
||||
const LEFT_URL = BASE_URL + "/frameLeft.html";
|
||||
|
@ -39,9 +39,6 @@
|
||||
* Tests Places views (menu, toolbar, tree) for liveupdate.
|
||||
*/
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
let toolbar = document.getElementById("PersonalToolbar");
|
||||
let wasCollapsed = toolbar.collapsed;
|
||||
|
||||
|
@ -50,10 +50,9 @@ _CHROME_FILES = \
|
||||
|
||||
# Disabled due to bad interactions with next tests.
|
||||
# browser_ui_locationbar.js
|
||||
# Disabled due to random failures.
|
||||
# browser_ui_bookmarks_sidebar.js
|
||||
_BROWSER_TEST_FILES = \
|
||||
browser_ui_000_data.js \
|
||||
browser_ui_bookmarks_sidebar.js \
|
||||
browser_ui_history_menu.js \
|
||||
browser_ui_history_sidebar.js \
|
||||
browser_ui_history_sidebar_2.js \
|
||||
|
@ -98,14 +98,16 @@ ptests.push({
|
||||
var start = Date.now();
|
||||
var sb = document.getElementById("sidebar");
|
||||
sb.addEventListener("load", function() {
|
||||
var duration = Date.now() - start;
|
||||
sb.removeEventListener("load", arguments.callee, true);
|
||||
toggleSidebar("viewBookmarksSidebar", false);
|
||||
self.times.push(duration);
|
||||
if (self.times.length == TEST_REPEAT_COUNT)
|
||||
self.finish();
|
||||
else
|
||||
self.run();
|
||||
executeSoon(function() {
|
||||
var duration = Date.now() - start;
|
||||
toggleSidebar("viewBookmarksSidebar", false);
|
||||
self.times.push(duration);
|
||||
if (self.times.length == TEST_REPEAT_COUNT)
|
||||
self.finish();
|
||||
else
|
||||
self.run();
|
||||
});
|
||||
}, true);
|
||||
toggleSidebar("viewBookmarksSidebar", true);
|
||||
},
|
||||
@ -122,6 +124,7 @@ ptests.push({
|
||||
});
|
||||
|
||||
function test() {
|
||||
requestLongerTimeout(2);
|
||||
// kick off tests
|
||||
setTimeout(runNextTest, 0);
|
||||
}
|
||||
|
@ -185,6 +185,7 @@ function processTestResult(aTest) {
|
||||
}
|
||||
|
||||
function test() {
|
||||
requestLongerTimeout(2);
|
||||
// kick off tests
|
||||
setTimeout(runNextTest, 0);
|
||||
}
|
||||
|
@ -130,6 +130,7 @@ function processTestResult(aTest) {
|
||||
}
|
||||
|
||||
function test() {
|
||||
requestLongerTimeout(2);
|
||||
// kick off tests
|
||||
setTimeout(runNextTest, 0);
|
||||
}
|
||||
|
@ -130,6 +130,7 @@ function processTestResult(aTest) {
|
||||
}
|
||||
|
||||
function test() {
|
||||
requestLongerTimeout(2);
|
||||
// kick off tests
|
||||
setTimeout(runNextTest, 0);
|
||||
}
|
||||
|
@ -92,13 +92,13 @@ function test() {
|
||||
expiry: time,
|
||||
isHttpOnly: true,
|
||||
QueryInterface: function(iid) {
|
||||
const validIIDs = [Components.interfaces.nsISupports,
|
||||
Components.interfaces.nsICookie,
|
||||
Components.interfaces.nsICookie2];
|
||||
const validIIDs = [Ci.nsISupports,
|
||||
Ci.nsICookie,
|
||||
Ci.nsICookie2];
|
||||
for (var i = 0; i < validIIDs.length; ++i)
|
||||
if (iid == validIIDs[i])
|
||||
return this;
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
throw Cr.NS_ERROR_NO_INTERFACE;
|
||||
}
|
||||
};
|
||||
cp.cookieDialog(window, cookie, "mozilla.org", 10, false, remember);
|
||||
|
@ -37,8 +37,8 @@
|
||||
// Test to make sure that the visited page titles do not get updated inside the
|
||||
// private browsing mode.
|
||||
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
Components.utils.import("resource://gre/modules/PlacesUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/PlacesUtils.jsm");
|
||||
|
||||
function do_test()
|
||||
{
|
||||
|
@ -576,11 +576,11 @@ function test_storage_cleared()
|
||||
{
|
||||
function getStorageForURI(aURI)
|
||||
{
|
||||
let principal = Components.classes["@mozilla.org/scriptsecuritymanager;1"].
|
||||
getService(Components.interfaces.nsIScriptSecurityManager).
|
||||
let principal = Cc["@mozilla.org/scriptsecuritymanager;1"].
|
||||
getService(Ci.nsIScriptSecurityManager).
|
||||
getCodebasePrincipal(aURI);
|
||||
let dsm = Components.classes["@mozilla.org/dom/storagemanager;1"].
|
||||
getService(Components.interfaces.nsIDOMStorageManager);
|
||||
let dsm = Cc["@mozilla.org/dom/storagemanager;1"].
|
||||
getService(Ci.nsIDOMStorageManager);
|
||||
return dsm.getLocalStorageForPrincipal(principal, "");
|
||||
}
|
||||
|
||||
|
@ -38,9 +38,6 @@
|
||||
|
||||
function run_test_on_service()
|
||||
{
|
||||
let Cc = Components.classes;
|
||||
let Ci = Components.interfaces;
|
||||
let Cu = Components.utils;
|
||||
Cu.import("resource:///modules/openLocationLastURL.jsm");
|
||||
|
||||
function clearHistory() {
|
||||
|
@ -679,10 +679,10 @@ SessionStoreService.prototype = {
|
||||
this.onTabSelect(win);
|
||||
break;
|
||||
case "TabShow":
|
||||
this.onTabShow(aEvent.originalTarget);
|
||||
this.onTabShow(win, aEvent.originalTarget);
|
||||
break;
|
||||
case "TabHide":
|
||||
this.onTabHide(aEvent.originalTarget);
|
||||
this.onTabHide(win, aEvent.originalTarget);
|
||||
break;
|
||||
case "TabPinned":
|
||||
case "TabUnpinned":
|
||||
@ -1064,7 +1064,7 @@ SessionStoreService.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
onTabShow: function sss_onTabShow(aTab) {
|
||||
onTabShow: function sss_onTabShow(aWindow, aTab) {
|
||||
// If the tab hasn't been restored yet, move it into the right _tabsToRestore bucket
|
||||
if (aTab.linkedBrowser.__SS_restoreState &&
|
||||
aTab.linkedBrowser.__SS_restoreState == TAB_STATE_NEEDS_RESTORE) {
|
||||
@ -1072,9 +1072,13 @@ SessionStoreService.prototype = {
|
||||
// Just put it at the end of the list of visible tabs;
|
||||
this._tabsToRestore.visible.push(aTab);
|
||||
}
|
||||
|
||||
// Default delay of 2 seconds gives enough time to catch multiple TabShow
|
||||
// events due to changing groups in Panorama.
|
||||
this.saveStateDelayed(aWindow);
|
||||
},
|
||||
|
||||
onTabHide: function sss_onTabHide(aTab) {
|
||||
onTabHide: function sss_onTabHide(aWindow, aTab) {
|
||||
// If the tab hasn't been restored yet, move it into the right _tabsToRestore bucket
|
||||
if (aTab.linkedBrowser.__SS_restoreState &&
|
||||
aTab.linkedBrowser.__SS_restoreState == TAB_STATE_NEEDS_RESTORE) {
|
||||
@ -1082,6 +1086,10 @@ SessionStoreService.prototype = {
|
||||
// Just put it at the end of the list of hidden tabs;
|
||||
this._tabsToRestore.hidden.push(aTab);
|
||||
}
|
||||
|
||||
// Default delay of 2 seconds gives enough time to catch multiple TabHide
|
||||
// events due to changing groups in Panorama.
|
||||
this.saveStateDelayed(aWindow);
|
||||
},
|
||||
|
||||
/* ........ nsISessionStore API .............. */
|
||||
|
@ -144,6 +144,7 @@ _BROWSER_TEST_FILES = \
|
||||
browser_624727.js \
|
||||
browser_625257.js \
|
||||
browser_628270.js \
|
||||
browser_635418.js \
|
||||
$(NULL)
|
||||
|
||||
ifneq ($(OS_ARCH),Darwin)
|
||||
|
@ -0,0 +1,88 @@
|
||||
/* ***** 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 sessionstore test code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Mehdi Mulani <mmmulani@uwaterloo.ca>
|
||||
* Paul O’Shannessy <paul@oshannessy.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK *****/
|
||||
|
||||
// This tests that hiding/showing a tab, on its own, eventually triggers a
|
||||
// session store.
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
// We speed up the interval between session saves to ensure that the test
|
||||
// runs quickly.
|
||||
Services.prefs.setIntPref("browser.sessionstore.interval", 2000);
|
||||
|
||||
// Loading a tab causes a save state and this is meant to catch that event.
|
||||
waitForSaveState(testBug635418_1);
|
||||
|
||||
// Assumption: Only one window is open and it has one tab open.
|
||||
gBrowser.addTab("about:mozilla");
|
||||
}
|
||||
|
||||
function testBug635418_1() {
|
||||
ok(!gBrowser.tabs[0].hidden, "first tab should not be hidden");
|
||||
ok(!gBrowser.tabs[1].hidden, "second tab should not be hidden");
|
||||
|
||||
waitForSaveState(testBug635418_2);
|
||||
|
||||
// We can't hide the selected tab, so hide the new one
|
||||
gBrowser.hideTab(gBrowser.tabs[1]);
|
||||
}
|
||||
|
||||
function testBug635418_2() {
|
||||
let state = JSON.parse(SS_SVC.getBrowserState());
|
||||
ok(!state.windows[0].tabs[0].hidden, "first tab should still not be hidden");
|
||||
ok(state.windows[0].tabs[1].hidden, "second tab should be hidden by now");
|
||||
|
||||
waitForSaveState(testBug635418_3);
|
||||
gBrowser.showTab(gBrowser.tabs[1]);
|
||||
}
|
||||
|
||||
function testBug635418_3() {
|
||||
let state = JSON.parse(SS_SVC.getBrowserState());
|
||||
ok(!state.windows[0].tabs[0].hidden, "first tab should still still not be hidden");
|
||||
ok(!state.windows[0].tabs[1].hidden, "second tab should not be hidden again");
|
||||
|
||||
done();
|
||||
}
|
||||
|
||||
function done() {
|
||||
gBrowser.removeTab(window.gBrowser.tabs[1]);
|
||||
|
||||
Services.prefs.clearUserPref("browser.sessionstore.interval");
|
||||
|
||||
executeSoon(finish);
|
||||
}
|
@ -1 +1 @@
|
||||
4.0b12pre
|
||||
4.0b13pre
|
||||
|
@ -79,3 +79,4 @@ tr
|
||||
uk
|
||||
zh-CN
|
||||
zh-TW
|
||||
zu
|
||||
|
@ -1391,6 +1391,10 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
|
||||
color: -moz-menubartext;
|
||||
}
|
||||
|
||||
#TabsToolbar[tabsontop=true]:not(:-moz-lwtheme):-moz-system-metric(menubar-drag) {
|
||||
-moz-binding: url("chrome://global/content/bindings/toolbar.xml#toolbar-drag");
|
||||
}
|
||||
|
||||
#TabsToolbar[tabsontop=false] {
|
||||
background-image:
|
||||
-moz-linear-gradient(bottom, rgba(0,0,0,.3) 1px, rgba(0,0,0,.05) 1px, transparent 50%);
|
||||
|
@ -196,12 +196,12 @@ html[dir=rtl] .stack-trayed .tab-title {
|
||||
.tabInGroupItem {
|
||||
box-shadow: none;
|
||||
border-color: transparent;
|
||||
background-color: transparent;
|
||||
background-color: rgb(240,240,240);
|
||||
margin: 8px;
|
||||
}
|
||||
|
||||
.tabInGroupItem .favicon {
|
||||
background-color: #EBEBEB;
|
||||
background-color: rgb(240,240,240);
|
||||
}
|
||||
|
||||
.groupItem {
|
||||
|
@ -170,17 +170,11 @@
|
||||
border-top-right-radius: 3.5px;
|
||||
background-clip: padding-box;
|
||||
}
|
||||
#main-window[sizemode=normal]:not([inFullscreen=true])[disablechrome] #navigator-toolbox::after {
|
||||
visibility: visible;
|
||||
background-color: @toolbarShadowColor@;
|
||||
}
|
||||
#main-window[sizemode=normal]:not([inFullscreen=true]) #TabsToolbar[tabsontop=true]:not(:-moz-lwtheme),
|
||||
#main-window[sizemode=normal]:not([inFullscreen=true])[disablechrome] #TabsToolbar {
|
||||
#main-window[sizemode=normal]:not([inFullscreen]):not([disablechrome]) #TabsToolbar[tabsontop=true]:not(:-moz-lwtheme) {
|
||||
margin-bottom: -1px;
|
||||
background-image: none !important;
|
||||
}
|
||||
#main-window[sizemode=normal]:not([inFullscreen=true]) #tabbrowser-tabs[tabsontop=true] > .tabbrowser-arrowscrollbox > .arrowscrollbox-scrollbox > .scrollbox-innerbox:not(:-moz-lwtheme),
|
||||
#main-window[sizemode=normal]:not([inFullscreen=true])[disablechrome] .tabbrowser-arrowscrollbox > .arrowscrollbox-scrollbox > .scrollbox-innerbox {
|
||||
#main-window[sizemode=normal]:not([inFullscreen]):not([disablechrome]) #tabbrowser-tabs[tabsontop=true] > .tabbrowser-arrowscrollbox > .arrowscrollbox-scrollbox > .scrollbox-innerbox:not(:-moz-lwtheme) {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
|
@ -280,6 +280,9 @@ class DeviceManager:
|
||||
# success: True
|
||||
# failure: False
|
||||
def pushFile(self, localname, destname):
|
||||
if (os.name == "nt"):
|
||||
destname = destname.replace('\\', '/')
|
||||
|
||||
if (self.debug >= 3): print "in push file with: " + localname + ", and: " + destname
|
||||
if (self.validateFile(destname, localname) == True):
|
||||
if (self.debug >= 3): print "files are validated"
|
||||
@ -486,11 +489,17 @@ class DeviceManager:
|
||||
# returns:
|
||||
# success: pid
|
||||
# failure: None
|
||||
def fireProcess(self, appname):
|
||||
def fireProcess(self, appname, failIfRunning=False):
|
||||
if (not appname):
|
||||
if (self.debug >= 1): print "WARNING: fireProcess called with no command to run"
|
||||
return None
|
||||
|
||||
if (self.debug >= 2): print "FIRE PROC: '" + appname + "'"
|
||||
|
||||
|
||||
if (self.processExist(appname) != None):
|
||||
print "WARNING: process %s appears to be running already\n" % appname
|
||||
if (failIfRunning):
|
||||
return None
|
||||
|
||||
try:
|
||||
data = self.verifySendCMD(['exec ' + appname])
|
||||
@ -513,7 +522,11 @@ class DeviceManager:
|
||||
# returns:
|
||||
# success: output filename
|
||||
# failure: None
|
||||
def launchProcess(self, cmd, outputFile = "process.txt", cwd = '', env = ''):
|
||||
def launchProcess(self, cmd, outputFile = "process.txt", cwd = '', env = '', failIfRunning=False):
|
||||
if not cmd:
|
||||
if (self.debug >= 1): print "WARNING: launchProcess called without command to run"
|
||||
return None
|
||||
|
||||
cmdline = subprocess.list2cmdline(cmd)
|
||||
if (outputFile == "process.txt" or outputFile == None):
|
||||
outputFile = self.getDeviceRoot();
|
||||
@ -525,7 +538,7 @@ class DeviceManager:
|
||||
# Prepend our env to the command
|
||||
cmdline = '%s %s' % (self.formatEnvString(env), cmdline)
|
||||
|
||||
if self.fireProcess(cmdline) is None:
|
||||
if self.fireProcess(cmdline, failIfRunning) is None:
|
||||
return None
|
||||
return outputFile
|
||||
|
||||
@ -1073,7 +1086,7 @@ class DeviceManager:
|
||||
proclist.append(l.split('\t'))
|
||||
result['process'] = proclist
|
||||
|
||||
print "results: " + str(result)
|
||||
if (self.debug >= 3): print "results: " + str(result)
|
||||
return result
|
||||
|
||||
"""
|
||||
@ -1154,14 +1167,14 @@ class DeviceManager:
|
||||
if (destPath):
|
||||
cmd += " " + destPath
|
||||
|
||||
if (self.debug > 3): print "INFO: updateApp using command: " + str(cmd)
|
||||
|
||||
if (ipAddr is not None):
|
||||
ip, port = self.getCallbackIpAndPort(ipAddr, port)
|
||||
cmd += " %s %s" % (ip, port)
|
||||
# Set up our callback server
|
||||
callbacksvr = callbackServer(ip, port, self.debug)
|
||||
|
||||
if (self.debug >= 3): print "INFO: updateApp using command: " + str(cmd)
|
||||
|
||||
try:
|
||||
status = self.verifySendCMD([cmd])
|
||||
except(DMError):
|
||||
@ -1170,7 +1183,7 @@ class DeviceManager:
|
||||
if ipAddr is not None:
|
||||
status = callbacksvr.disconnect()
|
||||
|
||||
if (self.debug > 3): print "INFO: updateApp: got status back: " + str(status)
|
||||
if (self.debug >= 3): print "INFO: updateApp: got status back: " + str(status)
|
||||
|
||||
return status
|
||||
|
||||
@ -1209,13 +1222,65 @@ class DeviceManager:
|
||||
Returns a properly formatted env string for the agent.
|
||||
Input - env, which is either None, '', or a dict
|
||||
Output - a quoted string of the form: '"envvar1=val1,envvar2=val2..."'
|
||||
If env is None or '' return '""' (empty quoted string)
|
||||
If env is None or '' return '' (empty quoted string)
|
||||
"""
|
||||
def formatEnvString(self, env):
|
||||
if (env == None or env == ''):
|
||||
return '""'
|
||||
return ''
|
||||
|
||||
return '"%s"' % ','.join(map(lambda x: '%s=%s' % (x[0], x[1]), env.iteritems()))
|
||||
retVal = '"%s"' % ','.join(map(lambda x: '%s=%s' % (x[0], x[1]), env.iteritems()))
|
||||
if (retVal == '""'):
|
||||
return ''
|
||||
|
||||
return retVal
|
||||
|
||||
"""
|
||||
adjust the screen resolution on the device, REBOOT REQUIRED
|
||||
NOTE: this only works on a tegra ATM
|
||||
success: True
|
||||
failure: False
|
||||
|
||||
supported resolutions: 640x480, 800x600, 1024x768, 1152x864, 1200x1024, 1440x900, 1680x1050, 1920x1080
|
||||
"""
|
||||
def adjustResolution(self, width=1680, height=1050, type='hdmi'):
|
||||
if self.getInfo('os')['os'][0].split()[0] != 'harmony-eng':
|
||||
if (self.debug >= 2): print "WARNING: unable to adjust screen resolution on non Tegra device"
|
||||
return False
|
||||
|
||||
results = self.getInfo('screen')
|
||||
parts = results['screen'][0].split(':')
|
||||
if (self.debug >= 3): print "INFO: we have a current resolution of %s, %s" % (parts[1].split()[0], parts[2].split()[0])
|
||||
|
||||
#verify screen type is valid, and set it to the proper value (https://bugzilla.mozilla.org/show_bug.cgi?id=632895#c4)
|
||||
screentype = -1
|
||||
if (type == 'hdmi'):
|
||||
screentype = 5
|
||||
elif (type == 'vga' or type == 'crt'):
|
||||
screentype = 3
|
||||
else:
|
||||
return False
|
||||
|
||||
#verify we have numbers
|
||||
if not (isinstance(width, int) and isinstance(height, int)):
|
||||
return False
|
||||
|
||||
if (width < 100 or width > 9999):
|
||||
return False
|
||||
|
||||
if (height < 100 or height > 9999):
|
||||
return False
|
||||
|
||||
if (self.debug >= 3): print "INFO: adjusting screen resolution to %s, %s and rebooting" % (width, height)
|
||||
try:
|
||||
self.verifySendCMD(["exec setprop persist.tegra.dpy%s.mode.width %s" % (screentype, width)])
|
||||
self.verifySendCMD(["exec setprop persist.tegra.dpy%s.mode.height %s" % (screentype, height)])
|
||||
except(DMError):
|
||||
return False
|
||||
|
||||
if (self.reboot(True) == None):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
gCallbackData = ''
|
||||
|
||||
@ -1228,7 +1293,7 @@ class callbackServer():
|
||||
self.port = port
|
||||
self.connected = False
|
||||
self.debug = debuglevel
|
||||
if (self.debug > 3) : print "Creating server with " + str(ip) + ":" + str(port)
|
||||
if (self.debug >= 3) : print "Creating server with " + str(ip) + ":" + str(port)
|
||||
self.server = myServer((ip, port), self.myhandler)
|
||||
self.server_thread = Thread(target=self.server.serve_forever)
|
||||
self.server_thread.setDaemon(True)
|
||||
@ -1236,17 +1301,17 @@ class callbackServer():
|
||||
|
||||
def disconnect(self, step = 60, timeout = 600):
|
||||
t = 0
|
||||
if (self.debug > 3): print "Calling disconnect on callback server"
|
||||
if (self.debug >= 3): print "Calling disconnect on callback server"
|
||||
while t < timeout:
|
||||
if (gCallbackData):
|
||||
# Got the data back
|
||||
if (self.debug > 3): print "Got data back from agent: " + str(gCallbackData)
|
||||
if (self.debug >= 3): print "Got data back from agent: " + str(gCallbackData)
|
||||
break
|
||||
time.sleep(step)
|
||||
t += step
|
||||
|
||||
try:
|
||||
if (self.debug > 3): print "Shutting down server now"
|
||||
if (self.debug >= 3): print "Shutting down server now"
|
||||
self.server.shutdown()
|
||||
except:
|
||||
print "Unable to shutdown callback server - check for a connection on port: " + str(self.port)
|
||||
|
@ -130,7 +130,9 @@ class RemoteAutomation(Automation):
|
||||
dm = None
|
||||
def __init__(self, dm, cmd, stdout = None, stderr = None, env = None, cwd = '.'):
|
||||
self.dm = dm
|
||||
self.proc = dm.launchProcess(cmd, stdout, cwd, env)
|
||||
self.proc = dm.launchProcess(cmd, stdout, cwd, env, True)
|
||||
if (self.proc is None):
|
||||
raise Exception("unable to launch process")
|
||||
exepath = cmd[0]
|
||||
name = exepath.split('/')[-1]
|
||||
self.procName = name
|
||||
|
@ -88,7 +88,7 @@ test$(DLL_SUFFIX): test.$(OBJ_SUFFIX) elfhack $(CSRCS:.c=.$(OBJ_SUFFIX))
|
||||
[ $$(objdump -R $@.bak | wc -l) -gt $$(objdump -R $@ | wc -l) ]
|
||||
|
||||
dummy: dummy.$(OBJ_SUFFIX) test$(DLL_SUFFIX)
|
||||
$(CC) -o $@ $^
|
||||
$(CC) $(LDFLAGS) -o $@ $^
|
||||
|
||||
libs:: dummy
|
||||
# Will either crash or return exit code 1 if elfhack is broken
|
||||
@ -116,3 +116,4 @@ include $(topsrcdir)/config/rules.mk
|
||||
inject/%.$(OBJ_SUFFIX): DEFINES += -DBITS=$(if $(HAVE_64BIT_OS),64,32)
|
||||
inject/%.$(OBJ_SUFFIX): CFLAGS := -O2 -fno-stack-protector $(filter -m% -I%,$(CFLAGS))
|
||||
inject/$(CPU)-noinit.$(OBJ_SUFFIX): DEFINES += -DNOINIT
|
||||
test.$(OBJ_SUFFIX): CFLAGS := -O0
|
||||
|
@ -10,4 +10,4 @@
|
||||
# hardcoded milestones in the tree from these two files.
|
||||
#--------------------------------------------------------
|
||||
|
||||
2.0b12pre
|
||||
2.0b13pre
|
||||
|
136
configure.in
136
configure.in
@ -1837,6 +1837,74 @@ MOZ_ARG_ENABLE_BOOL(profiling,
|
||||
MOZ_PROFILING=1,
|
||||
MOZ_PROFILING= )
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Use Valgrind
|
||||
dnl ========================================================
|
||||
MOZ_ARG_ENABLE_BOOL(valgrind,
|
||||
[ --enable-valgrind Enable Valgrind integration hooks (default=no)],
|
||||
MOZ_VALGRIND=1,
|
||||
MOZ_VALGRIND= )
|
||||
if test -n "$MOZ_VALGRIND"; then
|
||||
AC_CHECK_HEADER([valgrind/valgrind.h], [],
|
||||
AC_MSG_ERROR(
|
||||
[--enable-valgrind specified but Valgrind is not installed]))
|
||||
AC_DEFINE(MOZ_VALGRIND)
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
dnl jprof
|
||||
dnl ========================================================
|
||||
MOZ_ARG_ENABLE_BOOL(jprof,
|
||||
[ --enable-jprof Enable jprof profiling tool (needs mozilla/tools/jprof). Implies --enable-profiling.],
|
||||
MOZ_JPROF=1,
|
||||
MOZ_JPROF= )
|
||||
if test -n "$MOZ_JPROF"; then
|
||||
MOZ_PROFILING=1
|
||||
AC_DEFINE(MOZ_JPROF)
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
dnl shark
|
||||
dnl ========================================================
|
||||
MOZ_ARG_ENABLE_BOOL(shark,
|
||||
[ --enable-shark Enable shark remote profiling. Implies --enable-profiling.],
|
||||
MOZ_SHARK=1,
|
||||
MOZ_SHARK= )
|
||||
if test -n "$MOZ_SHARK"; then
|
||||
MOZ_PROFILING=1
|
||||
AC_DEFINE(MOZ_SHARK)
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
dnl callgrind
|
||||
dnl ========================================================
|
||||
MOZ_ARG_ENABLE_BOOL(callgrind,
|
||||
[ --enable-callgrind Enable callgrind profiling],
|
||||
MOZ_CALLGRIND=1,
|
||||
MOZ_CALLGRIND= )
|
||||
if test -n "$MOZ_CALLGRIND"; then
|
||||
AC_DEFINE(MOZ_CALLGRIND)
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
dnl vtune
|
||||
dnl ========================================================
|
||||
MOZ_ARG_ENABLE_BOOL(vtune,
|
||||
[ --enable-vtune Enable vtune profiling. Implies --enable-profiling.],
|
||||
MOZ_VTUNE=1,
|
||||
MOZ_VTUNE= )
|
||||
if test -n "$MOZ_VTUNE"; then
|
||||
MOZ_PROFILING=1
|
||||
AC_DEFINE(MOZ_VTUNE)
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
dnl Profiling
|
||||
dnl ========================================================
|
||||
if test -n "$MOZ_PROFILING"; then
|
||||
AC_DEFINE(MOZ_PROFILING)
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
dnl System overrides of the defaults for host
|
||||
dnl ========================================================
|
||||
@ -7590,74 +7658,6 @@ if test -n "$MOZ_GCTIMER"; then
|
||||
AC_DEFINE(MOZ_GCTIMER)
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Use Valgrind
|
||||
dnl ========================================================
|
||||
MOZ_ARG_ENABLE_BOOL(valgrind,
|
||||
[ --enable-valgrind Enable Valgrind integration hooks (default=no)],
|
||||
MOZ_VALGRIND=1,
|
||||
MOZ_VALGRIND= )
|
||||
if test -n "$MOZ_VALGRIND"; then
|
||||
AC_CHECK_HEADER([valgrind/valgrind.h], [],
|
||||
AC_MSG_ERROR(
|
||||
[--enable-valgrind specified but Valgrind is not installed]))
|
||||
AC_DEFINE(MOZ_VALGRIND)
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
dnl jprof
|
||||
dnl ========================================================
|
||||
MOZ_ARG_ENABLE_BOOL(jprof,
|
||||
[ --enable-jprof Enable jprof profiling tool (needs mozilla/tools/jprof). Implies --enable-profiling.],
|
||||
MOZ_JPROF=1,
|
||||
MOZ_JPROF= )
|
||||
if test -n "$MOZ_JPROF"; then
|
||||
MOZ_PROFILING=1
|
||||
AC_DEFINE(MOZ_JPROF)
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
dnl shark
|
||||
dnl ========================================================
|
||||
MOZ_ARG_ENABLE_BOOL(shark,
|
||||
[ --enable-shark Enable shark remote profiling. Implies --enable-profiling.],
|
||||
MOZ_SHARK=1,
|
||||
MOZ_SHARK= )
|
||||
if test -n "$MOZ_SHARK"; then
|
||||
MOZ_PROFILING=1
|
||||
AC_DEFINE(MOZ_SHARK)
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
dnl callgrind
|
||||
dnl ========================================================
|
||||
MOZ_ARG_ENABLE_BOOL(callgrind,
|
||||
[ --enable-callgrind Enable callgrind profiling],
|
||||
MOZ_CALLGRIND=1,
|
||||
MOZ_CALLGRIND= )
|
||||
if test -n "$MOZ_CALLGRIND"; then
|
||||
AC_DEFINE(MOZ_CALLGRIND)
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
dnl vtune
|
||||
dnl ========================================================
|
||||
MOZ_ARG_ENABLE_BOOL(vtune,
|
||||
[ --enable-vtune Enable vtune profiling. Implies --enable-profiling.],
|
||||
MOZ_VTUNE=1,
|
||||
MOZ_VTUNE= )
|
||||
if test -n "$MOZ_VTUNE"; then
|
||||
MOZ_PROFILING=1
|
||||
AC_DEFINE(MOZ_VTUNE)
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
dnl Profiling
|
||||
dnl ========================================================
|
||||
if test -n "$MOZ_PROFILING"; then
|
||||
AC_DEFINE(MOZ_PROFILING)
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
dnl Zealous JavaScript GC
|
||||
dnl ========================================================
|
||||
|
@ -500,11 +500,18 @@ struct FindContentData
|
||||
*/
|
||||
struct nsRadioGroupStruct
|
||||
{
|
||||
nsRadioGroupStruct()
|
||||
: mRequiredRadioCount(0)
|
||||
, mGroupSuffersFromValueMissing(false)
|
||||
{}
|
||||
|
||||
/**
|
||||
* A strong pointer to the currently selected radio button.
|
||||
*/
|
||||
nsCOMPtr<nsIDOMHTMLInputElement> mSelectedRadioButton;
|
||||
nsCOMArray<nsIFormControl> mRadioButtons;
|
||||
PRUint32 mRequiredRadioCount;
|
||||
bool mGroupSuffersFromValueMissing;
|
||||
};
|
||||
|
||||
|
||||
@ -1725,6 +1732,7 @@ NS_INTERFACE_TABLE_HEAD(nsDocument)
|
||||
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsPIDOMEventTarget)
|
||||
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsISupportsWeakReference)
|
||||
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIRadioGroupContainer)
|
||||
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIRadioGroupContainer_MOZILLA_2_0_BRANCH)
|
||||
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIMutationObserver)
|
||||
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIApplicationCacheContainer)
|
||||
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIDOMNSDocument_MOZILLA_2_0_BRANCH)
|
||||
@ -6710,6 +6718,12 @@ nsDocument::AddToRadioGroup(const nsAString& aName,
|
||||
GetRadioGroup(aName, &radioGroup);
|
||||
if (radioGroup) {
|
||||
radioGroup->mRadioButtons.AppendObject(aRadio);
|
||||
|
||||
nsCOMPtr<nsIContent> element = do_QueryInterface(aRadio);
|
||||
NS_ASSERTION(element, "radio controls have to be content elements");
|
||||
if (element->HasAttr(kNameSpaceID_None, nsGkAtoms::required)) {
|
||||
radioGroup->mRequiredRadioCount++;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@ -6723,6 +6737,14 @@ nsDocument::RemoveFromRadioGroup(const nsAString& aName,
|
||||
GetRadioGroup(aName, &radioGroup);
|
||||
if (radioGroup) {
|
||||
radioGroup->mRadioButtons.RemoveObject(aRadio);
|
||||
|
||||
nsCOMPtr<nsIContent> element = do_QueryInterface(aRadio);
|
||||
NS_ASSERTION(element, "radio controls have to be content elements");
|
||||
if (element->HasAttr(kNameSpaceID_None, nsGkAtoms::required)) {
|
||||
radioGroup->mRequiredRadioCount--;
|
||||
NS_ASSERTION(radioGroup->mRequiredRadioCount >= 0,
|
||||
"mRequiredRadioCount shouldn't be negative!");
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@ -6750,6 +6772,70 @@ nsDocument::WalkRadioGroup(const nsAString& aName,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRUint32
|
||||
nsDocument::GetRequiredRadioCount(const nsAString& aName) const
|
||||
{
|
||||
nsRadioGroupStruct* radioGroup = nsnull;
|
||||
// TODO: we should call GetRadioGroup here (and make it const) but for that
|
||||
// we would need to have an explicit CreateRadioGroup() instead of create
|
||||
// one when GetRadioGroup is called. See bug 636123.
|
||||
nsAutoString tmKey(aName);
|
||||
if (IsHTML())
|
||||
ToLowerCase(tmKey); //should case-insensitive.
|
||||
mRadioGroups.Get(tmKey, &radioGroup);
|
||||
|
||||
return radioGroup ? radioGroup->mRequiredRadioCount : 0;
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::RadioRequiredChanged(const nsAString& aName, nsIFormControl* aRadio)
|
||||
{
|
||||
nsRadioGroupStruct* radioGroup = nsnull;
|
||||
GetRadioGroup(aName, &radioGroup);
|
||||
|
||||
if (!radioGroup) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> element = do_QueryInterface(aRadio);
|
||||
NS_ASSERTION(element, "radio controls have to be content elements");
|
||||
if (element->HasAttr(kNameSpaceID_None, nsGkAtoms::required)) {
|
||||
radioGroup->mRequiredRadioCount++;
|
||||
} else {
|
||||
radioGroup->mRequiredRadioCount--;
|
||||
NS_ASSERTION(radioGroup->mRequiredRadioCount >= 0,
|
||||
"mRequiredRadioCount shouldn't be negative!");
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
nsDocument::GetValueMissingState(const nsAString& aName) const
|
||||
{
|
||||
nsRadioGroupStruct* radioGroup = nsnull;
|
||||
// TODO: we should call GetRadioGroup here (and make it const) but for that
|
||||
// we would need to have an explicit CreateRadioGroup() instead of create
|
||||
// one when GetRadioGroup is called. See bug 636123.
|
||||
nsAutoString tmKey(aName);
|
||||
if (IsHTML())
|
||||
ToLowerCase(tmKey); //should case-insensitive.
|
||||
mRadioGroups.Get(tmKey, &radioGroup);
|
||||
|
||||
return radioGroup && radioGroup->mGroupSuffersFromValueMissing;
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::SetValueMissingState(const nsAString& aName, bool aValue)
|
||||
{
|
||||
nsRadioGroupStruct* radioGroup = nsnull;
|
||||
GetRadioGroup(aName, &radioGroup);
|
||||
|
||||
if (!radioGroup) {
|
||||
return;
|
||||
}
|
||||
|
||||
radioGroup->mGroupSuffersFromValueMissing = aValue;
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::RetrieveRelevantHeaders(nsIChannel *aChannel)
|
||||
{
|
||||
|
@ -515,7 +515,7 @@ class nsDocument : public nsIDocument,
|
||||
public nsIDOM3EventTarget,
|
||||
public nsIDOMNSEventTarget,
|
||||
public nsIScriptObjectPrincipal,
|
||||
public nsIRadioGroupContainer,
|
||||
public nsIRadioGroupContainer_MOZILLA_2_0_BRANCH,
|
||||
public nsIApplicationCacheContainer,
|
||||
public nsStubMutationObserver,
|
||||
public nsIDOMNSDocument_MOZILLA_2_0_BRANCH
|
||||
@ -790,6 +790,11 @@ public:
|
||||
nsIFormControl* aRadio);
|
||||
NS_IMETHOD RemoveFromRadioGroup(const nsAString& aName,
|
||||
nsIFormControl* aRadio);
|
||||
virtual PRUint32 GetRequiredRadioCount(const nsAString& aName) const;
|
||||
virtual void RadioRequiredChanged(const nsAString& aName,
|
||||
nsIFormControl* aRadio);
|
||||
virtual bool GetValueMissingState(const nsAString& aName) const;
|
||||
virtual void SetValueMissingState(const nsAString& aName, bool aValue);
|
||||
|
||||
// for radio group
|
||||
nsresult GetRadioGroup(const nsAString& aName,
|
||||
|
@ -332,6 +332,7 @@ nsFrameLoader::nsFrameLoader(nsIContent *aOwner, PRBool aNetworkCreated)
|
||||
, mCurrentRemoteFrame(nsnull)
|
||||
, mRemoteBrowser(nsnull)
|
||||
#endif
|
||||
, mRenderMode(RENDER_MODE_DEFAULT)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -389,7 +389,6 @@ nsresult nsTreeWalker::FirstChildInternal(PRBool aReversed, nsIDOMNode **_retval
|
||||
* @returns Errorcode
|
||||
*/
|
||||
nsresult nsTreeWalker::NextSiblingInternal(PRBool aReversed, nsIDOMNode **_retval)
|
||||
|
||||
{
|
||||
nsresult rv;
|
||||
PRInt16 filtered;
|
||||
@ -402,46 +401,39 @@ nsresult nsTreeWalker::NextSiblingInternal(PRBool aReversed, nsIDOMNode **_retva
|
||||
return NS_OK;
|
||||
|
||||
while (1) {
|
||||
nsCOMPtr<nsINode> sibling = aReversed ? node->GetPreviousSibling()
|
||||
: node->GetNextSibling();
|
||||
nsINode* sibling = aReversed ? node->GetPreviousSibling()
|
||||
: node->GetNextSibling();
|
||||
|
||||
while (sibling) {
|
||||
rv = TestNode(sibling, &filtered);
|
||||
node = sibling;
|
||||
|
||||
rv = TestNode(node, &filtered);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
switch (filtered) {
|
||||
case nsIDOMNodeFilter::FILTER_ACCEPT:
|
||||
// Node found
|
||||
mCurrentNode = sibling;
|
||||
return CallQueryInterface(sibling, _retval);
|
||||
case nsIDOMNodeFilter::FILTER_SKIP: {
|
||||
nsINode *firstChild = aReversed ? sibling->GetLastChild()
|
||||
: sibling->GetFirstChild();
|
||||
if (firstChild) {
|
||||
sibling = firstChild;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case nsIDOMNodeFilter::FILTER_REJECT:
|
||||
// Keep searching
|
||||
break;
|
||||
if (filtered == nsIDOMNodeFilter::FILTER_ACCEPT) {
|
||||
// Node found
|
||||
mCurrentNode.swap(node);
|
||||
return CallQueryInterface(mCurrentNode, _retval);
|
||||
}
|
||||
|
||||
// If rejected or no children, try a sibling
|
||||
if (filtered == nsIDOMNodeFilter::FILTER_REJECT ||
|
||||
!(sibling = aReversed ? node->GetLastChild()
|
||||
: node->GetFirstChild())) {
|
||||
sibling = aReversed ? node->GetPreviousSibling()
|
||||
: node->GetNextSibling();
|
||||
}
|
||||
sibling = aReversed ? sibling->GetPreviousSibling()
|
||||
: sibling->GetNextSibling();
|
||||
}
|
||||
|
||||
node = node->GetNodeParent();
|
||||
|
||||
if (!node || node == mRoot)
|
||||
break;
|
||||
return NS_OK;
|
||||
|
||||
// Is parent transparent in filtered view?
|
||||
rv = TestNode(node, &filtered);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (filtered == nsIDOMNodeFilter::FILTER_ACCEPT)
|
||||
break;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -468,6 +468,7 @@ _TEST_FILES2 = \
|
||||
test_bug558431.html \
|
||||
file_bug558431.html \
|
||||
file_bug558431.html^headers^ \
|
||||
test_bug628938.html \
|
||||
$(NULL)
|
||||
|
||||
# This test fails on the Mac for some reason
|
||||
|
240
content/base/test/test_bug628938.html
Normal file
240
content/base/test/test_bug628938.html
Normal file
@ -0,0 +1,240 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=628938
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 628938</title>
|
||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=628938">Mozilla Bug 628938</a>
|
||||
<p id="display"></p>
|
||||
<foo id="content" style="display: none">
|
||||
<div><div>foo</div></div>
|
||||
<span> bar </span>
|
||||
<div>tulip<span>bar</span></div>
|
||||
<span></span>
|
||||
<div>foo</div>
|
||||
<span></span>
|
||||
<div>bar</div>
|
||||
<span></span>
|
||||
<div>foobar</div>
|
||||
</foo>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 628938 **/
|
||||
|
||||
var gResults = [];
|
||||
var gIdx = 0;
|
||||
|
||||
function walkTree(walker)
|
||||
{
|
||||
if(walker.firstChild()) {
|
||||
do {
|
||||
if (walker.currentNode.nodeType == Node.ELEMENT_NODE) {
|
||||
ok(gResults[gIdx][0], "current node should be an element");
|
||||
is(walker.currentNode.nodeName, gResults[gIdx][1],
|
||||
"current node name should be " + gResults[gIdx][1]);
|
||||
} else {
|
||||
ok(!gResults[gIdx][0], "current node shouldn't be an element");
|
||||
is(walker.currentNode.nodeValue, gResults[gIdx][1],
|
||||
"current node value should be " + gResults[gIdx][1]);
|
||||
}
|
||||
gIdx++;
|
||||
// Recursively walk the rest of the sub-tree.
|
||||
walkTree(walker);
|
||||
} while(walker.nextSibling());
|
||||
|
||||
// don't forget to return the treewalker to it's previous state
|
||||
// before exiting the function
|
||||
walker.parentNode();
|
||||
}
|
||||
}
|
||||
|
||||
function regularWalk()
|
||||
{
|
||||
gResults = [
|
||||
[ false, "\n " ],
|
||||
[ true, "DIV" ],
|
||||
[ true, "DIV" ],
|
||||
[ false, "foo" ],
|
||||
[ false, "\n " ],
|
||||
[ true, "SPAN" ],
|
||||
[ false, " bar " ],
|
||||
[ false, "\n " ],
|
||||
[ true, "DIV" ],
|
||||
[ false, "tulip" ],
|
||||
[ true, "SPAN" ],
|
||||
[ false, "bar" ],
|
||||
[ false, "\n " ],
|
||||
[ true, "SPAN" ],
|
||||
[ false, "\n " ],
|
||||
[ true, "DIV" ],
|
||||
[ false, "foo" ],
|
||||
[ false, "\n " ],
|
||||
[ true, "SPAN" ],
|
||||
[ false, "\n " ],
|
||||
[ true, "DIV" ],
|
||||
[ false, "bar" ],
|
||||
[ false, "\n " ],
|
||||
[ true, "SPAN" ],
|
||||
[ false, "\n " ],
|
||||
[ true, "DIV" ],
|
||||
[ false, "foobar" ],
|
||||
[ false, "\n" ],
|
||||
];
|
||||
var walker = document.createTreeWalker(document.getElementById('content'),
|
||||
NodeFilter.SHOW_ALL, null, true);
|
||||
|
||||
walkTree(walker);
|
||||
|
||||
gIdx = 0;
|
||||
}
|
||||
|
||||
function noWhiteSpaceWalk()
|
||||
{
|
||||
gResults = [
|
||||
[ true, "DIV" ],
|
||||
[ true, "DIV" ],
|
||||
[ false, "foo" ],
|
||||
[ true, "SPAN" ],
|
||||
[ false, " bar " ],
|
||||
[ true, "DIV" ],
|
||||
[ false, "tulip" ],
|
||||
[ true, "SPAN" ],
|
||||
[ false, "bar" ],
|
||||
[ true, "SPAN" ],
|
||||
[ true, "DIV" ],
|
||||
[ false, "foo" ],
|
||||
[ true, "SPAN" ],
|
||||
[ true, "DIV" ],
|
||||
[ false, "bar" ],
|
||||
[ true, "SPAN" ],
|
||||
[ true, "DIV" ],
|
||||
[ false, "foobar" ],
|
||||
];
|
||||
var walker = document.createTreeWalker(document.getElementById('content'),
|
||||
NodeFilter.SHOW_ALL,
|
||||
{
|
||||
acceptNode : function(node) {
|
||||
if (node.nodeType == Node.TEXT_NODE &&
|
||||
!(/[^\t\n\r ]/.test(node.nodeValue)))
|
||||
return NodeFilter.FILTER_REJECT;
|
||||
return NodeFilter.FILTER_ACCEPT;
|
||||
}
|
||||
}, true);
|
||||
|
||||
walkTree(walker);
|
||||
|
||||
gIdx = 0;
|
||||
}
|
||||
|
||||
function onlyElementsWalk()
|
||||
{
|
||||
gResults = [
|
||||
[ true, "DIV" ],
|
||||
[ true, "DIV" ],
|
||||
[ true, "SPAN" ],
|
||||
[ true, "DIV" ],
|
||||
[ true, "SPAN" ],
|
||||
[ true, "SPAN" ],
|
||||
[ true, "DIV" ],
|
||||
[ true, "SPAN" ],
|
||||
[ true, "DIV" ],
|
||||
[ true, "SPAN" ],
|
||||
[ true, "DIV" ],
|
||||
];
|
||||
var walker = document.createTreeWalker(document.getElementById('content'),
|
||||
NodeFilter.SHOW_ELEMENT, null, true);
|
||||
|
||||
walkTree(walker);
|
||||
|
||||
gIdx = 0;
|
||||
}
|
||||
|
||||
function onlyDivSubTreeWalk()
|
||||
{
|
||||
gResults = [
|
||||
[ true, "DIV" ],
|
||||
[ true, "DIV" ],
|
||||
[ false, "foo" ],
|
||||
[ true, "DIV" ],
|
||||
[ false, "tulip" ],
|
||||
[ true, "SPAN" ],
|
||||
[ false, "bar" ],
|
||||
[ true, "DIV" ],
|
||||
[ false, "foo" ],
|
||||
[ true, "DIV" ],
|
||||
[ false, "bar" ],
|
||||
[ true, "DIV" ],
|
||||
[ false, "foobar" ],
|
||||
];
|
||||
var walker = document.createTreeWalker(document.getElementById('content'),
|
||||
NodeFilter.SHOW_ALL,
|
||||
{
|
||||
acceptNode : function(node) {
|
||||
if (node.nodeType == Node.TEXT_NODE &&
|
||||
!(/[^\t\n\r ]/.test(node.nodeValue)))
|
||||
return NodeFilter.FILTER_REJECT;
|
||||
|
||||
while (node) {
|
||||
if (node.nodeName == "DIV")
|
||||
return NodeFilter.FILTER_ACCEPT;
|
||||
node = node.parentNode;
|
||||
}
|
||||
return NodeFilter.FILTER_SKIP;
|
||||
}
|
||||
}, true);
|
||||
|
||||
walkTree(walker);
|
||||
|
||||
gIdx = 0;
|
||||
}
|
||||
|
||||
function onlyDivDataWalk()
|
||||
{
|
||||
gResults = [
|
||||
[ true, "DIV" ],
|
||||
[ true, "DIV" ],
|
||||
[ false, "foo" ],
|
||||
[ true, "DIV" ],
|
||||
[ false, "tulip" ],
|
||||
[ true, "SPAN" ],
|
||||
[ true, "DIV" ],
|
||||
[ false, "foo" ],
|
||||
[ true, "DIV" ],
|
||||
[ false, "bar" ],
|
||||
[ true, "DIV" ],
|
||||
[ false, "foobar" ],
|
||||
];
|
||||
var walker = document.createTreeWalker(document.getElementById('content'),
|
||||
NodeFilter.SHOW_ALL,
|
||||
{
|
||||
acceptNode : function(node) {
|
||||
if (node.nodeName == "DIV" ||
|
||||
(node.parentNode &&
|
||||
node.parentNode.nodeName == "DIV"))
|
||||
return NodeFilter.FILTER_ACCEPT;
|
||||
return NodeFilter.FILTER_SKIP;
|
||||
}
|
||||
}, true);
|
||||
|
||||
walkTree(walker);
|
||||
|
||||
gIdx = 0;
|
||||
}
|
||||
|
||||
regularWalk();
|
||||
noWhiteSpaceWalk();
|
||||
onlyElementsWalk();
|
||||
onlyDivSubTreeWalk();
|
||||
onlyDivDataWalk();
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -113,11 +113,17 @@ WebGLContext::WebGLContext()
|
||||
mBlackTexturesAreInitialized = PR_FALSE;
|
||||
mFakeBlackStatus = DoNotNeedFakeBlack;
|
||||
|
||||
mFakeVertexAttrib0Array = nsnull;
|
||||
mVertexAttrib0Vector[0] = 0;
|
||||
mVertexAttrib0Vector[1] = 0;
|
||||
mVertexAttrib0Vector[2] = 0;
|
||||
mVertexAttrib0Vector[3] = 1;
|
||||
mFakeVertexAttrib0BufferObjectVector[0] = 0;
|
||||
mFakeVertexAttrib0BufferObjectVector[1] = 0;
|
||||
mFakeVertexAttrib0BufferObjectVector[2] = 0;
|
||||
mFakeVertexAttrib0BufferObjectVector[3] = 1;
|
||||
mFakeVertexAttrib0BufferObjectSize = 0;
|
||||
mFakeVertexAttrib0BufferObject = 0;
|
||||
mFakeVertexAttrib0BufferStatus = VertexAttrib0Status::Default;
|
||||
}
|
||||
|
||||
WebGLContext::~WebGLContext()
|
||||
@ -223,6 +229,10 @@ WebGLContext::DestroyResourcesAndContext()
|
||||
mBlackTexturesAreInitialized = PR_FALSE;
|
||||
}
|
||||
|
||||
if (mFakeVertexAttrib0BufferObject) {
|
||||
gl->fDeleteBuffers(1, &mFakeVertexAttrib0BufferObject);
|
||||
}
|
||||
|
||||
// We just got rid of everything, so the context had better
|
||||
// have been going away.
|
||||
#ifdef DEBUG
|
||||
|
@ -80,6 +80,10 @@ class WebGLContextBoundObject;
|
||||
|
||||
enum FakeBlackStatus { DoNotNeedFakeBlack, DoNeedFakeBlack, DontKnowIfNeedFakeBlack };
|
||||
|
||||
struct VertexAttrib0Status {
|
||||
enum { Default, EmulatedUninitializedArray, EmulatedInitializedArray };
|
||||
};
|
||||
|
||||
struct WebGLTexelFormat {
|
||||
enum { Generic, Auto, RGBA8, RGB8, RGBX8, BGRA8, BGR8, BGRX8, RGBA5551, RGBA4444, RGB565, R8, RA8, A8 };
|
||||
};
|
||||
@ -357,6 +361,7 @@ public:
|
||||
nsresult ErrorInvalidEnumInfo(const char *info, PRUint32 enumvalue) {
|
||||
return ErrorInvalidEnum("%s: invalid enum value 0x%x", info, enumvalue);
|
||||
}
|
||||
nsresult ErrorOutOfMemory(const char *fmt = 0, ...);
|
||||
|
||||
WebGLTexture *activeBoundTextureForTarget(WebGLenum target) {
|
||||
return target == LOCAL_GL_TEXTURE_2D ? mBound2DTextures[mActiveTexture]
|
||||
@ -371,6 +376,7 @@ public:
|
||||
// all context resources to be lost.
|
||||
PRUint32 Generation() { return mGeneration.value(); }
|
||||
|
||||
protected:
|
||||
void SetDontKnowIfNeedFakeBlack() {
|
||||
mFakeBlackStatus = DontKnowIfNeedFakeBlack;
|
||||
}
|
||||
@ -379,11 +385,11 @@ public:
|
||||
void BindFakeBlackTextures();
|
||||
void UnbindFakeBlackTextures();
|
||||
|
||||
PRBool NeedFakeVertexAttrib0();
|
||||
int WhatDoesVertexAttrib0Need();
|
||||
void DoFakeVertexAttrib0(WebGLuint vertexCount);
|
||||
void UndoFakeVertexAttrib0();
|
||||
void InvalidateFakeVertexAttrib0();
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsIDOMHTMLCanvasElement> mCanvasElement;
|
||||
nsHTMLCanvasElement *HTMLCanvasElement() {
|
||||
return static_cast<nsHTMLCanvasElement*>(mCanvasElement.get());
|
||||
@ -434,6 +440,7 @@ protected:
|
||||
PRBool ValidateTexFormatAndType(WebGLenum format, WebGLenum type,
|
||||
PRUint32 *texelSize, const char *info);
|
||||
PRBool ValidateDrawModeEnum(WebGLenum mode, const char *info);
|
||||
PRBool ValidateAttribIndex(WebGLuint index, const char *info);
|
||||
|
||||
void Invalidate();
|
||||
void DestroyResourcesAndContext();
|
||||
@ -509,6 +516,9 @@ protected:
|
||||
PRBool *isNull = 0,
|
||||
PRBool *isDeleted = 0);
|
||||
|
||||
PRInt32 MaxTextureSizeForTarget(WebGLenum target) const {
|
||||
return target == LOCAL_GL_TEXTURE_2D ? mGLMaxTextureSize : mGLMaxCubeMapTextureSize;
|
||||
}
|
||||
|
||||
// the buffers bound to the current program's attribs
|
||||
nsTArray<WebGLVertexAttribData> mAttribBuffers;
|
||||
@ -550,7 +560,10 @@ protected:
|
||||
PRBool mBlackTexturesAreInitialized;
|
||||
|
||||
WebGLfloat mVertexAttrib0Vector[4];
|
||||
nsAutoArrayPtr<WebGLfloat> mFakeVertexAttrib0Array;
|
||||
WebGLfloat mFakeVertexAttrib0BufferObjectVector[4];
|
||||
size_t mFakeVertexAttrib0BufferObjectSize;
|
||||
GLuint mFakeVertexAttrib0BufferObject;
|
||||
int mFakeVertexAttrib0BufferStatus;
|
||||
|
||||
WebGLint mStencilRef;
|
||||
WebGLuint mStencilValueMask, mStencilWriteMask;
|
||||
@ -699,19 +712,25 @@ public:
|
||||
|
||||
// element array buffers are the only buffers for which we need to keep a copy of the data.
|
||||
// this method assumes that the byte length has previously been set by calling SetByteLength.
|
||||
void CopyDataIfElementArray(const void* data) {
|
||||
PRBool CopyDataIfElementArray(const void* data) {
|
||||
if (mTarget == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
|
||||
mData = realloc(mData, mByteLength);
|
||||
if (!mData)
|
||||
return PR_FALSE;
|
||||
memcpy(mData, data, mByteLength);
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
// same comments as for CopyElementArrayData
|
||||
void ZeroDataIfElementArray() {
|
||||
PRBool ZeroDataIfElementArray() {
|
||||
if (mTarget == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
|
||||
mData = realloc(mData, mByteLength);
|
||||
if (!mData)
|
||||
return PR_FALSE;
|
||||
memset(mData, 0, mByteLength);
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
// same comments as for CopyElementArrayData
|
||||
@ -871,6 +890,16 @@ public:
|
||||
return const_cast<WebGLTexture*>(this)->ImageInfoAt(level, face);
|
||||
}
|
||||
|
||||
PRBool HasImageInfoAt(size_t level, size_t face) const {
|
||||
return level <= mMaxLevelWithCustomImages &&
|
||||
face < mFacesCount &&
|
||||
ImageInfoAt(level, 0).mIsDefined;
|
||||
}
|
||||
|
||||
static size_t FaceForTarget(WebGLenum target) {
|
||||
return target == LOCAL_GL_TEXTURE_2D ? 0 : target - LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
WebGLenum mTarget;
|
||||
@ -961,14 +990,12 @@ public:
|
||||
|
||||
void SetImageInfo(WebGLenum aTarget, WebGLint aLevel,
|
||||
WebGLsizei aWidth, WebGLsizei aHeight,
|
||||
WebGLenum aFormat = 0, WebGLenum aType = 0) {
|
||||
size_t face = 0;
|
||||
if (aTarget == LOCAL_GL_TEXTURE_2D) {
|
||||
if (mTarget != LOCAL_GL_TEXTURE_2D) return;
|
||||
} else {
|
||||
if (mTarget == LOCAL_GL_TEXTURE_2D) return;
|
||||
face = aTarget - LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X;
|
||||
}
|
||||
WebGLenum aFormat = 0, WebGLenum aType = 0)
|
||||
{
|
||||
if ( (aTarget == LOCAL_GL_TEXTURE_2D) != (mTarget == LOCAL_GL_TEXTURE_2D) )
|
||||
return;
|
||||
|
||||
size_t face = FaceForTarget(aTarget);
|
||||
|
||||
EnsureMaxLevelWithCustomImagesAtLeast(aLevel);
|
||||
|
||||
|
@ -183,6 +183,9 @@ WebGLContext::BindAttribLocation(nsIWebGLProgram *pobj, WebGLuint location, cons
|
||||
if (name.IsEmpty())
|
||||
return ErrorInvalidValue("BindAttribLocation: name can't be null or empty");
|
||||
|
||||
if (!ValidateAttribIndex(location, "bindAttribLocation"))
|
||||
return NS_OK;
|
||||
|
||||
MakeContextCurrent();
|
||||
|
||||
gl->fBindAttribLocation(progname, location, NS_LossyConvertUTF16toASCII(name).get());
|
||||
@ -398,7 +401,8 @@ WebGLContext::BufferData_size(WebGLenum target, WebGLsizei size, WebGLenum usage
|
||||
MakeContextCurrent();
|
||||
|
||||
boundBuffer->SetByteLength(size);
|
||||
boundBuffer->ZeroDataIfElementArray();
|
||||
if (!boundBuffer->ZeroDataIfElementArray())
|
||||
return ErrorOutOfMemory("bufferData: out of memory");
|
||||
boundBuffer->InvalidateCachedMaxElements();
|
||||
|
||||
gl->fBufferData(target, size, 0, usage);
|
||||
@ -428,7 +432,8 @@ WebGLContext::BufferData_buf(WebGLenum target, js::ArrayBuffer *wb, WebGLenum us
|
||||
MakeContextCurrent();
|
||||
|
||||
boundBuffer->SetByteLength(wb->byteLength);
|
||||
boundBuffer->CopyDataIfElementArray(wb->data);
|
||||
if (!boundBuffer->CopyDataIfElementArray(wb->data))
|
||||
return ErrorOutOfMemory("bufferData: out of memory");
|
||||
boundBuffer->InvalidateCachedMaxElements();
|
||||
|
||||
gl->fBufferData(target, wb->byteLength, wb->data, usage);
|
||||
@ -458,7 +463,8 @@ WebGLContext::BufferData_array(WebGLenum target, js::TypedArray *wa, WebGLenum u
|
||||
MakeContextCurrent();
|
||||
|
||||
boundBuffer->SetByteLength(wa->byteLength);
|
||||
boundBuffer->CopyDataIfElementArray(wa->data);
|
||||
if (!boundBuffer->CopyDataIfElementArray(wa->data))
|
||||
return ErrorOutOfMemory("bufferData: out of memory");
|
||||
boundBuffer->InvalidateCachedMaxElements();
|
||||
|
||||
gl->fBufferData(target, wa->byteLength, wa->data, usage);
|
||||
@ -656,7 +662,7 @@ WebGLContext::CopyTexSubImage2D_base(WebGLenum target,
|
||||
// Hopefully calloc will just mmap zero pages here.
|
||||
void *tempZeroData = calloc(1, bytesNeeded);
|
||||
if (!tempZeroData)
|
||||
return SynthesizeGLError(LOCAL_GL_OUT_OF_MEMORY, "%s: could not allocate %d bytes (for zero fill)", info, bytesNeeded);
|
||||
return ErrorOutOfMemory("%s: could not allocate %d bytes (for zero fill)", info, bytesNeeded);
|
||||
|
||||
// now initialize the texture as black
|
||||
|
||||
@ -737,6 +743,10 @@ WebGLContext::CopyTexImage2D(WebGLenum target,
|
||||
if (level < 0)
|
||||
return ErrorInvalidValue("copyTexImage2D: level may not be negative");
|
||||
|
||||
WebGLsizei maxTextureSize = MaxTextureSizeForTarget(target);
|
||||
if (!(maxTextureSize >> level))
|
||||
return ErrorInvalidValue("copyTexImage2D: 2^level exceeds maximum texture size");
|
||||
|
||||
if (level >= 1) {
|
||||
if (!(is_pot_assuming_nonnegative(width) &&
|
||||
is_pot_assuming_nonnegative(height)))
|
||||
@ -790,6 +800,10 @@ WebGLContext::CopyTexSubImage2D(WebGLenum target,
|
||||
if (level < 0)
|
||||
return ErrorInvalidValue("copyTexSubImage2D: level may not be negative");
|
||||
|
||||
WebGLsizei maxTextureSize = MaxTextureSizeForTarget(target);
|
||||
if (!(maxTextureSize >> level))
|
||||
return ErrorInvalidValue("copyTexSubImage2D: 2^level exceeds maximum texture size");
|
||||
|
||||
if (width < 0 || height < 0)
|
||||
return ErrorInvalidValue("copyTexSubImage2D: width and height may not be negative");
|
||||
|
||||
@ -800,8 +814,12 @@ WebGLContext::CopyTexSubImage2D(WebGLenum target,
|
||||
if (!tex)
|
||||
return ErrorInvalidOperation("copyTexSubImage2D: no texture bound to this target");
|
||||
|
||||
WebGLsizei texWidth = tex->ImageInfoAt(level,0).mWidth;
|
||||
WebGLsizei texHeight = tex->ImageInfoAt(level,0).mHeight;
|
||||
WebGLint face = WebGLTexture::FaceForTarget(target);
|
||||
if (!tex->HasImageInfoAt(level, face))
|
||||
return ErrorInvalidOperation("copyTexSubImage2D: to texture image previously defined for this level and face");
|
||||
|
||||
WebGLsizei texWidth = tex->ImageInfoAt(level, face).mWidth;
|
||||
WebGLsizei texHeight = tex->ImageInfoAt(level, face).mHeight;
|
||||
|
||||
if (xoffset + width > texWidth || xoffset + width < 0)
|
||||
return ErrorInvalidValue("copyTexSubImage2D: xoffset+width is too large");
|
||||
@ -809,7 +827,7 @@ WebGLContext::CopyTexSubImage2D(WebGLenum target,
|
||||
if (yoffset + height > texHeight || yoffset + height < 0)
|
||||
return ErrorInvalidValue("copyTexSubImage2D: yoffset+height is too large");
|
||||
|
||||
WebGLenum format = tex->ImageInfoAt(level,0).mFormat;
|
||||
WebGLenum format = tex->ImageInfoAt(level, face).mFormat;
|
||||
PRBool texFormatRequiresAlpha = format == LOCAL_GL_RGBA ||
|
||||
format == LOCAL_GL_ALPHA ||
|
||||
format == LOCAL_GL_LUMINANCE_ALPHA;
|
||||
@ -1072,8 +1090,8 @@ WebGLContext::DepthRange(WebGLfloat zNear, WebGLfloat zFar)
|
||||
NS_IMETHODIMP
|
||||
WebGLContext::DisableVertexAttribArray(WebGLuint index)
|
||||
{
|
||||
if (index > mAttribBuffers.Length())
|
||||
return ErrorInvalidValue("DisableVertexAttribArray: index out of range");
|
||||
if (!ValidateAttribIndex(index, "disableVertexAttribArray"))
|
||||
return NS_OK;
|
||||
|
||||
MakeContextCurrent();
|
||||
|
||||
@ -1085,46 +1103,91 @@ WebGLContext::DisableVertexAttribArray(WebGLuint index)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRBool
|
||||
WebGLContext::NeedFakeVertexAttrib0()
|
||||
int
|
||||
WebGLContext::WhatDoesVertexAttrib0Need()
|
||||
{
|
||||
return !gl->IsGLES2() &&
|
||||
!mAttribBuffers[0].enabled;
|
||||
// here we may assume that mCurrentProgram != null
|
||||
|
||||
// work around Mac OSX crash, see bug 631420
|
||||
#ifdef XP_MACOSX
|
||||
if (mAttribBuffers[0].enabled &&
|
||||
!mCurrentProgram->IsAttribInUse(0))
|
||||
return VertexAttrib0Status::EmulatedUninitializedArray;
|
||||
#endif
|
||||
|
||||
return (gl->IsGLES2() || mAttribBuffers[0].enabled) ? VertexAttrib0Status::Default
|
||||
: mCurrentProgram->IsAttribInUse(0) ? VertexAttrib0Status::EmulatedInitializedArray
|
||||
: VertexAttrib0Status::EmulatedUninitializedArray;
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::DoFakeVertexAttrib0(WebGLuint vertexCount)
|
||||
{
|
||||
if (!NeedFakeVertexAttrib0())
|
||||
int whatDoesAttrib0Need = WhatDoesVertexAttrib0Need();
|
||||
|
||||
if (whatDoesAttrib0Need == VertexAttrib0Status::Default)
|
||||
return;
|
||||
|
||||
mFakeVertexAttrib0Array = new WebGLfloat[4 * vertexCount];
|
||||
WebGLuint dataSize = sizeof(WebGLfloat) * 4 * vertexCount;
|
||||
|
||||
for(size_t i = 0; i < vertexCount; ++i) {
|
||||
mFakeVertexAttrib0Array[4 * i + 0] = mVertexAttrib0Vector[0];
|
||||
mFakeVertexAttrib0Array[4 * i + 1] = mVertexAttrib0Vector[1];
|
||||
mFakeVertexAttrib0Array[4 * i + 2] = mVertexAttrib0Vector[2];
|
||||
mFakeVertexAttrib0Array[4 * i + 3] = mVertexAttrib0Vector[3];
|
||||
if (!mFakeVertexAttrib0BufferObject) {
|
||||
gl->fGenBuffers(1, &mFakeVertexAttrib0BufferObject);
|
||||
}
|
||||
|
||||
gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
|
||||
gl->fVertexAttribPointer(0, 4, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, mFakeVertexAttrib0Array);
|
||||
// if the VBO status is already exactly what we need, or if the only difference is that it's initialized and
|
||||
// we don't need it to be, then consider it OK
|
||||
PRBool vertexAttrib0BufferStatusOK =
|
||||
mFakeVertexAttrib0BufferStatus == whatDoesAttrib0Need ||
|
||||
(mFakeVertexAttrib0BufferStatus == VertexAttrib0Status::EmulatedInitializedArray &&
|
||||
whatDoesAttrib0Need == VertexAttrib0Status::EmulatedUninitializedArray);
|
||||
|
||||
if (!vertexAttrib0BufferStatusOK ||
|
||||
mFakeVertexAttrib0BufferObjectSize < dataSize ||
|
||||
mFakeVertexAttrib0BufferObjectVector[0] != mVertexAttrib0Vector[0] ||
|
||||
mFakeVertexAttrib0BufferObjectVector[1] != mVertexAttrib0Vector[1] ||
|
||||
mFakeVertexAttrib0BufferObjectVector[2] != mVertexAttrib0Vector[2] ||
|
||||
mFakeVertexAttrib0BufferObjectVector[3] != mVertexAttrib0Vector[3])
|
||||
{
|
||||
mFakeVertexAttrib0BufferStatus = whatDoesAttrib0Need;
|
||||
mFakeVertexAttrib0BufferObjectSize = dataSize;
|
||||
mFakeVertexAttrib0BufferObjectVector[0] = mVertexAttrib0Vector[0];
|
||||
mFakeVertexAttrib0BufferObjectVector[1] = mVertexAttrib0Vector[1];
|
||||
mFakeVertexAttrib0BufferObjectVector[2] = mVertexAttrib0Vector[2];
|
||||
mFakeVertexAttrib0BufferObjectVector[3] = mVertexAttrib0Vector[3];
|
||||
|
||||
gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mFakeVertexAttrib0BufferObject);
|
||||
|
||||
WebGLuint dataSize = sizeof(WebGLfloat) * 4 * vertexCount;
|
||||
|
||||
if (mFakeVertexAttrib0BufferStatus == VertexAttrib0Status::EmulatedInitializedArray) {
|
||||
nsAutoArrayPtr<WebGLfloat> array(new WebGLfloat[4 * vertexCount]);
|
||||
for(size_t i = 0; i < vertexCount; ++i) {
|
||||
array[4 * i + 0] = mVertexAttrib0Vector[0];
|
||||
array[4 * i + 1] = mVertexAttrib0Vector[1];
|
||||
array[4 * i + 2] = mVertexAttrib0Vector[2];
|
||||
array[4 * i + 3] = mVertexAttrib0Vector[3];
|
||||
}
|
||||
gl->fBufferData(LOCAL_GL_ARRAY_BUFFER, dataSize, array, LOCAL_GL_DYNAMIC_DRAW);
|
||||
} else {
|
||||
gl->fBufferData(LOCAL_GL_ARRAY_BUFFER, dataSize, nsnull, LOCAL_GL_DYNAMIC_DRAW);
|
||||
}
|
||||
|
||||
gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mBoundArrayBuffer ? mBoundArrayBuffer->GLName() : 0);
|
||||
}
|
||||
|
||||
gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mFakeVertexAttrib0BufferObject);
|
||||
gl->fVertexAttribPointer(0, 4, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, 0);
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::UndoFakeVertexAttrib0()
|
||||
{
|
||||
if (!NeedFakeVertexAttrib0())
|
||||
int whatDoesAttrib0Need = WhatDoesVertexAttrib0Need();
|
||||
|
||||
if (whatDoesAttrib0Need == VertexAttrib0Status::Default)
|
||||
return;
|
||||
|
||||
mFakeVertexAttrib0Array = nsnull;
|
||||
|
||||
// first set the bound buffer as needed for subsequent gl->fVertexAttribPointer call.
|
||||
// since in DoFakeVertexAttrib0() we called bindBuffer on buffer zero, we only need to do that if
|
||||
// we have a nonzero buffer binding for this attrib.
|
||||
if (mAttribBuffers[0].buf)
|
||||
gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mAttribBuffers[0].buf->GLName());
|
||||
|
||||
gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mAttribBuffers[0].buf ? mAttribBuffers[0].buf->GLName() : 0);
|
||||
gl->fVertexAttribPointer(0,
|
||||
mAttribBuffers[0].size,
|
||||
mAttribBuffers[0].type,
|
||||
@ -1132,7 +1195,6 @@ WebGLContext::UndoFakeVertexAttrib0()
|
||||
mAttribBuffers[0].stride,
|
||||
(const GLvoid *) mAttribBuffers[0].byteOffset);
|
||||
|
||||
// now restore the bound buffer to its state before we did this whole draw call business
|
||||
gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mBoundArrayBuffer ? mBoundArrayBuffer->GLName() : 0);
|
||||
}
|
||||
|
||||
@ -1393,8 +1455,8 @@ NS_IMETHODIMP WebGLContext::Disable(WebGLenum cap)
|
||||
NS_IMETHODIMP
|
||||
WebGLContext::EnableVertexAttribArray(WebGLuint index)
|
||||
{
|
||||
if (index > mAttribBuffers.Length())
|
||||
return ErrorInvalidValue("EnableVertexAttribArray: index out of range");
|
||||
if (!ValidateAttribIndex(index, "enableVertexAttribArray"))
|
||||
return NS_OK;
|
||||
|
||||
MakeContextCurrent();
|
||||
|
||||
@ -2453,8 +2515,8 @@ WebGLContext::GetVertexAttrib(WebGLuint index, WebGLenum pname, nsIVariant **ret
|
||||
{
|
||||
*retval = nsnull;
|
||||
|
||||
if (index >= mAttribBuffers.Length())
|
||||
return ErrorInvalidValue("getVertexAttrib: invalid index");
|
||||
if (!ValidateAttribIndex(index, "getVertexAttrib"))
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIWritableVariant> wrval = do_CreateInstance("@mozilla.org/variant;1");
|
||||
NS_ENSURE_TRUE(wrval, NS_ERROR_FAILURE);
|
||||
@ -2520,8 +2582,8 @@ WebGLContext::GetVertexAttribOffset(WebGLuint index, WebGLenum pname, WebGLuint
|
||||
{
|
||||
*retval = 0;
|
||||
|
||||
if (index >= mAttribBuffers.Length())
|
||||
return ErrorInvalidValue("getVertexAttribOffset: invalid index");
|
||||
if (!ValidateAttribIndex(index, "getVertexAttribOffset"))
|
||||
return NS_OK;
|
||||
|
||||
if (pname != LOCAL_GL_VERTEX_ATTRIB_ARRAY_POINTER)
|
||||
return ErrorInvalidEnum("getVertexAttribOffset: bad parameter");
|
||||
@ -3814,8 +3876,8 @@ WebGLContext::VertexAttribPointer(WebGLuint index, WebGLint size, WebGLenum type
|
||||
// requiredAlignment should always be a power of two.
|
||||
WebGLsizei requiredAlignmentMask = requiredAlignment - 1;
|
||||
|
||||
if (index >= mAttribBuffers.Length())
|
||||
return ErrorInvalidValue("VertexAttribPointer: index out of range - %d >= %d", index, mAttribBuffers.Length());
|
||||
if (!ValidateAttribIndex(index, "vertexAttribPointer"))
|
||||
return NS_OK;
|
||||
|
||||
if (size < 1 || size > 4)
|
||||
return ErrorInvalidValue("VertexAttribPointer: invalid element size");
|
||||
@ -3904,12 +3966,12 @@ WebGLContext::TexImage2D_base(WebGLenum target, WebGLint level, WebGLenum intern
|
||||
if (format != internalformat)
|
||||
return ErrorInvalidOperation("texImage2D: format does not match internalformat");
|
||||
|
||||
WebGLsizei maxTextureSize = target == LOCAL_GL_TEXTURE_2D ? mGLMaxTextureSize : mGLMaxCubeMapTextureSize;
|
||||
WebGLsizei maxTextureSize = MaxTextureSizeForTarget(target);
|
||||
|
||||
if (level < 0)
|
||||
return ErrorInvalidValue("texImage2D: level must be >= 0");
|
||||
|
||||
if ((1 << level) > maxTextureSize)
|
||||
if (!(maxTextureSize >> level))
|
||||
return ErrorInvalidValue("texImage2D: 2^level exceeds maximum texture size");
|
||||
|
||||
if (width < 0 || height < 0)
|
||||
@ -3992,7 +4054,7 @@ WebGLContext::TexImage2D_base(WebGLenum target, WebGLint level, WebGLenum intern
|
||||
// Hopefully calloc will just mmap zero pages here.
|
||||
void *tempZeroData = calloc(1, bytesNeeded);
|
||||
if (!tempZeroData)
|
||||
return SynthesizeGLError(LOCAL_GL_OUT_OF_MEMORY, "texImage2D: could not allocate %d bytes (for zero fill)", bytesNeeded);
|
||||
return ErrorOutOfMemory("texImage2D: could not allocate %d bytes (for zero fill)", bytesNeeded);
|
||||
|
||||
gl->fTexImage2D(target, level, internalformat, width, height, border, format, type, tempZeroData);
|
||||
|
||||
@ -4087,12 +4149,12 @@ WebGLContext::TexSubImage2D_base(WebGLenum target, WebGLint level,
|
||||
return ErrorInvalidEnumInfo("texSubImage2D: target", target);
|
||||
}
|
||||
|
||||
WebGLsizei maxTextureSize = target == LOCAL_GL_TEXTURE_2D ? mGLMaxTextureSize : mGLMaxCubeMapTextureSize;
|
||||
WebGLsizei maxTextureSize = MaxTextureSizeForTarget(target);
|
||||
|
||||
if (level < 0)
|
||||
return ErrorInvalidValue("texSubImage2D: level must be >= 0");
|
||||
|
||||
if ((1 << level) > maxTextureSize)
|
||||
if (!(maxTextureSize >> level))
|
||||
return ErrorInvalidValue("texSubImage2D: 2^level exceeds maximum texture size");
|
||||
|
||||
if (width < 0 || height < 0)
|
||||
|
@ -315,3 +315,15 @@ WebGLContext::ErrorInvalidValue(const char *fmt, ...)
|
||||
|
||||
return SynthesizeGLError(LOCAL_GL_INVALID_VALUE);
|
||||
}
|
||||
|
||||
nsresult
|
||||
WebGLContext::ErrorOutOfMemory(const char *fmt, ...)
|
||||
{
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
LogMessageIfVerbose(fmt, va);
|
||||
va_end(va);
|
||||
|
||||
return SynthesizeGLError(LOCAL_GL_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
|
@ -376,6 +376,22 @@ PRBool WebGLContext::ValidateTexFormatAndType(WebGLenum format, WebGLenum type,
|
||||
}
|
||||
}
|
||||
|
||||
PRBool WebGLContext::ValidateAttribIndex(WebGLuint index, const char *info)
|
||||
{
|
||||
if (index > mAttribBuffers.Length()) {
|
||||
if (index == WebGLuint(-1)) {
|
||||
ErrorInvalidValue("%s: index -1 is invalid. That probably comes from a getAttribLication() call, "
|
||||
"where this return value -1 means that the passed name didn't correspond to an active attribute in "
|
||||
"the specified program.", info);
|
||||
} else {
|
||||
ErrorInvalidValue("%s: index %d is out of range", info, index);
|
||||
}
|
||||
return PR_FALSE;
|
||||
} else {
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
WebGLContext::InitAndValidateGL()
|
||||
{
|
||||
|
@ -51,6 +51,7 @@
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsCRT.h"
|
||||
#include "nsIScriptObjectPrincipal.h"
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_2(nsDOMDataTransfer, mDragTarget, mDragImage)
|
||||
|
||||
@ -459,8 +460,28 @@ nsDOMDataTransfer::MozGetDataAt(const nsAString& aFormat,
|
||||
(NS_FAILED(principal->Subsumes(formatitem.mPrincipal, &subsumes)) || !subsumes))
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
|
||||
if (!formatitem.mData)
|
||||
if (!formatitem.mData) {
|
||||
FillInExternalDragData(formatitem, aIndex);
|
||||
} else {
|
||||
nsCOMPtr<nsISupports> data;
|
||||
formatitem.mData->GetAsISupports(getter_AddRefs(data));
|
||||
// Make sure the code that is calling us is same-origin with the data.
|
||||
nsCOMPtr<nsPIDOMEventTarget> pt = do_QueryInterface(data);
|
||||
if (pt) {
|
||||
nsresult rv = NS_OK;
|
||||
nsIScriptContext* c = pt->GetContextForEventHandlers(&rv);
|
||||
NS_ENSURE_TRUE(c && NS_SUCCEEDED(rv), NS_ERROR_DOM_SECURITY_ERR);
|
||||
nsIScriptObjectPrincipal* sp = c->GetObjectPrincipal();
|
||||
NS_ENSURE_TRUE(sp, NS_ERROR_DOM_SECURITY_ERR);
|
||||
nsIPrincipal* dataPrincipal = sp->GetPrincipal();
|
||||
NS_ENSURE_TRUE(dataPrincipal, NS_ERROR_DOM_SECURITY_ERR);
|
||||
NS_ENSURE_TRUE(principal || (principal = GetCurrentPrincipal()),
|
||||
NS_ERROR_DOM_SECURITY_ERR);
|
||||
PRBool equals = PR_FALSE;
|
||||
NS_ENSURE_TRUE(NS_SUCCEEDED(principal->Equals(dataPrincipal, &equals)) && equals,
|
||||
NS_ERROR_DOM_SECURITY_ERR);
|
||||
}
|
||||
}
|
||||
*aData = formatitem.mData;
|
||||
NS_IF_ADDREF(*aData);
|
||||
return NS_OK;
|
||||
|
@ -137,4 +137,23 @@ public:
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIRadioGroupContainer,
|
||||
NS_IRADIOGROUPCONTAINER_IID)
|
||||
|
||||
#define NS_IRADIOGROUPCONTAINER_MOZILLA_2_0_BRANCH_IID \
|
||||
{ 0xaa9ec446, 0xcdc7, 0x4030, \
|
||||
{ 0xab, 0x02, 0xda, 0x44, 0xee, 0xb1, 0x80, 0x0a } }
|
||||
|
||||
class nsIRadioGroupContainer_MOZILLA_2_0_BRANCH : public nsIRadioGroupContainer
|
||||
{
|
||||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IRADIOGROUPCONTAINER_MOZILLA_2_0_IID)
|
||||
|
||||
virtual PRUint32 GetRequiredRadioCount(const nsAString& aName) const = 0;
|
||||
virtual void RadioRequiredChanged(const nsAString& aName,
|
||||
nsIFormControl* aRadio) = 0;
|
||||
virtual bool GetValueMissingState(const nsAString& aName) const = 0;
|
||||
virtual void SetValueMissingState(const nsAString& aName, bool aValue) = 0;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIRadioGroupContainer_MOZILLA_2_0_BRANCH,
|
||||
NS_IRADIOGROUPCONTAINER_MOZILLA_2_0_BRANCH_IID)
|
||||
|
||||
#endif /* nsIRadioGroupContainer_h__ */
|
||||
|
@ -98,18 +98,6 @@ NS_GetRadioGetCheckedChangedVisitor(PRBool* aCheckedChanged,
|
||||
nsIFormControl* aExcludeElement,
|
||||
nsIRadioVisitor** aVisitor);
|
||||
|
||||
/**
|
||||
* This visitor will return (via aRequired) if an element of the group has the
|
||||
* required attribute set.
|
||||
*
|
||||
* @param aExcludeElement an element to exclude (for optimization purpose), can be null
|
||||
* @param aRequired whether there is a radio in the group with the required attribute [OUT]
|
||||
* @return the visitor
|
||||
*/
|
||||
nsIRadioVisitor*
|
||||
NS_GetRadioGroupRequiredVisitor(nsIFormControl* aExcludeElement,
|
||||
bool* aRequired);
|
||||
|
||||
/**
|
||||
* This visitor will update the validity states of all radio in the group and
|
||||
* call ContentStatesChanged if needed.
|
||||
|
@ -295,6 +295,10 @@ nsHTMLFormElement::Init()
|
||||
|
||||
NS_ENSURE_TRUE(mSelectedRadioButtons.Init(4),
|
||||
NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_ENSURE_TRUE(mRequiredRadioButtonCounts.Init(4),
|
||||
NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_ENSURE_TRUE(mValueMissingRadioGroups.Init(4),
|
||||
NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -329,12 +333,13 @@ DOMCI_NODE_DATA(HTMLFormElement, nsHTMLFormElement)
|
||||
|
||||
// QueryInterface implementation for nsHTMLFormElement
|
||||
NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsHTMLFormElement)
|
||||
NS_HTML_CONTENT_INTERFACE_TABLE5(nsHTMLFormElement,
|
||||
NS_HTML_CONTENT_INTERFACE_TABLE6(nsHTMLFormElement,
|
||||
nsIDOMHTMLFormElement,
|
||||
nsIDOMNSHTMLFormElement,
|
||||
nsIForm,
|
||||
nsIWebProgressListener,
|
||||
nsIRadioGroupContainer)
|
||||
nsIRadioGroupContainer,
|
||||
nsIRadioGroupContainer_MOZILLA_2_0_BRANCH)
|
||||
NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLFormElement,
|
||||
nsGenericHTMLElement)
|
||||
NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLFormElement)
|
||||
@ -1175,16 +1180,8 @@ nsHTMLFormElement::AddElement(nsGenericHTMLFormElement* aChild,
|
||||
#ifdef DEBUG
|
||||
AssertDocumentOrder(controlList, this);
|
||||
#endif
|
||||
|
||||
//
|
||||
// Notify the radio button it's been added to a group
|
||||
//
|
||||
|
||||
PRInt32 type = aChild->GetType();
|
||||
if (type == NS_FORM_INPUT_RADIO) {
|
||||
nsRefPtr<nsHTMLInputElement> radio =
|
||||
static_cast<nsHTMLInputElement*>(aChild);
|
||||
radio->AddedToRadioGroup();
|
||||
}
|
||||
|
||||
//
|
||||
// If it is a password control, and the password manager has not yet been
|
||||
@ -1262,6 +1259,15 @@ nsHTMLFormElement::AddElement(nsGenericHTMLFormElement* aChild,
|
||||
}
|
||||
}
|
||||
|
||||
// Notify the radio button it's been added to a group
|
||||
// This has to be done _after_ UpdateValidity() call to prevent the element
|
||||
// being count twice.
|
||||
if (type == NS_FORM_INPUT_RADIO) {
|
||||
nsRefPtr<nsHTMLInputElement> radio =
|
||||
static_cast<nsHTMLInputElement*>(aChild);
|
||||
radio->AddedToRadioGroup();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -2121,6 +2127,14 @@ NS_IMETHODIMP
|
||||
nsHTMLFormElement::AddToRadioGroup(const nsAString& aName,
|
||||
nsIFormControl* aRadio)
|
||||
{
|
||||
nsCOMPtr<nsIContent> element = do_QueryInterface(aRadio);
|
||||
NS_ASSERTION(element, "radio controls have to be content elements!");
|
||||
|
||||
if (element->HasAttr(kNameSpaceID_None, nsGkAtoms::required)) {
|
||||
mRequiredRadioButtonCounts.Put(aName,
|
||||
mRequiredRadioButtonCounts.Get(aName)+1);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -2128,9 +2142,65 @@ NS_IMETHODIMP
|
||||
nsHTMLFormElement::RemoveFromRadioGroup(const nsAString& aName,
|
||||
nsIFormControl* aRadio)
|
||||
{
|
||||
nsCOMPtr<nsIContent> element = do_QueryInterface(aRadio);
|
||||
NS_ASSERTION(element, "radio controls have to be content elements!");
|
||||
|
||||
if (element->HasAttr(kNameSpaceID_None, nsGkAtoms::required)) {
|
||||
PRUint32 requiredNb = mRequiredRadioButtonCounts.Get(aName);
|
||||
NS_ASSERTION(requiredNb >= 1,
|
||||
"At least one radio button has to be required!");
|
||||
|
||||
if (requiredNb == 1) {
|
||||
mRequiredRadioButtonCounts.Remove(aName);
|
||||
} else {
|
||||
mRequiredRadioButtonCounts.Put(aName, requiredNb-1);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRUint32
|
||||
nsHTMLFormElement::GetRequiredRadioCount(const nsAString& aName) const
|
||||
{
|
||||
return mRequiredRadioButtonCounts.Get(aName);
|
||||
}
|
||||
|
||||
void
|
||||
nsHTMLFormElement::RadioRequiredChanged(const nsAString& aName,
|
||||
nsIFormControl* aRadio)
|
||||
{
|
||||
nsCOMPtr<nsIContent> element = do_QueryInterface(aRadio);
|
||||
NS_ASSERTION(element, "radio controls have to be content elements!");
|
||||
|
||||
if (element->HasAttr(kNameSpaceID_None, nsGkAtoms::required)) {
|
||||
mRequiredRadioButtonCounts.Put(aName,
|
||||
mRequiredRadioButtonCounts.Get(aName)+1);
|
||||
} else {
|
||||
PRUint32 requiredNb = mRequiredRadioButtonCounts.Get(aName);
|
||||
NS_ASSERTION(requiredNb >= 1,
|
||||
"At least one radio button has to be required!");
|
||||
if (requiredNb == 1) {
|
||||
mRequiredRadioButtonCounts.Remove(aName);
|
||||
} else {
|
||||
mRequiredRadioButtonCounts.Put(aName, requiredNb-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
nsHTMLFormElement::GetValueMissingState(const nsAString& aName) const
|
||||
{
|
||||
return mValueMissingRadioGroups.Get(aName);
|
||||
}
|
||||
|
||||
void
|
||||
nsHTMLFormElement::SetValueMissingState(const nsAString& aName, bool aValue)
|
||||
{
|
||||
mValueMissingRadioGroups.Put(aName, aValue);
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// nsFormControlList implementation, this could go away if there were
|
||||
// a lightweight collection implementation somewhere
|
||||
|
@ -53,6 +53,7 @@
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsInterfaceHashtable.h"
|
||||
#include "nsDataHashtable.h"
|
||||
|
||||
class nsFormControlList;
|
||||
class nsIMutableArray;
|
||||
@ -95,7 +96,7 @@ class nsHTMLFormElement : public nsGenericHTMLElement,
|
||||
public nsIDOMNSHTMLFormElement,
|
||||
public nsIWebProgressListener,
|
||||
public nsIForm,
|
||||
public nsIRadioGroupContainer
|
||||
public nsIRadioGroupContainer_MOZILLA_2_0_BRANCH
|
||||
{
|
||||
public:
|
||||
nsHTMLFormElement(already_AddRefed<nsINodeInfo> aNodeInfo);
|
||||
@ -149,6 +150,11 @@ public:
|
||||
nsIFormControl* aRadio);
|
||||
NS_IMETHOD RemoveFromRadioGroup(const nsAString& aName,
|
||||
nsIFormControl* aRadio);
|
||||
virtual PRUint32 GetRequiredRadioCount(const nsAString& aName) const;
|
||||
virtual void RadioRequiredChanged(const nsAString& aName,
|
||||
nsIFormControl* aRadio);
|
||||
virtual bool GetValueMissingState(const nsAString& aName) const;
|
||||
virtual void SetValueMissingState(const nsAString& aName, bool aValue);
|
||||
|
||||
// nsIContent
|
||||
virtual PRBool ParseAttribute(PRInt32 aNamespaceID,
|
||||
@ -412,6 +418,10 @@ protected:
|
||||
nsRefPtr<nsFormControlList> mControls;
|
||||
/** The currently selected radio button of each group */
|
||||
nsInterfaceHashtable<nsStringCaseInsensitiveHashKey,nsIDOMHTMLInputElement> mSelectedRadioButtons;
|
||||
/** The number of required radio button of each group */
|
||||
nsDataHashtable<nsStringCaseInsensitiveHashKey,PRUint32> mRequiredRadioButtonCounts;
|
||||
/** The value missing state of each group */
|
||||
nsDataHashtable<nsStringCaseInsensitiveHashKey,bool> mValueMissingRadioGroups;
|
||||
/** Whether we are currently processing a submit event or not */
|
||||
PRPackedBool mGeneratingSubmit;
|
||||
/** Whether we are currently processing a reset event or not */
|
||||
|
@ -814,6 +814,9 @@ nsHTMLInputElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||
mType == NS_FORM_INPUT_RADIO &&
|
||||
(mForm || !(GET_BOOLBIT(mBitField, BF_PARSER_CREATING)))) {
|
||||
AddedToRadioGroup();
|
||||
UpdateValueMissingValidityStateForRadio(false);
|
||||
states |= NS_EVENT_STATE_VALID | NS_EVENT_STATE_INVALID |
|
||||
NS_EVENT_STATE_REQUIRED | NS_EVENT_STATE_OPTIONAL;
|
||||
}
|
||||
|
||||
// If @value is changed and BF_VALUE_CHANGED is false, @value is the value
|
||||
@ -906,6 +909,17 @@ nsHTMLInputElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||
NS_EVENT_STATE_MOZ_SUBMITINVALID;
|
||||
}
|
||||
|
||||
if (mType == NS_FORM_INPUT_RADIO && aName == nsGkAtoms::required) {
|
||||
nsCOMPtr<nsIRadioGroupContainer> c = GetRadioGroupContainer();
|
||||
nsCOMPtr<nsIRadioGroupContainer_MOZILLA_2_0_BRANCH> container =
|
||||
do_QueryInterface(c);
|
||||
nsAutoString name;
|
||||
|
||||
if (container && GetNameIfExists(name)) {
|
||||
container->RadioRequiredChanged(name, this);
|
||||
}
|
||||
}
|
||||
|
||||
if (aName == nsGkAtoms::required || aName == nsGkAtoms::disabled ||
|
||||
aName == nsGkAtoms::readonly) {
|
||||
UpdateValueMissingValidityState();
|
||||
@ -3483,6 +3497,13 @@ nsHTMLInputElement::AddedToRadioGroup()
|
||||
nsAutoString name;
|
||||
if (GetNameIfExists(name)) {
|
||||
container->AddToRadioGroup(name, static_cast<nsIFormControl*>(this));
|
||||
|
||||
// We initialize the validity of the element to the validity of the group
|
||||
// because we assume UpdateValueMissingState() will be called after.
|
||||
nsCOMPtr<nsIRadioGroupContainer_MOZILLA_2_0_BRANCH> container2 =
|
||||
do_QueryInterface(container);
|
||||
SetValidityState(VALIDITY_STATE_VALUE_MISSING,
|
||||
container2->GetValueMissingState(name));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3903,6 +3924,7 @@ nsHTMLInputElement::UpdateValueMissingValidityStateForRadio(bool aIgnoreSelf)
|
||||
{
|
||||
PRBool notify = !GET_BOOLBIT(mBitField, BF_PARSER_CREATING);
|
||||
nsCOMPtr<nsIDOMHTMLInputElement> selection = GetSelectedRadioButton();
|
||||
|
||||
// If there is no selection, that might mean the radio is not in a group.
|
||||
// In that case, we can look for the checked state of the radio.
|
||||
bool selected = selection ? true
|
||||
@ -3911,21 +3933,36 @@ nsHTMLInputElement::UpdateValueMissingValidityStateForRadio(bool aIgnoreSelf)
|
||||
: HasAttr(kNameSpaceID_None, nsGkAtoms::required);
|
||||
bool valueMissing = false;
|
||||
|
||||
// If the current radio is required, don't check the entire group.
|
||||
if (!required) {
|
||||
nsCOMPtr<nsIRadioVisitor> visitor =
|
||||
NS_GetRadioGroupRequiredVisitor(this, &required);
|
||||
VisitGroup(visitor, notify);
|
||||
nsCOMPtr<nsIRadioGroupContainer> c = GetRadioGroupContainer();
|
||||
nsCOMPtr<nsIRadioGroupContainer_MOZILLA_2_0_BRANCH> container =
|
||||
do_QueryInterface(c);
|
||||
nsAutoString name;
|
||||
GetNameIfExists(name);
|
||||
|
||||
// If the current radio is required and not ignored, we can assume the entire
|
||||
// group is required.
|
||||
if (!required && container && !name.IsEmpty()) {
|
||||
required = (aIgnoreSelf && HasAttr(kNameSpaceID_None, nsGkAtoms::required))
|
||||
? container->GetRequiredRadioCount(name) - 1
|
||||
: container->GetRequiredRadioCount(name);
|
||||
}
|
||||
|
||||
valueMissing = required && !selected;
|
||||
|
||||
SetValidityState(VALIDITY_STATE_VALUE_MISSING, valueMissing);
|
||||
if (container && !name.IsEmpty()) {
|
||||
if (container->GetValueMissingState(name) != valueMissing) {
|
||||
container->SetValueMissingState(name, valueMissing);
|
||||
|
||||
nsCOMPtr<nsIRadioVisitor> visitor =
|
||||
NS_SetRadioValueMissingState(this, GetCurrentDoc(), valueMissing,
|
||||
notify);
|
||||
VisitGroup(visitor, notify);
|
||||
SetValidityState(VALIDITY_STATE_VALUE_MISSING, valueMissing);
|
||||
|
||||
nsCOMPtr<nsIRadioVisitor> visitor =
|
||||
NS_SetRadioValueMissingState(this, GetCurrentDoc(), valueMissing,
|
||||
notify);
|
||||
VisitGroup(visitor, notify);
|
||||
}
|
||||
} else {
|
||||
SetValidityState(VALIDITY_STATE_VALUE_MISSING, valueMissing);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -4263,34 +4300,6 @@ protected:
|
||||
nsIFormControl* mExcludeElement;
|
||||
};
|
||||
|
||||
class nsRadioGroupRequiredVisitor : public nsRadioVisitor {
|
||||
public:
|
||||
nsRadioGroupRequiredVisitor(nsIFormControl* aExcludeElement, bool* aRequired)
|
||||
: mRequired(aRequired)
|
||||
, mExcludeElement(aExcludeElement)
|
||||
{ }
|
||||
|
||||
NS_IMETHOD Visit(nsIFormControl* aRadio, PRBool* aStop)
|
||||
{
|
||||
if (aRadio == mExcludeElement) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
*mRequired = static_cast<nsHTMLInputElement*>(aRadio)
|
||||
->HasAttr(kNameSpaceID_None, nsGkAtoms::required);
|
||||
|
||||
if (*mRequired) {
|
||||
*aStop = PR_TRUE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool* mRequired;
|
||||
nsIFormControl* mExcludeElement;
|
||||
};
|
||||
|
||||
class nsRadioSetValueMissingState : public nsRadioVisitor {
|
||||
public:
|
||||
nsRadioSetValueMissingState(nsIFormControl* aExcludeElement,
|
||||
@ -4411,13 +4420,6 @@ NS_GetRadioGetCheckedChangedVisitor(PRBool* aCheckedChanged,
|
||||
* visitor classes are defined after most of nsHTMLInputElement code.
|
||||
* See bug 586298
|
||||
*/
|
||||
nsIRadioVisitor*
|
||||
NS_GetRadioGroupRequiredVisitor(nsIFormControl* aExcludeElement,
|
||||
bool* aRequired)
|
||||
{
|
||||
return new nsRadioGroupRequiredVisitor(aExcludeElement, aRequired);
|
||||
}
|
||||
|
||||
nsIRadioVisitor*
|
||||
NS_SetRadioValueMissingState(nsIFormControl* aExcludeElement,
|
||||
nsIDocument* aDocument,
|
||||
|
@ -118,8 +118,7 @@ function checkRadios(r1, r2, r3, form)
|
||||
checkPseudoClasses(r2, true, true, false);
|
||||
checkPseudoClasses(r3, false, false, true);
|
||||
|
||||
// Removing the radio with the required attribute should make the entire
|
||||
// group invalid.
|
||||
// Removing the radio with the required attribute should make the group valid.
|
||||
r1.setCustomValidity('');
|
||||
r2.setCustomValidity('');
|
||||
r1.required = false;
|
||||
@ -136,6 +135,55 @@ function checkRadios(r1, r2, r3, form)
|
||||
p.appendChild(r2);
|
||||
checkPseudoClasses(r1, false, false, true);
|
||||
checkPseudoClasses(r2, false, false, true);
|
||||
|
||||
// Adding a radio element to an invalid group should make it invalid.
|
||||
p.removeChild(r1);
|
||||
checkPseudoClasses(r1, true, true, false);
|
||||
checkPseudoClasses(r2, false, false, true);
|
||||
|
||||
p.appendChild(r1);
|
||||
checkPseudoClasses(r1, false, false, true);
|
||||
checkPseudoClasses(r2, false, false, true);
|
||||
|
||||
// Adding a checked radio element to an invalid group should make it valid.
|
||||
p.removeChild(r1);
|
||||
checkPseudoClasses(r1, true, true, false);
|
||||
checkPseudoClasses(r2, false, false, true);
|
||||
|
||||
r1.checked = true;
|
||||
p.appendChild(r1);
|
||||
checkPseudoClasses(r1, true, true, false);
|
||||
checkPseudoClasses(r2, true, true, false);
|
||||
r1.checked = false;
|
||||
|
||||
// Adding an invalid radio element by changing the name attribute.
|
||||
r2.name = 'c';
|
||||
checkPseudoClasses(r1, true, true, false);
|
||||
checkPseudoClasses(r2, false, false, true);
|
||||
|
||||
r2.name = 'a';
|
||||
checkPseudoClasses(r1, false, false, true);
|
||||
checkPseudoClasses(r2, false, false, true);
|
||||
|
||||
// Adding an element to an invalid radio group by changing the name attribute.
|
||||
r1.name = 'c';
|
||||
checkPseudoClasses(r1, true, true, false);
|
||||
checkPseudoClasses(r2, false, false, true);
|
||||
|
||||
r1.name = 'a';
|
||||
checkPseudoClasses(r1, false, false, true);
|
||||
checkPseudoClasses(r2, false, false, true);
|
||||
|
||||
// Adding a checked element to an invalid radio group with the name attribute.
|
||||
r1.name = 'c';
|
||||
checkPseudoClasses(r1, true, true, false);
|
||||
checkPseudoClasses(r2, false, false, true);
|
||||
|
||||
r1.checked = true;
|
||||
r1.name = 'a';
|
||||
checkPseudoClasses(r1, true, true, false);
|
||||
checkPseudoClasses(r2, true, true, false);
|
||||
r1.checked = false;
|
||||
}
|
||||
|
||||
var r1 = document.getElementsByTagName('input')[0];
|
||||
|
@ -645,13 +645,7 @@ nsSHEntry::AddChild(nsISHEntry * aChild, PRInt32 aOffset)
|
||||
}
|
||||
#endif
|
||||
|
||||
// InsertObjectAt allows only appending one object.
|
||||
// If aOffset is larger than Count(), we must first manually
|
||||
// set the capacity.
|
||||
if (aOffset > mChildren.Count()) {
|
||||
mChildren.SetCount(aOffset);
|
||||
}
|
||||
if (!mChildren.InsertObjectAt(aChild, aOffset)) {
|
||||
if (!mChildren.ReplaceObjectAt(aChild, aOffset)) {
|
||||
NS_WARNING("Adding a child failed!");
|
||||
aChild->SetParent(nsnull);
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -8124,6 +8124,62 @@ nsDOMTokenListSH::GetStringAt(nsISupports *aNative, PRInt32 aIndex,
|
||||
|
||||
// Named Array helper
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNamedArraySH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, jsid id, PRUint32 flags,
|
||||
JSObject **objp, PRBool *_retval)
|
||||
{
|
||||
if ((!(JSRESOLVE_ASSIGNING & flags)) && JSID_IS_STRING(id) &&
|
||||
!ObjectIsNativeWrapper(cx, obj)) {
|
||||
|
||||
{
|
||||
JSObject *realObj;
|
||||
|
||||
if (wrapper) {
|
||||
wrapper->GetJSObject(&realObj);
|
||||
} else {
|
||||
realObj = obj;
|
||||
}
|
||||
|
||||
JSAutoEnterCompartment ac;
|
||||
|
||||
if (!ac.enter(cx, realObj)) {
|
||||
*_retval = PR_FALSE;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
JSObject *proto = ::JS_GetPrototype(cx, realObj);
|
||||
JSBool hasProp;
|
||||
|
||||
if (proto && ::JS_HasPropertyById(cx, proto, id, &hasProp) && hasProp) {
|
||||
// We found the property we're resolving on the prototype,
|
||||
// nothing left to do here then.
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure rv == NS_OK here, so GetNamedItem implementations
|
||||
// that never fail don't have to set rv.
|
||||
nsresult rv = NS_OK;
|
||||
nsWrapperCache *cache;
|
||||
|
||||
nsISupports* item = GetNamedItem(GetNative(wrapper, obj),
|
||||
nsDependentJSString(id), &cache, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (item) {
|
||||
*_retval = ::JS_DefinePropertyById(cx, obj, id, JSVAL_VOID, nsnull,
|
||||
nsnull, JSPROP_ENUMERATE | JSPROP_SHARED);
|
||||
|
||||
*objp = obj;
|
||||
|
||||
return *_retval ? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return nsArraySH::NewResolve(wrapper, cx, obj, id, flags, objp, _retval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNamedArraySH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, jsid id, jsval *vp,
|
||||
@ -9347,6 +9403,31 @@ nsHTMLFormElementSH::NewEnumerate(nsIXPConnectWrappedNative *wrapper,
|
||||
|
||||
// HTMLSelectElement helper
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLSelectElementSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, jsid id, PRUint32 flags,
|
||||
JSObject **objp, PRBool *_retval)
|
||||
{
|
||||
PRInt32 n = GetArrayIndexFromId(cx, id);
|
||||
if (n >= 0) {
|
||||
nsHTMLSelectElement *s =
|
||||
nsHTMLSelectElement::FromSupports(GetNative(wrapper, obj));
|
||||
|
||||
nsHTMLOptionCollection *options = s->GetOptions();
|
||||
if (options) {
|
||||
nsresult rv;
|
||||
nsISupports *node = options->GetNodeAt(n, &rv);
|
||||
if (node) {
|
||||
*objp = obj;
|
||||
*_retval = JS_DefineElement(cx, obj, n, JSVAL_VOID, nsnull, nsnull,
|
||||
JSPROP_ENUMERATE | JSPROP_SHARED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLSelectElementSH::GetProperty(nsIXPConnectWrappedNative *wrapper,
|
||||
JSContext *cx, JSObject *obj, jsid id,
|
||||
|
@ -807,6 +807,10 @@ protected:
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHOD NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, jsid id, PRUint32 flags,
|
||||
JSObject **objp, PRBool *_retval);
|
||||
|
||||
virtual nsISupports* GetNamedItem(nsISupports *aNative,
|
||||
const nsAString& aName,
|
||||
nsWrapperCache **cache,
|
||||
@ -1075,6 +1079,9 @@ protected:
|
||||
}
|
||||
|
||||
public:
|
||||
NS_IMETHOD NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, jsid id, PRUint32 flags,
|
||||
JSObject **objp, PRBool *_retval);
|
||||
NS_IMETHOD GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, jsid id, jsval *vp,
|
||||
PRBool *_retval);
|
||||
|
@ -148,6 +148,8 @@ static PRLogModuleInfo* gJSDiagnostics;
|
||||
static nsITimer *sGCTimer;
|
||||
static nsITimer *sCCTimer;
|
||||
|
||||
static bool sGCHasRun;
|
||||
|
||||
// The number of currently pending document loads. This count isn't
|
||||
// guaranteed to always reflect reality and can't easily as we don't
|
||||
// have an easy place to know when a load ends or is interrupted in
|
||||
@ -3392,8 +3394,8 @@ nsJSContext::MaybePokeCC()
|
||||
void
|
||||
nsJSContext::PokeCC()
|
||||
{
|
||||
if (sCCTimer) {
|
||||
// There's already a timer for GC'ing, just return
|
||||
if (sCCTimer || !sGCHasRun) {
|
||||
// There's already a timer for GC'ing, or GC hasn't run yet, just return.
|
||||
return;
|
||||
}
|
||||
|
||||
@ -3477,9 +3479,16 @@ DOMGCCallback(JSContext *cx, JSGCStatus status)
|
||||
} else {
|
||||
// If this was a full GC, poke the CC to run soon.
|
||||
if (!cx->runtime->gcTriggerCompartment) {
|
||||
sGCHasRun = true;
|
||||
nsJSContext::PokeCC();
|
||||
}
|
||||
}
|
||||
|
||||
// If we didn't end up scheduling a GC, and there are unused
|
||||
// chunks waiting to expire, make sure we will GC again soon.
|
||||
if (!sGCTimer && JS_GetGCParameter(cx->runtime, JSGC_UNUSED_CHUNKS) > 0) {
|
||||
nsJSContext::PokeGC();
|
||||
}
|
||||
}
|
||||
|
||||
JSBool result = gOldJSGCCallback ? gOldJSGCCallback(cx, status) : JS_TRUE;
|
||||
@ -3583,6 +3592,7 @@ nsJSRuntime::Startup()
|
||||
{
|
||||
// initialize all our statics, so that we can restart XPCOM
|
||||
sGCTimer = sCCTimer = nsnull;
|
||||
sGCHasRun = false;
|
||||
sPendingLoadCount = 0;
|
||||
sLoadingInProgress = PR_FALSE;
|
||||
sPostGCEventsToConsole = PR_FALSE;
|
||||
|
@ -88,6 +88,10 @@
|
||||
#include "mozilla/dom/StorageParent.h"
|
||||
#include "nsAccelerometer.h"
|
||||
|
||||
#ifdef ANDROID
|
||||
#include "gfxAndroidPlatform.h"
|
||||
#endif
|
||||
|
||||
using namespace mozilla::ipc;
|
||||
using namespace mozilla::net;
|
||||
using namespace mozilla::places;
|
||||
@ -321,6 +325,16 @@ ContentParent::RecvReadPrefsArray(InfallibleTArray<PrefTuple> *prefs)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::RecvReadFontList(InfallibleTArray<FontListEntry>* retValue)
|
||||
{
|
||||
#ifdef ANDROID
|
||||
gfxAndroidPlatform::GetPlatform()->GetFontList(retValue);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ContentParent::EnsurePrefService()
|
||||
{
|
||||
|
@ -143,6 +143,7 @@ private:
|
||||
virtual bool DeallocPStorage(PStorageParent* aActor);
|
||||
|
||||
virtual bool RecvReadPrefsArray(InfallibleTArray<PrefTuple> *retValue);
|
||||
virtual bool RecvReadFontList(InfallibleTArray<FontListEntry>* retValue);
|
||||
|
||||
void EnsurePrefService();
|
||||
|
||||
|
@ -81,6 +81,12 @@ union StorageConstructData
|
||||
StorageClone;
|
||||
};
|
||||
|
||||
struct FontListEntry {
|
||||
nsCString familyName;
|
||||
nsCString filepath;
|
||||
PRUint32 index;
|
||||
};
|
||||
|
||||
rpc protocol PContent
|
||||
{
|
||||
manages PAudio;
|
||||
@ -144,6 +150,8 @@ parent:
|
||||
// PrefService message
|
||||
sync ReadPrefsArray() returns (PrefTuple[] retValue);
|
||||
|
||||
sync ReadFontList() returns (FontListEntry[] retValue);
|
||||
|
||||
sync SyncMessage(nsString aMessage, nsString aJSON)
|
||||
returns (nsString[] retval);
|
||||
|
||||
|
@ -642,6 +642,25 @@ PluginInstanceParent::GetImage(ImageContainer* aContainer, Image** aImage)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
PluginInstanceParent::GetImageSize(nsIntSize* aSize)
|
||||
{
|
||||
if (mFrontSurface) {
|
||||
gfxIntSize size = mFrontSurface->GetSize();
|
||||
*aSize = nsIntSize(size.width, size.height);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
if (mIOSurface) {
|
||||
*aSize = nsIntSize(mIOSurface->GetWidth(), mIOSurface->GetHeight());
|
||||
return NS_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
nsresult
|
||||
PluginInstanceParent::IsRemoteDrawingCoreAnimation(PRBool *aDrawing)
|
||||
|
@ -279,6 +279,7 @@ public:
|
||||
nsresult AsyncSetWindow(NPWindow* window);
|
||||
nsresult GetSurface(gfxASurface** aSurface);
|
||||
nsresult GetImage(mozilla::layers::ImageContainer* aContainer, mozilla::layers::Image** aImage);
|
||||
nsresult GetImageSize(nsIntSize* aSize);
|
||||
#ifdef XP_MACOSX
|
||||
nsresult IsRemoteDrawingCoreAnimation(PRBool *aDrawing);
|
||||
#endif
|
||||
|
@ -50,6 +50,7 @@ class gfxASurface;
|
||||
class gfxContext;
|
||||
class nsCString;
|
||||
struct nsIntRect;
|
||||
struct nsIntSize;
|
||||
class nsNPAPIPlugin;
|
||||
|
||||
namespace mozilla {
|
||||
@ -100,6 +101,7 @@ public:
|
||||
virtual nsresult AsyncSetWindow(NPP instance, NPWindow* window) = 0;
|
||||
virtual nsresult GetSurface(NPP instance, gfxASurface** aSurface) = 0;
|
||||
virtual nsresult GetImage(NPP instance, ImageContainer* aContainer, Image** aImage) = 0;
|
||||
virtual nsresult GetImageSize(NPP instance, nsIntSize* aSize) = 0;
|
||||
virtual bool UseAsyncPainting() = 0;
|
||||
#if defined(XP_MACOSX)
|
||||
virtual nsresult IsRemoteDrawingCoreAnimation(NPP instance, PRBool *aDrawing) = 0;
|
||||
|
@ -691,6 +691,14 @@ PluginModuleParent::GetImage(NPP instance,
|
||||
return !i ? NS_ERROR_FAILURE : i->GetImage(aContainer, aImage);
|
||||
}
|
||||
|
||||
nsresult
|
||||
PluginModuleParent::GetImageSize(NPP instance,
|
||||
nsIntSize* aSize)
|
||||
{
|
||||
PluginInstanceParent* i = InstCast(instance);
|
||||
return !i ? NS_ERROR_FAILURE : i->GetImageSize(aSize);
|
||||
}
|
||||
|
||||
nsresult
|
||||
PluginModuleParent::SetBackgroundUnknown(NPP instance)
|
||||
{
|
||||
|
@ -232,6 +232,7 @@ private:
|
||||
virtual nsresult AsyncSetWindow(NPP instance, NPWindow* window);
|
||||
virtual nsresult GetSurface(NPP instance, gfxASurface** aSurface);
|
||||
virtual nsresult GetImage(NPP instance, mozilla::layers::ImageContainer* aContainer, mozilla::layers::Image** aImage);
|
||||
virtual nsresult GetImageSize(NPP instance, nsIntSize* aSize);
|
||||
NS_OVERRIDE virtual bool UseAsyncPainting() { return true; }
|
||||
NS_OVERRIDE
|
||||
virtual nsresult SetBackgroundUnknown(NPP instance);
|
||||
|
@ -62,23 +62,19 @@ DIRS = android
|
||||
endif
|
||||
|
||||
CPPSRCS = \
|
||||
nsAccelerometer.cpp \
|
||||
$(NULL)
|
||||
nsAccelerometer.cpp \
|
||||
$(NULL)
|
||||
|
||||
# On Systems that have built-in geolocation providers,
|
||||
# we really do not need these.
|
||||
ifneq (Android,$(OS_TARGET))
|
||||
EXTRA_COMPONENTS = \
|
||||
NetworkGeolocationProvider.js \
|
||||
NetworkGeolocationProvider.manifest \
|
||||
GPSDGeolocationProvider.js \
|
||||
GPSDGeolocationProvider.manifest \
|
||||
$(NULL)
|
||||
endif
|
||||
NetworkGeolocationProvider.js \
|
||||
NetworkGeolocationProvider.manifest \
|
||||
GPSDGeolocationProvider.js \
|
||||
GPSDGeolocationProvider.manifest \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS = \
|
||||
nsAccelerometer.h \
|
||||
$(NULL)
|
||||
nsAccelerometer.h \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
|
||||
|
@ -135,6 +135,7 @@ _TEST_FILES = \
|
||||
test_bug617296.html \
|
||||
test_bug620947.html \
|
||||
test_bug622361.html \
|
||||
test_bug633133.html \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
|
46
dom/tests/mochitest/bugs/test_bug633133.html
Normal file
46
dom/tests/mochitest/bugs/test_bug633133.html
Normal file
@ -0,0 +1,46 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=633133
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 633133</title>
|
||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=633133">Mozilla Bug 633133</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
<div id='foo'></div>
|
||||
<div name='bar'></div>
|
||||
<select id="select">
|
||||
<option>option1</option>
|
||||
<option>option2</option>
|
||||
</select>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 633133 **/
|
||||
|
||||
var divCollection = document.getElementsByTagName('div');
|
||||
|
||||
ok("foo" in divCollection, "'foo' should be in the div collection");
|
||||
ok("bar" in divCollection, "'bar' should be in the div collection");
|
||||
ok(!("" in divCollection), "empty string shouldn't be in the div collection");
|
||||
ok(!("foobar" in divCollection), "'foobar' shouldn't be in the div collection");
|
||||
|
||||
var select = $('select');
|
||||
is(select[0].text, "option1", "select elements work");
|
||||
Math.sin();
|
||||
ok(1 in select, "in works");
|
||||
is(select[1].text, "option2", "can get it too");
|
||||
ok(!(2 in select), "in works for elements out of range");
|
||||
is(select[2], undefined, "can get them too and they're undefined");
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
18
editor/libeditor/base/crashtests/636074-1.html
Normal file
18
editor/libeditor/base/crashtests/636074-1.html
Normal file
@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<script>
|
||||
|
||||
function boom()
|
||||
{
|
||||
document.getElementById("i").focus();
|
||||
document.documentElement.contentEditable = "true";
|
||||
document.execCommand("inserthtml", false, "<table>");
|
||||
document.execCommand("indent", false, null);
|
||||
document.execCommand("delete", false, null);
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body onload="boom();"><input id="i"></body>
|
||||
</html>
|
@ -7,3 +7,4 @@ load 430624-1.html
|
||||
load 459613.html
|
||||
load 475132-1.xhtml
|
||||
load 633709.xhtml
|
||||
asserts(6) load 636074-1.html # Bug 439258, charged to the wrong test due to bug 635550
|
||||
|
@ -2661,7 +2661,7 @@ NS_IMETHODIMP nsEditor::CreateTxnForInsertText(const nsAString & aStringToInsert
|
||||
rv = txn->Init(aTextNode, aOffset, aStringToInsert, this);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
txn.swap(*aTxn);
|
||||
txn.forget(aTxn);
|
||||
}
|
||||
|
||||
return rv;
|
||||
@ -2705,7 +2705,7 @@ NS_IMETHODIMP nsEditor::CreateTxnForDeleteText(nsIDOMCharacterData *aElement,
|
||||
nsresult rv = txn->Init(this, aElement, aOffset, aLength, &mRangeUpdater);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
txn.swap(*aTxn);
|
||||
txn.forget(aTxn);
|
||||
}
|
||||
|
||||
return rv;
|
||||
@ -2725,7 +2725,7 @@ NS_IMETHODIMP nsEditor::CreateTxnForSplitNode(nsIDOMNode *aNode,
|
||||
nsresult rv = txn->Init(this, aNode, aOffset);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
txn.swap(*aTxn);
|
||||
txn.forget(aTxn);
|
||||
}
|
||||
|
||||
return rv;
|
||||
@ -2742,7 +2742,7 @@ NS_IMETHODIMP nsEditor::CreateTxnForJoinNode(nsIDOMNode *aLeftNode,
|
||||
nsresult rv = txn->Init(this, aLeftNode, aRightNode);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
txn.swap(*aTxn);
|
||||
txn.forget(aTxn);
|
||||
}
|
||||
|
||||
return rv;
|
||||
@ -4532,7 +4532,7 @@ nsEditor::CreateTxnForSetAttribute(nsIDOMElement *aElement,
|
||||
nsresult rv = txn->Init(this, aElement, aAttribute, aValue, PR_FALSE);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
txn.swap(*aTxn);
|
||||
txn.forget(aTxn);
|
||||
}
|
||||
|
||||
return rv;
|
||||
@ -4551,7 +4551,7 @@ nsEditor::CreateTxnForRemoveAttribute(nsIDOMElement *aElement,
|
||||
nsresult rv = txn->Init(this, aElement, aAttribute, EmptyString(), PR_TRUE);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
txn.swap(*aTxn);
|
||||
txn.forget(aTxn);
|
||||
}
|
||||
|
||||
return rv;
|
||||
@ -4570,7 +4570,7 @@ NS_IMETHODIMP nsEditor::CreateTxnForCreateElement(const nsAString& aTag,
|
||||
nsresult rv = txn->Init(this, aTag, aParent, aPosition);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
txn.swap(*aTxn);
|
||||
txn.forget(aTxn);
|
||||
}
|
||||
|
||||
return rv;
|
||||
@ -4589,7 +4589,7 @@ NS_IMETHODIMP nsEditor::CreateTxnForInsertElement(nsIDOMNode * aNode,
|
||||
nsresult rv = txn->Init(aNode, aParent, aPosition, this);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
txn.swap(*aTxn);
|
||||
txn.forget(aTxn);
|
||||
}
|
||||
|
||||
return rv;
|
||||
@ -4605,7 +4605,7 @@ NS_IMETHODIMP nsEditor::CreateTxnForDeleteElement(nsIDOMNode * aElement,
|
||||
nsresult rv = txn->Init(this, aElement, &mRangeUpdater);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
txn.swap(*aTxn);
|
||||
txn.forget(aTxn);
|
||||
}
|
||||
|
||||
return rv;
|
||||
@ -4623,7 +4623,7 @@ nsEditor::CreateTxnForIMEText(const nsAString& aStringToInsert,
|
||||
mIMETextRangeList, aStringToInsert, mSelConWeak);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
txn.swap(*aTxn);
|
||||
txn.forget(aTxn);
|
||||
}
|
||||
|
||||
return rv;
|
||||
@ -4638,7 +4638,7 @@ nsEditor::CreateTxnForAddStyleSheet(nsCSSStyleSheet* aSheet, AddStyleSheetTxn* *
|
||||
nsresult rv = txn->Init(this, aSheet);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
txn.swap(*aTxn);
|
||||
txn.forget(aTxn);
|
||||
}
|
||||
|
||||
return rv;
|
||||
@ -4654,7 +4654,7 @@ nsEditor::CreateTxnForRemoveStyleSheet(nsCSSStyleSheet* aSheet, RemoveStyleSheet
|
||||
nsresult rv = txn->Init(this, aSheet);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
txn.swap(*aTxn);
|
||||
txn.forget(aTxn);
|
||||
}
|
||||
|
||||
return rv;
|
||||
@ -4727,7 +4727,7 @@ nsEditor::CreateTxnForDeleteSelection(nsIEditor::EDirection aAction,
|
||||
// we let the aggregation txn be destroyed when the refptr goes out of scope
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
aggTxn.swap(*aTxn);
|
||||
aggTxn.forget(aTxn);
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -4822,15 +4822,14 @@ nsEditor::CreateTxnForDeleteInsertionPoint(nsIDOMRange *aRange,
|
||||
priorNodeAsText->GetLength(&length);
|
||||
if (0<length)
|
||||
{
|
||||
DeleteTextTxn *txn;
|
||||
nsRefPtr<DeleteTextTxn> txn;
|
||||
result = CreateTxnForDeleteCharacter(priorNodeAsText, length,
|
||||
ePrevious, &txn);
|
||||
ePrevious, getter_AddRefs(txn));
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
aTxn->AppendChild(txn);
|
||||
NS_ADDREF(*aNode = priorNode);
|
||||
*aOffset = txn->GetOffset();
|
||||
*aLength = txn->GetNumCharsToDelete();
|
||||
NS_RELEASE(txn);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -4841,11 +4840,10 @@ nsEditor::CreateTxnForDeleteInsertionPoint(nsIDOMRange *aRange,
|
||||
}
|
||||
else
|
||||
{ // priorNode is not text, so tell it's parent to delete it
|
||||
DeleteElementTxn *txn;
|
||||
result = CreateTxnForDeleteElement(priorNode, &txn);
|
||||
nsRefPtr<DeleteElementTxn> txn;
|
||||
result = CreateTxnForDeleteElement(priorNode, getter_AddRefs(txn));
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
aTxn->AppendChild(txn);
|
||||
NS_RELEASE(txn);
|
||||
NS_ADDREF(*aNode = priorNode);
|
||||
}
|
||||
}
|
||||
@ -4865,14 +4863,14 @@ nsEditor::CreateTxnForDeleteInsertionPoint(nsIDOMRange *aRange,
|
||||
nextNodeAsText->GetLength(&length);
|
||||
if (0<length)
|
||||
{
|
||||
DeleteTextTxn *txn;
|
||||
result = CreateTxnForDeleteCharacter(nextNodeAsText, 0, eNext, &txn);
|
||||
nsRefPtr<DeleteTextTxn> txn;
|
||||
result = CreateTxnForDeleteCharacter(nextNodeAsText, 0, eNext,
|
||||
getter_AddRefs(txn));
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
aTxn->AppendChild(txn);
|
||||
NS_ADDREF(*aNode = nextNode);
|
||||
*aOffset = txn->GetOffset();
|
||||
*aLength = txn->GetNumCharsToDelete();
|
||||
NS_RELEASE(txn);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -4883,11 +4881,10 @@ nsEditor::CreateTxnForDeleteInsertionPoint(nsIDOMRange *aRange,
|
||||
}
|
||||
else
|
||||
{ // nextNode is not text, so tell it's parent to delete it
|
||||
DeleteElementTxn *txn;
|
||||
result = CreateTxnForDeleteElement(nextNode, &txn);
|
||||
nsRefPtr<DeleteElementTxn> txn;
|
||||
result = CreateTxnForDeleteElement(nextNode, getter_AddRefs(txn));
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
aTxn->AppendChild(txn);
|
||||
NS_RELEASE(txn);
|
||||
NS_ADDREF(*aNode = nextNode);
|
||||
}
|
||||
}
|
||||
|
@ -1,2 +1,2 @@
|
||||
asserts(6) load 403965-1.xhtml # Bug 439258, but also charged to the wrong test
|
||||
load 403965-1.xhtml
|
||||
load 580151-1.xhtml
|
||||
|
@ -455,6 +455,8 @@ abstract public class GeckoApp
|
||||
outFile.length() == fileEntry.getSize())
|
||||
return;
|
||||
|
||||
killAnyZombies();
|
||||
|
||||
File dir = outFile.getParentFile();
|
||||
if (!outFile.exists())
|
||||
dir.mkdirs();
|
||||
@ -474,6 +476,27 @@ abstract public class GeckoApp
|
||||
outFile.setLastModified(fileEntry.getTime());
|
||||
}
|
||||
|
||||
boolean haveKilledZombies = false;
|
||||
|
||||
void killAnyZombies() {
|
||||
if (haveKilledZombies)
|
||||
return;
|
||||
haveKilledZombies = true;
|
||||
File proc = new File("/proc");
|
||||
File[] files = proc.listFiles();
|
||||
for (int i = 0; i < files.length; i++) {
|
||||
File p = files[i];
|
||||
File pEnv = new File(p, "environ");
|
||||
if (pEnv.canRead() && !p.getName().equals("self")) {
|
||||
int pid = Integer.parseInt(p.getName());
|
||||
if (pid != android.os.Process.myPid()) {
|
||||
Log.i("GeckoProcs", "gonna kill pid: " + p.getName());
|
||||
android.os.Process.killProcess(pid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addEnvToIntent(Intent intent) {
|
||||
Map<String,String> envMap = System.getenv();
|
||||
Set<Map.Entry<String,String>> envSet = envMap.entrySet();
|
||||
|
@ -558,6 +558,11 @@ public class GeckoInputConnection
|
||||
|
||||
GeckoAppShell.sendEventToGecko(
|
||||
new GeckoEvent(GeckoEvent.IME_COMPOSITION_END, 0, 0));
|
||||
|
||||
GeckoAppShell.sendEventToGecko(
|
||||
new GeckoEvent(GeckoEvent.IME_SET_SELECTION, start + count, 0));
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1743,8 +1743,6 @@ public:
|
||||
}
|
||||
virtual ~BasicShadowableThebesLayer()
|
||||
{
|
||||
NS_ABORT_IF_FALSE(!HasShadow() || !BasicManager()->InTransaction(),
|
||||
"Shadow layers can't be destroyed during txns!");
|
||||
if (IsSurfaceDescriptorValid(mBackBuffer))
|
||||
BasicManager()->ShadowLayerForwarder::DestroySharedSurface(&mBackBuffer);
|
||||
MOZ_COUNT_DTOR(BasicShadowableThebesLayer);
|
||||
|
@ -332,6 +332,14 @@ DeviceManagerD3D9::Init()
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Grab the associated HMONITOR so that we can find out
|
||||
* if it changed later */
|
||||
D3DDEVICE_CREATION_PARAMETERS parameters;
|
||||
if (FAILED(mDevice->GetCreationParameters(¶meters)))
|
||||
return false;
|
||||
mDeviceMonitor = mD3D9->GetAdapterMonitor(parameters.AdapterOrdinal);
|
||||
|
||||
|
||||
/*
|
||||
* Do some post device creation setup
|
||||
*/
|
||||
@ -560,7 +568,26 @@ DeviceManagerD3D9::VerifyReadyForRendering()
|
||||
++mDeviceResetCount;
|
||||
|
||||
if (hr == D3DERR_DEVICELOST) {
|
||||
return false;
|
||||
/* It is not unusual for Reset to return DEVICELOST
|
||||
* we're supposed to continue trying until we get
|
||||
* DEVICENOTRESET and then Reset is supposed to succeed.
|
||||
* Unfortunately, it seems like when we dock or undock
|
||||
* DEVICELOST happens and we never get DEVICENOTRESET. */
|
||||
|
||||
HMONITOR hMonitorWindow;
|
||||
hMonitorWindow = MonitorFromWindow(mFocusWnd, MONITOR_DEFAULTTOPRIMARY);
|
||||
if (hMonitorWindow == mDeviceMonitor) {
|
||||
/* The monitor has not changed. So, let's assume that the
|
||||
* DEVICENOTRESET will be comming. */
|
||||
|
||||
/* jrmuizel: I'm not sure how to trigger this case. Usually, we get
|
||||
* DEVICENOTRESET right away and Reset() succeeds without going through a
|
||||
* set of DEVICELOSTs. This is presumeably because we don't call
|
||||
* VerifyReadyForRendering when we don't have any reason to paint.
|
||||
* Hopefully comparing HMONITORs is not overly aggressive. */
|
||||
return false;
|
||||
}
|
||||
/* otherwise fall through and recreate the device */
|
||||
}
|
||||
|
||||
if (FAILED(hr) || !CreateVertexBuffer()) {
|
||||
|
@ -233,6 +233,9 @@ private:
|
||||
*/
|
||||
HWND mFocusWnd;
|
||||
|
||||
/* we use this to help track if our device temporarily or permanently lost */
|
||||
HMONITOR mDeviceMonitor;
|
||||
|
||||
PRUint32 mDeviceResetCount;
|
||||
|
||||
/* If this device supports dynamic textures */
|
||||
|
@ -217,7 +217,6 @@ CanvasLayerOGL::RenderLayer(int aPreviousDestination,
|
||||
|
||||
gl()->MakeCurrent();
|
||||
gl()->BindTex2DOffscreen(mCanvasGLContext);
|
||||
DEBUG_GL_ERROR_CHECK(gl());
|
||||
program = mOGLManager->GetBasicLayerProgram(CanUseOpaqueSurface(), PR_TRUE);
|
||||
} else if (mDelayedUpdates) {
|
||||
NS_ABORT_IF_FALSE(mCanvasSurface, "WebGL canvases should always be using full texture upload");
|
||||
@ -246,8 +245,6 @@ CanvasLayerOGL::RenderLayer(int aPreviousDestination,
|
||||
|
||||
mOGLManager->BindAndDrawQuad(program, mNeedsYFlip ? true : false);
|
||||
|
||||
DEBUG_GL_ERROR_CHECK(gl());
|
||||
|
||||
if (useGLContext) {
|
||||
gl()->UnbindTex2DOffscreen(mCanvasGLContext);
|
||||
}
|
||||
@ -344,8 +341,6 @@ ShadowCanvasLayerOGL::RenderLayer(int aPreviousFrameBuffer,
|
||||
program->SetTextureUnit(0);
|
||||
|
||||
mOGLManager->BindAndDrawQuad(program);
|
||||
|
||||
DEBUG_GL_ERROR_CHECK(gl());
|
||||
}
|
||||
|
||||
#endif // MOZ_IPC
|
||||
|
@ -71,8 +71,6 @@ RenderColorLayer(ColorLayer* aLayer, LayerManagerOGL *aManager,
|
||||
program->SetRenderColor(color);
|
||||
|
||||
aManager->BindAndDrawQuad(program);
|
||||
|
||||
DEBUG_GL_ERROR_CHECK(aManager->gl());
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -332,16 +332,10 @@ ContainerRender(Container* aContainer,
|
||||
2, f);
|
||||
}
|
||||
|
||||
DEBUG_GL_ERROR_CHECK(aContainer->gl());
|
||||
|
||||
aManager->BindAndDrawQuad(rgb, aManager->IsDrawingFlipped());
|
||||
|
||||
DEBUG_GL_ERROR_CHECK(aContainer->gl());
|
||||
|
||||
// Clean up resources. This also unbinds the texture.
|
||||
aContainer->gl()->fDeleteTextures(1, &containerSurface);
|
||||
|
||||
DEBUG_GL_ERROR_CHECK(aContainer->gl());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -432,8 +432,6 @@ ImageLayerOGL::RenderLayer(int,
|
||||
program->SetRenderOffset(aOffset);
|
||||
program->SetYCbCrTextureUnits(0, 1, 2);
|
||||
|
||||
DEBUG_GL_ERROR_CHECK(gl());
|
||||
|
||||
mOGLManager->BindAndDrawQuad(program);
|
||||
|
||||
// We shouldn't need to do this, but do it anyway just in case
|
||||
@ -503,8 +501,6 @@ ImageLayerOGL::RenderLayer(int,
|
||||
gl()->fBindTexture(LOCAL_GL_TEXTURE_RECTANGLE_ARB, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
DEBUG_GL_ERROR_CHECK(gl());
|
||||
}
|
||||
|
||||
static void
|
||||
@ -839,8 +835,6 @@ ShadowImageLayerOGL::RenderLayer(int aPreviousFrameBuffer,
|
||||
program->SetTextureUnit(0);
|
||||
|
||||
mOGLManager->BindAndDrawQuad(program);
|
||||
|
||||
DEBUG_GL_ERROR_CHECK(gl());
|
||||
}
|
||||
|
||||
#endif // MOZ_IPC
|
||||
|
@ -182,8 +182,6 @@ LayerManagerOGL::Initialize(nsRefPtr<GLContext> aContext)
|
||||
|
||||
MakeCurrent();
|
||||
|
||||
DEBUG_GL_ERROR_CHECK(mGLContext);
|
||||
|
||||
mHasBGRA =
|
||||
mGLContext->IsExtensionSupported(gl::GLContext::EXT_texture_format_BGRA8888) ||
|
||||
mGLContext->IsExtensionSupported(gl::GLContext::EXT_bgra);
|
||||
@ -318,8 +316,6 @@ LayerManagerOGL::Initialize(nsRefPtr<GLContext> aContext)
|
||||
// back to default framebuffer, to avoid confusion
|
||||
mGLContext->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0);
|
||||
|
||||
DEBUG_GL_ERROR_CHECK(mGLContext);
|
||||
|
||||
/* Create a simple quad VBO */
|
||||
|
||||
mGLContext->fGenBuffers(1, &mQuadVBO);
|
||||
@ -335,8 +331,6 @@ LayerManagerOGL::Initialize(nsRefPtr<GLContext> aContext)
|
||||
};
|
||||
mGLContext->fBufferData(LOCAL_GL_ARRAY_BUFFER, sizeof(vertices), vertices, LOCAL_GL_STATIC_DRAW);
|
||||
|
||||
DEBUG_GL_ERROR_CHECK(mGLContext);
|
||||
|
||||
nsCOMPtr<nsIConsoleService>
|
||||
console(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
|
||||
|
||||
@ -360,8 +354,6 @@ LayerManagerOGL::Initialize(nsRefPtr<GLContext> aContext)
|
||||
console->LogStringMessage(msg.get());
|
||||
}
|
||||
|
||||
DEBUG_GL_ERROR_CHECK(mGLContext);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -575,8 +567,6 @@ LayerManagerOGL::Render()
|
||||
MakeCurrent();
|
||||
}
|
||||
|
||||
DEBUG_GL_ERROR_CHECK(mGLContext);
|
||||
|
||||
SetupBackBuffer(width, height);
|
||||
SetupPipeline(width, height, ApplyWorldTransform);
|
||||
|
||||
@ -585,8 +575,6 @@ LayerManagerOGL::Render()
|
||||
LOCAL_GL_ONE, LOCAL_GL_ONE);
|
||||
mGLContext->fEnable(LOCAL_GL_BLEND);
|
||||
|
||||
DEBUG_GL_ERROR_CHECK(mGLContext);
|
||||
|
||||
const nsIntRect *clipRect = mRoot->GetClipRect();
|
||||
|
||||
if (clipRect) {
|
||||
@ -601,8 +589,6 @@ LayerManagerOGL::Render()
|
||||
|
||||
mGLContext->fEnable(LOCAL_GL_SCISSOR_TEST);
|
||||
|
||||
DEBUG_GL_ERROR_CHECK(mGLContext);
|
||||
|
||||
mGLContext->fClearColor(0.0, 0.0, 0.0, 0.0);
|
||||
mGLContext->fClear(LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
@ -612,8 +598,6 @@ LayerManagerOGL::Render()
|
||||
|
||||
static_cast<nsIWidget_MOZILLA_2_0_BRANCH*>(mWidget)->DrawOver(this, rect);
|
||||
|
||||
DEBUG_GL_ERROR_CHECK(mGLContext);
|
||||
|
||||
if (mTarget) {
|
||||
CopyToTarget();
|
||||
return;
|
||||
@ -645,8 +629,6 @@ LayerManagerOGL::Render()
|
||||
2, f);
|
||||
}
|
||||
|
||||
DEBUG_GL_ERROR_CHECK(mGLContext);
|
||||
|
||||
// we're going to use client-side vertex arrays for this.
|
||||
mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
|
||||
|
||||
@ -698,17 +680,12 @@ LayerManagerOGL::Render()
|
||||
0, coords);
|
||||
|
||||
mGLContext->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4);
|
||||
DEBUG_GL_ERROR_CHECK(mGLContext);
|
||||
}
|
||||
|
||||
mGLContext->fDisableVertexAttribArray(vcattr);
|
||||
mGLContext->fDisableVertexAttribArray(tcattr);
|
||||
|
||||
DEBUG_GL_ERROR_CHECK(mGLContext);
|
||||
|
||||
mGLContext->fFlush();
|
||||
|
||||
DEBUG_GL_ERROR_CHECK(mGLContext);
|
||||
}
|
||||
|
||||
void
|
||||
@ -979,8 +956,6 @@ LayerManagerOGL::CreateFBOWithTexture(const nsIntRect& aRect, InitMode aInit,
|
||||
|
||||
*aFBO = fbo;
|
||||
*aTexture = tex;
|
||||
|
||||
DEBUG_GL_ERROR_CHECK(gl());
|
||||
}
|
||||
|
||||
void LayerOGL::ApplyFilter(gfxPattern::GraphicsFilter aFilter)
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user