Merge m-c to bs.

This commit is contained in:
Kyle Huey 2011-02-25 15:23:05 -05:00
commit 225c13b333
275 changed files with 5206 additions and 1668 deletions

View File

@ -306,7 +306,7 @@ already_AddRefed<nsRootAccessible> nsAccessNode::GetRootAccessible()
}
nsIFrame*
nsAccessNode::GetFrame()
nsAccessNode::GetFrame() const
{
return mContent ? mContent->GetPrimaryFrame() : nsnull;
}

View File

@ -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.

View File

@ -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
};
//////////////////////////////////////////////////////////////////////////////

View File

@ -55,6 +55,7 @@
nsApplicationAccessible::nsApplicationAccessible() :
nsAccessibleWrap(nsnull, nsnull)
{
mFlags |= eApplicationAccessible;
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -681,7 +681,7 @@ nsDocAccessible::Shutdown()
}
nsIFrame*
nsDocAccessible::GetFrame()
nsDocAccessible::GetFrame() const
{
nsCOMPtr<nsIPresShell> shell(do_QueryReferent(mWeakShell));

View File

@ -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; }

View File

@ -871,7 +871,7 @@ nsHTMLComboboxListAccessible::
// nsHTMLComboboxAccessible: nsAccessNode
nsIFrame*
nsHTMLComboboxListAccessible::GetFrame()
nsHTMLComboboxListAccessible::GetFrame() const
{
nsIFrame* frame = nsHTMLSelectListAccessible::GetFrame();

View File

@ -228,7 +228,7 @@ public:
virtual ~nsHTMLComboboxListAccessible() {}
// nsAccessNode
virtual nsIFrame* GetFrame();
virtual nsIFrame* GetFrame() const;
virtual bool IsPrimaryForNode() const;
// nsAccessible

View File

@ -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

View File

@ -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(

View File

@ -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] {

View File

@ -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");

View File

@ -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();

View File

@ -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;
}
});
},

View File

@ -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;

View File

@ -258,6 +258,7 @@ _BROWSER_FILES += \
$(NULL)
else
_BROWSER_FILES += \
browser_bug565667.js \
browser_customize.js \
$(NULL)

View 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 OShannessy <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.

View File

@ -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);

View File

@ -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 \

View File

@ -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();
});
}

View File

@ -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");

View File

@ -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();
});
});
}

View 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();
});
}

View File

@ -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();
}

View File

@ -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;
}

View File

@ -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";

View File

@ -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);

View File

@ -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;

View File

@ -39,9 +39,6 @@
* Tests Library Left pane view for liveupdate.
*/
const Cc = Components.classes;
const Ci = Components.interfaces;
var gLibrary = null;
function test() {

View File

@ -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";

View File

@ -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;

View File

@ -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 \

View File

@ -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);
}

View File

@ -185,6 +185,7 @@ function processTestResult(aTest) {
}
function test() {
requestLongerTimeout(2);
// kick off tests
setTimeout(runNextTest, 0);
}

View File

@ -130,6 +130,7 @@ function processTestResult(aTest) {
}
function test() {
requestLongerTimeout(2);
// kick off tests
setTimeout(runNextTest, 0);
}

View File

@ -130,6 +130,7 @@ function processTestResult(aTest) {
}
function test() {
requestLongerTimeout(2);
// kick off tests
setTimeout(runNextTest, 0);
}

View File

@ -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);

View File

@ -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()
{

View File

@ -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, "");
}

View File

@ -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() {

View File

@ -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 .............. */

View File

@ -144,6 +144,7 @@ _BROWSER_TEST_FILES = \
browser_624727.js \
browser_625257.js \
browser_628270.js \
browser_635418.js \
$(NULL)
ifneq ($(OS_ARCH),Darwin)

View File

@ -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 OShannessy <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);
}

View File

@ -1 +1 @@
4.0b12pre
4.0b13pre

View File

@ -79,3 +79,4 @@ tr
uk
zh-CN
zh-TW
zu

View File

@ -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%);

View File

@ -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 {

View File

@ -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;
}

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -10,4 +10,4 @@
# hardcoded milestones in the tree from these two files.
#--------------------------------------------------------
2.0b12pre
2.0b13pre

View File

@ -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 ========================================================

View File

@ -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)
{

View File

@ -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,

View File

@ -332,6 +332,7 @@ nsFrameLoader::nsFrameLoader(nsIContent *aOwner, PRBool aNetworkCreated)
, mCurrentRemoteFrame(nsnull)
, mRemoteBrowser(nsnull)
#endif
, mRenderMode(RENDER_MODE_DEFAULT)
{
}

View File

@ -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;
}

View File

@ -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

View 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>

View File

@ -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

View File

@ -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);

View File

@ -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)

View File

@ -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);
}

View File

@ -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()
{

View File

@ -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;

View File

@ -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__ */

View File

@ -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.

View File

@ -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

View File

@ -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 */

View File

@ -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,

View File

@ -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];

View File

@ -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;

View File

@ -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,

View File

@ -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);

View File

@ -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;

View File

@ -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()
{

View File

@ -143,6 +143,7 @@ private:
virtual bool DeallocPStorage(PStorageParent* aActor);
virtual bool RecvReadPrefsArray(InfallibleTArray<PrefTuple> *retValue);
virtual bool RecvReadFontList(InfallibleTArray<FontListEntry>* retValue);
void EnsurePrefService();

View File

@ -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);

View File

@ -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)

View File

@ -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

View File

@ -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;

View File

@ -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)
{

View File

@ -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);

View File

@ -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

View File

@ -135,6 +135,7 @@ _TEST_FILES = \
test_bug617296.html \
test_bug620947.html \
test_bug622361.html \
test_bug633133.html \
$(NULL)
libs:: $(_TEST_FILES)

View 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>

View 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>

View File

@ -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

View File

@ -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);
}
}

View File

@ -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

View File

@ -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();

View File

@ -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));
}
}

View File

@ -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);

View File

@ -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(&parameters)))
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()) {

View File

@ -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 */

View File

@ -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

View File

@ -71,8 +71,6 @@ RenderColorLayer(ColorLayer* aLayer, LayerManagerOGL *aManager,
program->SetRenderColor(color);
aManager->BindAndDrawQuad(program);
DEBUG_GL_ERROR_CHECK(aManager->gl());
}
void

View File

@ -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());
}
}

View File

@ -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

View File

@ -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