Bug 581732 - Merge mozilla-central to tabcandy-central 2010/07/24 (with conflicts).

This commit is contained in:
Edward Lee 2010-07-24 16:48:38 -07:00
commit e99995210d
797 changed files with 36391 additions and 24418 deletions

View File

@ -1250,7 +1250,8 @@ nsDocAccessible::ContentInserted(nsIDocument *aDocument, nsIContent* aContainer,
void
nsDocAccessible::ContentRemoved(nsIDocument *aDocument, nsIContent* aContainer,
nsIContent* aChild, PRInt32 /* unused */)
nsIContent* aChild, PRInt32 /* unused */,
nsIContent* aPreviousSibling)
{
// It's no needed to invalidate the subtree of the removed element,
// because we get notifications directly from content (see

View File

@ -51,7 +51,6 @@ CPPSRCS = \
nsAccessibleWrap.cpp \
nsTextAccessibleWrap.cpp \
nsDocAccessibleWrap.cpp \
nsRootAccessibleWrap.cpp \
nsHTMLWin32ObjectAccessible.cpp \
nsARIAGridAccessibleWrap.cpp \
nsXULMenuAccessibleWrap.cpp \

View File

@ -219,10 +219,16 @@ __try {
nsIView *rootView;
viewManager->GetRootView(rootView);
if (rootView == view) {
// If the current object has a widget but was created by an
// outer object with its own outer window, then
// we want the native accessible for that outer window
hwnd = ::GetParent(hwnd);
// If the client accessible (OBJID_CLIENT) has a window but its window
// was created by an outer window then we want the native accessible
// for that outer window. If the accessible was created for outer
// window (if the outer window has inner windows then they share the
// same client accessible with it) then return native accessible for
// the outer window.
HWND parenthwnd = ::GetParent(hwnd);
if (parenthwnd)
hwnd = parenthwnd;
NS_ASSERTION(hwnd, "No window handle for window");
}
}

View File

@ -43,15 +43,8 @@
#ifndef _nsRootAccessibleWrap_H_
#define _nsRootAccessibleWrap_H_
#include "nsCOMPtr.h"
#include "nsRootAccessible.h"
class nsRootAccessibleWrap: public nsRootAccessible
{
public:
nsRootAccessibleWrap(nsIDocument *aDocument, nsIContent *aRootContent,
nsIWeakReference *aShell);
virtual ~nsRootAccessibleWrap();
};
typedef class nsRootAccessible nsRootAccessibleWrap;
#endif

View File

@ -48,14 +48,14 @@
label="&openLinkCmdInCurrent.label;"
accesskey="&openLinkCmdInCurrent.accesskey;"
oncommand="gContextMenu.openLinkInCurrent();"/>
<menuitem id="context-openlink"
label="&openLinkCmd.label;"
accesskey="&openLinkCmd.accesskey;"
oncommand="gContextMenu.openLink();"/>
<menuitem id="context-openlinkintab"
label="&openLinkCmdInTab.label;"
accesskey="&openLinkCmdInTab.accesskey;"
oncommand="gContextMenu.openLinkInTab();"/>
<menuitem id="context-openlink"
label="&openLinkCmd.label;"
accesskey="&openLinkCmd.accesskey;"
oncommand="gContextMenu.openLink();"/>
<menuseparator id="context-sep-open"/>
<menuitem id="context-bookmarklink"
label="&bookmarkThisLinkCmd.label;"
@ -250,14 +250,14 @@
label="&showOnlyThisFrameCmd.label;"
accesskey="&showOnlyThisFrameCmd.accesskey;"
oncommand="gContextMenu.showOnlyThisFrame();"/>
<menuitem id="context-openframe"
label="&openFrameCmd.label;"
accesskey="&openFrameCmd.accesskey;"
oncommand="gContextMenu.openFrame();"/>
<menuitem id="context-openframeintab"
label="&openFrameCmdInTab.label;"
accesskey="&openFrameCmdInTab.accesskey;"
oncommand="gContextMenu.openFrameInTab();"/>
<menuitem id="context-openframe"
label="&openFrameCmd.label;"
accesskey="&openFrameCmd.accesskey;"
oncommand="gContextMenu.openFrame();"/>
<menuseparator/>
<menuitem id="context-reloadframe"
label="&reloadFrameCmd.label;"

View File

@ -48,35 +48,20 @@ const MOUSE_SCROLL_ZOOM = 3;
* Controls the "full zoom" setting and its site-specific preferences.
*/
var FullZoom = {
//**************************************************************************//
// Name & Values
// The name of the setting. Identifies the setting in the prefs database.
// Identifies the setting in the content prefs database.
name: "browser.content.full-zoom",
// The global value (if any) for the setting. Lazily loaded from the service
// when first requested, then updated by the pref change listener as it changes.
// If there is no global value, then this should be undefined.
get globalValue() {
var globalValue = this._cps.getPref(null, this.name);
var globalValue = Services.contentPrefs.getPref(null, this.name);
if (typeof globalValue != "undefined")
globalValue = this._ensureValid(globalValue);
delete this.globalValue;
return this.globalValue = globalValue;
},
//**************************************************************************//
// Convenience Getters
// Content Pref Service
get _cps() {
delete this._cps;
return this._cps = Cc["@mozilla.org/content-pref/service;1"].
getService(Ci.nsIContentPrefService);
},
// browser.zoom.siteSpecific preference cache
_siteSpecificPref: undefined,
@ -93,19 +78,11 @@ var FullZoom = {
//**************************************************************************//
// nsISupports
// We can't use the Ci shortcut here because it isn't defined yet.
interfaces: [Components.interfaces.nsIDOMEventListener,
Components.interfaces.nsIObserver,
Components.interfaces.nsIContentPrefObserver,
Components.interfaces.nsISupportsWeakReference,
Components.interfaces.nsISupports],
QueryInterface: function FullZoom_QueryInterface(aIID) {
if (!this.interfaces.some(function (v) aIID.equals(v)))
throw Cr.NS_ERROR_NO_INTERFACE;
return this;
},
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMEventListener,
Ci.nsIObserver,
Ci.nsIContentPrefObserver,
Ci.nsISupportsWeakReference,
Ci.nsISupports]),
//**************************************************************************//
// Initialization & Destruction
@ -115,13 +92,11 @@ var FullZoom = {
window.addEventListener("DOMMouseScroll", this, false);
// Register ourselves with the service so we know when our pref changes.
this._cps.addObserver(this.name, this);
Services.contentPrefs.addObserver(this.name, this);
// We disable site-specific preferences in Private Browsing mode, because the
// content preferences module is disabled
let os = Cc["@mozilla.org/observer-service;1"].
getService(Ci.nsIObserverService);
os.addObserver(this, "private-browsing", true);
Services.obs.addObserver(this, "private-browsing", true);
// Retrieve the initial status of the Private Browsing mode.
this._inPrivateBrowsing = Cc["@mozilla.org/privatebrowsing;1"].
@ -138,13 +113,10 @@ var FullZoom = {
},
destroy: function FullZoom_destroy() {
let os = Cc["@mozilla.org/observer-service;1"].
getService(Ci.nsIObserverService);
os.removeObserver(this, "private-browsing");
Services.obs.removeObserver(this, "private-browsing");
gPrefService.removeObserver("browser.zoom.", this);
this._cps.removeObserver(this.name, this);
Services.contentPrefs.removeObserver(this.name, this);
window.removeEventListener("DOMMouseScroll", this, false);
delete this._cps;
},
@ -231,7 +203,7 @@ var FullZoom = {
// nsIContentPrefObserver
onContentPrefSet: function FullZoom_onContentPrefSet(aGroup, aName, aValue) {
if (aGroup == this._cps.grouper.group(gBrowser.currentURI))
if (aGroup == Services.contentPrefs.grouper.group(gBrowser.currentURI))
this._applyPrefToSetting(aValue);
else if (aGroup == null) {
this.globalValue = this._ensureValid(aValue);
@ -239,13 +211,13 @@ var FullZoom = {
// If the current page doesn't have a site-specific preference,
// then its zoom should be set to the new global preference now that
// the global preference has changed.
if (!this._cps.hasPref(gBrowser.currentURI, this.name))
if (!Services.contentPrefs.hasPref(gBrowser.currentURI, this.name))
this._applyPrefToSetting();
}
},
onContentPrefRemoved: function FullZoom_onContentPrefRemoved(aGroup, aName) {
if (aGroup == this._cps.grouper.group(gBrowser.currentURI))
if (aGroup == Services.contentPrefs.grouper.group(gBrowser.currentURI))
this._applyPrefToSetting();
else if (aGroup == null) {
this.globalValue = undefined;
@ -253,7 +225,7 @@ var FullZoom = {
// If the current page doesn't have a site-specific preference,
// then its zoom should be set to the default preference now that
// the global preference has changed.
if (!this._cps.hasPref(gBrowser.currentURI, this.name))
if (!Services.contentPrefs.hasPref(gBrowser.currentURI, this.name))
this._applyPrefToSetting();
}
},
@ -282,7 +254,7 @@ var FullZoom = {
}
var self = this;
this._cps.getPref(aURI, this.name, function(aResult) {
Services.contentPrefs.getPref(aURI, this.name, function (aResult) {
// Check that we're still where we expect to be in case this took a while.
let isSaneURI = (aBrowser && aBrowser.currentURI) ?
aURI.equals(aBrowser.currentURI) : false;
@ -366,12 +338,12 @@ var FullZoom = {
return;
var zoomLevel = ZoomManager.zoom;
this._cps.setPref(gBrowser.currentURI, this.name, zoomLevel);
Services.contentPrefs.setPref(gBrowser.currentURI, this.name, zoomLevel);
},
_removePref: function FullZoom__removePref() {
if (!(content.document instanceof Ci.nsIImageDocument))
this._cps.removePref(gBrowser.currentURI, this.name);
Services.contentPrefs.removePref(gBrowser.currentURI, this.name);
},

View File

@ -42,16 +42,16 @@
<menu id="file-menu" label="&fileMenu.label;"
accesskey="&fileMenu.accesskey;">
<menupopup id="menu_FilePopup">
<menuitem id="menu_newNavigator"
label="&newNavigatorCmd.label;"
accesskey="&newNavigatorCmd.accesskey;"
key="key_newNavigator"
command="cmd_newNavigator"/>
<menuitem id="menu_newNavigatorTab"
label="&tabCmd.label;"
command="cmd_newNavigatorTab"
key="key_newNavigatorTab"
accesskey="&tabCmd.accesskey;"/>
<menuitem id="menu_newNavigator"
label="&newNavigatorCmd.label;"
accesskey="&newNavigatorCmd.accesskey;"
key="key_newNavigator"
command="cmd_newNavigator"/>
<menuitem id="menu_openLocation"
label="&openLocationCmd.label;"
command="Browser:OpenLocation"
@ -62,17 +62,17 @@
command="Browser:OpenFile"
key="openFileKb"
accesskey="&openFileCmd.accesskey;"/>
<menuitem id="menu_close"
label="&closeCmd.label;"
key="key_close"
accesskey="&closeCmd.accesskey;"
command="cmd_close"/>
<menuitem id="menu_closeWindow"
hidden="true"
command="cmd_closeWindow"
key="key_closeWindow"
label="&closeWindow.label;"
accesskey="&closeWindow.accesskey;"/>
<menuitem id="menu_close"
label="&closeCmd.label;"
key="key_close"
accesskey="&closeCmd.accesskey;"
command="cmd_close"/>
<menuseparator/>
<menuitem id="menu_savePage"
label="&savePageCmd.label;"
@ -615,10 +615,10 @@
accesskey="&errorConsoleCmd.accesskey;"
key="key_errorConsole"
oncommand="toJavaScriptConsole();"/>
<menuitem id="headsUpDisplayConsole"
label="&hudConsoleCmd.label;"
accesskey="&hudConsoleCmd.accesskey;"
key="key_hudConsole"
<menuitem id="webConsole"
label="&webConsoleCmd.label;"
accesskey="&webConsoleCmd.accesskey;"
key="key_webConsole"
oncommand="HUDConsoleUI.toggleHUD();"/>
<menuitem id="menu_pageInfo"
accesskey="&pageInfoCmd.accesskey;"

View File

@ -236,7 +236,7 @@
<key id="key_openDownloads" key="&downloads.commandkey;" command="Tools:Downloads" modifiers="accel"/>
#endif
<key id="key_errorConsole" key="&errorConsoleCmd.commandkey;" oncommand="toJavaScriptConsole();" modifiers="accel,shift"/>
<key id="key_hudConsole" key="&hudConsoleCmd.commandkey;" oncommand="HUDConsoleUI.toggleHUD();" modifiers="accel,shift"/>
<key id="key_webConsole" key="&webConsoleCmd.commandkey;" oncommand="HUDConsoleUI.toggleHUD();" modifiers="accel,shift"/>
<key id="key_inspect" key="&inspectMenu.commandkey;" command="Tools:Inspect" modifiers="accel,shift"/>
<key id="openFileKb" key="&openFileCmd.commandkey;" command="Browser:OpenFile" modifiers="accel"/>
<key id="key_savePage" key="&savePageCmd.commandkey;" command="Browser:SavePage" modifiers="accel"/>

View File

@ -80,7 +80,7 @@ toolbar[printpreview="true"] {
-moz-box-ordinal-group: 100;
}
#navigator-toolbox[tabsontop="true"] > #TabsToolbar {
#TabsToolbar[tabsontop="true"] {
-moz-box-ordinal-group: 10;
}

View File

@ -7778,6 +7778,12 @@ var TabContextMenu = {
// Only one of pin/unpin should be visible
document.getElementById("context_pinTab").hidden = this.contextTab.pinned;
document.getElementById("context_unpinTab").hidden = !this.contextTab.pinned;
// Disable "Close other Tabs" if there is only one unpinned tab and
// hide it when the user rightclicked on a pinned tab.
var unpinnedTabs = gBrowser.tabs.length - gBrowser._numPinnedTabs;
document.getElementById("context_closeOtherTabs").disabled = unpinnedTabs <= 1;
document.getElementById("context_closeOtherTabs").hidden = this.contextTab.pinned;
}
};

View File

@ -112,17 +112,11 @@
<menupopup id="tabContextMenu"
onpopupshowing="if (event.target == this) TabContextMenu.updateContextMenu(this);"
onpopuphidden="if (event.target == this) TabContextMenu.contextTab = null;">
<menuitem id="context_newTab" label="&newTab.label;" accesskey="&newTab.accesskey;"
command="cmd_newNavigatorTab"/>
<menuseparator/>
<menuitem id="context_reloadTab" label="&reloadTab.label;" accesskey="&reloadTab.accesskey;"
oncommand="gBrowser.reloadTab(TabContextMenu.contextTab);"/>
<menuitem id="context_reloadAllTabs" label="&reloadAllTabs.label;" accesskey="&reloadAllTabs.accesskey;"
tbattr="tabbrowser-multiple"
oncommand="gBrowser.reloadAllTabs();"/>
<menuitem id="context_closeOtherTabs" label="&closeOtherTabs.label;" accesskey="&closeOtherTabs.accesskey;"
tbattr="tabbrowser-multiple"
oncommand="gBrowser.removeAllTabsBut(TabContextMenu.contextTab);"/>
<menuseparator/>
<menuitem id="context_openTabInWindow" label="&openTabInNewWindow.label;"
accesskey="&openTabInNewWindow.accesskey;"
@ -143,11 +137,13 @@
label="&bookmarkAllTabs.label;"
accesskey="&bookmarkAllTabs.accesskey;"
command="Browser:BookmarkAllTabs"/>
<menuseparator/>
<menuitem id="context_closeOtherTabs" label="&closeOtherTabs.label;" accesskey="&closeOtherTabs.accesskey;"
oncommand="gBrowser.removeAllTabsBut(TabContextMenu.contextTab);"/>
<menuitem id="context_undoCloseTab"
label="&undoCloseTab.label;"
accesskey="&undoCloseTab.accesskey;"
command="History:UndoCloseTab"/>
<menuseparator/>
<menuitem id="context_closeTab" label="&closeTab.label;" accesskey="&closeTab.accesskey;"
oncommand="gBrowser.removeTab(TabContextMenu.contextTab);"/>
</menupopup>

View File

@ -219,6 +219,7 @@
<li>Josh Aas</li>
<li>Robert Accettura</li>
<li>Lucas Adamski</li>
<li>Raymond Etornam Agbeame</li>
<li>Ehsan Akhgari</li>
<li>Sean Alamares</li>
<li>Pedro Alves</li>
@ -403,6 +404,7 @@
<li>Gervase Markham</li>
<li>Sean Martell</li>
<li>Jim Mathies</li>
<li>Blair McBride</li>
<li>Erica McClure</li>
<li>Graeme McCutcheon</li>
<li>Patrick McManus</li>
@ -578,6 +580,7 @@
<li>Christine Yen</li>
<li>Kohei Yoshino</li>
<li>Shigeru Yoshitake</li>
<li>Tanner M. Young</li>
<li>Boris Zbarsky</li>
<li>Marco Zehe</li>
<li>Matthew Zeier</li>

View File

@ -80,8 +80,8 @@
<menulist id="openWhereList">
<menupopup>
<menuitem value="0" id="currentWindow" label="&topTab.label;"/>
<menuitem value="1" label="&newWindow.label;"/>
<menuitem value="3" label="&newTab.label;"/>
<menuitem value="1" label="&newWindow.label;"/>
</menupopup>
</menulist>
<spacer flex="1"/>

View File

@ -54,6 +54,9 @@ var EXPORTED_SYMBOLS = ["style"];
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
Cu.import("resource://gre/modules/Services.jsm");
var style = {

View File

@ -1226,8 +1226,13 @@
<body>
<![CDATA[
var tabsToClose = this.tabs.length;
if (!aAll)
<<<<<<< local
tabsToClose = this.visibleTabs.length - 1;
=======
tabsToClose -= 1 + gBrowser._numPinnedTabs;
>>>>>>> other
if (tabsToClose <= 1)
return true;
@ -1274,13 +1279,22 @@
<parameter name="aTab"/>
<body>
<![CDATA[
if (aTab.pinned)
return;
if (this.warnAboutClosingTabs(false)) {
var tabs = this.visibleTabs;
this.selectedTab = aTab;
<<<<<<< local
for (let i = tabs.length - 1; i >= 0; --i) {
if (tabs[i] != aTab)
this.removeTab(tabs[i]);
=======
for (let i = this.tabs.length - 1; i >= 0; --i) {
if (this.tabs[i] != aTab && !this.tabs[i].pinned)
this.removeTab(this.tabs[i]);
>>>>>>> other
}
}
]]>
@ -2326,7 +2340,8 @@
inherited from the binding parent -->
<method name="_getScrollableElements">
<body><![CDATA[
return document.getBindingParent(this).childNodes;
return Array.filter(document.getBindingParent(this).childNodes,
this._canScrollToElement, this);
]]></body>
</method>
<method name="_canScrollToElement">

View File

@ -136,6 +136,7 @@ _BROWSER_FILES = \
browser_bug556061.js \
browser_bug562649.js \
browser_bug563588.js \
browser_bug577121.js \
browser_contextSearchTabPosition.js \
browser_ctrlTab.js \
browser_discovery.js \
@ -146,7 +147,6 @@ _BROWSER_FILES = \
browser_inspector_treeSelection.js \
browser_inspector_highlighter.js \
browser_inspector_stylePanel.js \
browser_overflowScroll.js \
browser_pageInfo.js \
browser_page_style_menu.js \
browser_pinnedTabs.js \
@ -181,9 +181,19 @@ _BROWSER_FILES = \
$(NULL)
ifneq (cocoa,$(MOZ_WIDGET_TOOLKIT))
_BROWSER_FILES += browser_bug462289.js
_BROWSER_FILES += \
browser_bug462289.js \
$(NULL)
else
_BROWSER_FILES += browser_customize.js
_BROWSER_FILES += \
browser_customize.js \
$(NULL)
endif
ifneq (gtk2,$(MOZ_WIDGET_TOOLKIT))
_BROWSER_FILES += \
browser_overflowScroll.js \
$(NULL)
endif
libs:: $(_TEST_FILES)

View File

@ -0,0 +1,56 @@
/* ***** 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 577121 test.
*
* The Initial Developer of the Original Code is
* Michael Kohler <michaelkohler@live.com>.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
function test() {
// Open 2 other tabs, and pin the second one. Like that, the initial tab
// should get closed.
let testTab1 = gBrowser.addTab();
let testTab2 = gBrowser.addTab();
gBrowser.pinTab(testTab2);
// Now execute "Close other Tabs" on the first manually opened tab (tab1).
// -> tab2 ist pinned, tab1 should remain open and the initial tab should
// get closed.
gBrowser.removeAllTabsBut(testTab1);
is(gBrowser.tabs.length, 2, "there are two remaining tabs open");
is(gBrowser.tabs[0], testTab2, "pinned tab2 stayed open");
is(gBrowser.tabs[1], testTab1, "tab1 stayed open");
// Cleanup. Close only one tab because we need an opened tab at the end of
// the test.
gBrowser.removeTab(testTab2);
}

View File

@ -1,7 +1,7 @@
var tabContainer = gBrowser.tabContainer;
var tabstrip = tabContainer.mTabstrip;
var tabstrip = gBrowser.tabContainer.mTabstrip;
var scrollbox = tabstrip._scrollbox;
var originalSmoothScroll = tabstrip.smoothScroll;
var tabs = gBrowser.tabs;
function rect(ele) ele.getBoundingClientRect();
function width(ele) rect(ele).width;
@ -12,13 +12,9 @@ function isRight(ele, msg) is(right(ele), right(scrollbox), msg);
function elementFromPoint(x) tabstrip._elementFromPoint(x);
function nextLeftElement() elementFromPoint(left(scrollbox) - 1);
function nextRightElement() elementFromPoint(right(scrollbox) + 1);
function firstScrollable() tabs[gBrowser._numPinnedTabs];
function test() {
if (TabsOnTop.enabled) {
todo(false, "need to figure out why this doesn't work with tabs on top on OS X and Windows 7 (bug 575748)");
return;
}
waitForExplicitFinish();
// If the previous (or more) test finished with cleaning up the tabs,
@ -32,8 +28,9 @@ function doTest() {
var tabMinWidth = parseInt(getComputedStyle(gBrowser.selectedTab, null).minWidth);
var tabCountForOverflow = Math.ceil(width(tabstrip) / tabMinWidth * 3);
while (tabContainer.childNodes.length < tabCountForOverflow)
while (tabs.length < tabCountForOverflow)
gBrowser.addTab("about:blank", {skipAnimation: true});
gBrowser.pinTab(tabs[0]);
tabstrip.addEventListener("overflow", runOverflowTests, false);
}
@ -48,37 +45,37 @@ function runOverflowTests(aEvent) {
var downButton = tabstrip._scrollButtonDown;
var element;
gBrowser.selectedTab = tabContainer.firstChild;
isLeft(tabContainer.firstChild, "Selecting the first tab scrolls it into view");
gBrowser.selectedTab = firstScrollable();
isLeft(firstScrollable(), "Selecting the first tab scrolls it into view");
element = nextRightElement();
EventUtils.synthesizeMouse(downButton, 0, 0, {});
EventUtils.synthesizeMouse(downButton, 1, 1, {});
isRight(element, "Scrolled one tab to the right with a single click");
gBrowser.selectedTab = tabContainer.lastChild;
isRight(tabContainer.lastChild, "Selecting the last tab scrolls it into view");
gBrowser.selectedTab = tabs[tabs.length - 1];
isRight(gBrowser.selectedTab, "Selecting the last tab scrolls it into view");
element = nextLeftElement();
EventUtils.synthesizeMouse(upButton, 0, 0, {});
EventUtils.synthesizeMouse(upButton, 1, 1, {});
isLeft(element, "Scrolled one tab to the left with a single click");
element = elementFromPoint(left(scrollbox) - width(scrollbox));
EventUtils.synthesizeMouse(upButton, 0, 0, {clickCount: 2});
EventUtils.synthesizeMouse(upButton, 1, 1, {clickCount: 2});
isLeft(element, "Scrolled one page of tabs with a double click");
EventUtils.synthesizeMouse(upButton, 0, 0, {clickCount: 3});
isLeft(tabContainer.firstChild, "Scrolled to the start with a triple click");
EventUtils.synthesizeMouse(upButton, 1, 1, {clickCount: 3});
isLeft(firstScrollable(), "Scrolled to the start with a triple click");
for (var i = 2; i; i--)
EventUtils.synthesizeMouseScroll(scrollbox, 0, 0, {axis: "horizontal", delta: -1});
isLeft(tabContainer.firstChild, "Remained at the start with the mouse wheel");
EventUtils.synthesizeMouseScroll(scrollbox, 1, 1, {axis: "horizontal", delta: -1});
isLeft(firstScrollable(), "Remained at the start with the mouse wheel");
element = nextRightElement();
EventUtils.synthesizeMouseScroll(scrollbox, 0, 0, {axis: "horizontal", delta: 1});
EventUtils.synthesizeMouseScroll(scrollbox, 1, 1, {axis: "horizontal", delta: 1});
isRight(element, "Scrolled one tab to the right with the mouse wheel");
while (tabContainer.childNodes.length > 1)
gBrowser.removeTab(tabContainer.lastChild);
while (tabs.length > 1)
gBrowser.removeTab(tabs[0]);
tabstrip.smoothScroll = originalSmoothScroll;
finish();

View File

@ -182,8 +182,8 @@ function runTest(testNum) {
case 3:
// Context menu for text link
checkContextMenu(["context-openlink", true,
"context-openlinkintab", true,
checkContextMenu(["context-openlinkintab", true,
"context-openlink", true,
"---", null,
"context-bookmarklink", true,
"context-savelink", true,
@ -303,8 +303,8 @@ function runTest(testNum) {
"context-selectall", true,
"frame", null,
["context-showonlythisframe", true,
"context-openframe", true,
"context-openframeintab", true,
"context-openframe", true,
"---", null,
"context-reloadframe", true,
"---", null,

View File

@ -554,9 +554,9 @@ FeedWriter.prototype = {
var url = makeURI(aURL);
url.QueryInterface(Ci.nsIURL);
if (url == null || url.fileName.length == 0)
return aURL;
return decodeURIComponent(aURL);
return decodeURI(url.fileName);
return decodeURIComponent(url.fileName);
},
/**

View File

@ -55,6 +55,8 @@ _TEST_FILES = test_bug408328.html \
bug408328-data.xml \
test_bug368464.html \
bug368464-data.xml \
test_bug494328.html \
bug494328-data.xml \
test_registerHandler.html \
$(NULL)

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
<channel>
<title>Channel title</title>
<description>Channel description</description>
<link>Channel link</link>
<item>
<title>Episode 1</title>
<enclosure url="http://www.example.com/podcasts/Episode%201" length="0" type="audio/x-m4a" />
</item>
<item>
<title>Episode 2</title>
<enclosure url="http://www.example.com/podcasts/Episode%20%232" length="0" type="audio/x-m4a" />
</item>
<item>
<title>Episode 3</title>
<enclosure url="http://www.example.com/podcasts/Episode%20%233/" length="0" type="audio/x-m4a" />
</item>
<item>
<title>Episode 4</title>
<enclosure url="http://www.example.com/podcasts/Is%20This%20Episode%20%234%3F" length="0" type="audio/x-m4a" />
</item>
</channel>
</rss>

View File

@ -0,0 +1,38 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=494328
-->
<head>
<title>Test for bug 494328</title>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/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=494328">Mozilla Bug 494328</a>
<p id="display"><iframe id="testFrame" src="bug494328-data.xml"></iframe></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
/** Test for Bug 494328 **/
SimpleTest.waitForExplicitFinish();
addLoadEvent(function() {
netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
var links = $("testFrame").contentDocument.getElementById("feedContent").querySelectorAll("div.enclosure > a");
is(links[0].textContent, "Episode 1", "filename decoded incorrectly");
is(links[1].textContent, "Episode #2", "filename decoded incorrectly");
is(links[2].textContent, "http://www.example.com/podcasts/Episode #3/", "filename decoded incorrectly");
is(links[3].textContent, "Is This Episode #4?", "filename decoded incorrectly");
});
addLoadEvent(SimpleTest.finish);
</script>
</pre>
</body>
</html>

View File

@ -134,12 +134,6 @@
default="true"
selectiontype="single"
selection="link"/>
<menuitem id="placesContext_open:newwindow"
command="placesCmd_open:window"
label="&cmd.open_window.label;"
accesskey="&cmd.open_window.accesskey;"
selectiontype="single"
selection="link"/>
<menuitem id="placesContext_open:newtab"
command="placesCmd_open:tab"
label="&cmd.open_tab.label;"
@ -162,6 +156,12 @@
accesskey="&cmd.open_all_in_tabs.accesskey;"
selectiontype="multiple"
selection="link"/>
<menuitem id="placesContext_open:newwindow"
command="placesCmd_open:window"
label="&cmd.open_window.label;"
accesskey="&cmd.open_window.accesskey;"
selectiontype="single"
selection="link"/>
<menuseparator id="placesContext_openSeparator"/>
<menuitem id="placesContext_new:bookmark"
command="placesCmd_new:bookmark"

View File

@ -129,11 +129,17 @@ function check_sidebar_tree_order(aExpectedRows) {
var tree = sidebar.contentDocument.getElementById("historyTree");
var treeView = tree.view;
var rc = treeView.rowCount;
is(rc, aExpectedRows, "All expected tree rows are present");
var columns = tree.columns;
is(columns.count, 1, "There should be only 1 column in the sidebar");
var found = 0;
for (var r = 0; r < rc; r++) {
var node = treeView.nodeForTreeIndex(r);
// We could inherit visits from previous tests, skip them since they are
// not interesting for us.
if (pages.indexOf(node.uri) == -1)
continue;
is(node.uri, pages[r], "Node is in correct position based on its visit date");
found++;
}
ok(found, aExpectedRows, "Found all expected results");
}

View File

@ -1015,12 +1015,12 @@ SessionStoreService.prototype = {
// create a new tab
let browser = aWindow.gBrowser;
let tab = browser.addTab();
// restore the tab's position
browser.moveTabTo(tab, closedTab.pos);
// restore tab content
this.restoreHistoryPrecursor(aWindow, [tab], [closedTabState], 1, 0, 0);
// restore the tab's position
browser.moveTabTo(tab, closedTab.pos);
// focus the tab's content area
let content = browser.getBrowserForTab(tab).contentWindow;

View File

@ -114,6 +114,7 @@ _BROWSER_TEST_FILES = \
browser_522545.js \
browser_524745.js \
browser_528776.js \
browser_579879.js \
$(NULL)
libs:: $(_BROWSER_TEST_FILES)

View File

@ -0,0 +1,21 @@
function test() {
waitForExplicitFinish();
var tab1 = gBrowser.addTab("data:text/plain,foo");
gBrowser.pinTab(tab1);
tab1.linkedBrowser.addEventListener("load", function () {
var tab2 = gBrowser.addTab();
gBrowser.pinTab(tab2);
is(Array.indexOf(gBrowser.tabs, tab1), 0, "pinned tab 1 is at the first position");
gBrowser.removeTab(tab1);
tab1 = undoCloseTab();
ok(tab1.pinned, "pinned tab 1 has been restored as a pinned tab");
is(Array.indexOf(gBrowser.tabs, tab1), 0, "pinned tab 1 has been restored to the first position");
gBrowser.removeTab(tab1);
gBrowser.removeTab(tab2);
finish();
}, true);
}

View File

@ -12,8 +12,6 @@
<!ENTITY mainWindow.titlePrivateBrowsingSuffix "(Private Browsing)">
<!-- Tab context menu -->
<!ENTITY newTab.label "New Tab">
<!ENTITY newTab.accesskey "N">
<!ENTITY reloadTab.label "Reload Tab">
<!ENTITY reloadTab.accesskey "R">
<!ENTITY reloadAllTabs.label "Reload All Tabs">
@ -171,9 +169,9 @@
<!ENTITY errorConsoleCmd.accesskey "C">
<!ENTITY errorConsoleCmd.commandkey "j">
<!ENTITY hudConsoleCmd.label "Heads Up Display">
<!ENTITY hudConsoleCmd.accesskey "U">
<!ENTITY hudConsoleCmd.commandkey "k">
<!ENTITY webConsoleCmd.label "Web Console">
<!ENTITY webConsoleCmd.accesskey "W">
<!ENTITY webConsoleCmd.commandkey "k">
<!ENTITY inspectMenu.label "Inspect">
<!ENTITY inspectMenu.accesskey "T">
@ -291,16 +289,16 @@
<!ENTITY searchFocus.commandkey2 "e">
<!ENTITY searchFocusUnix.commandkey "j">
<!ENTITY openLinkCmdInTab.label "Open Link in New Tab">
<!ENTITY openLinkCmdInTab.accesskey "T">
<!ENTITY openLinkCmd.label "Open Link in New Window">
<!ENTITY openLinkCmd.accesskey "W">
<!ENTITY openLinkCmdInCurrent.label "Open Link">
<!ENTITY openLinkCmdInCurrent.accesskey "O">
<!ENTITY openLinkCmdInTab.label "Open Link in New Tab">
<!ENTITY openLinkCmdInTab.accesskey "T">
<!ENTITY openFrameCmd.label "Open Frame in New Window">
<!ENTITY openFrameCmd.accesskey "W">
<!ENTITY openFrameCmdInTab.label "Open Frame in New Tab">
<!ENTITY openFrameCmdInTab.accesskey "T">
<!ENTITY openFrameCmd.label "Open Frame in New Window">
<!ENTITY openFrameCmd.accesskey "W">
<!ENTITY showOnlyThisFrameCmd.label "Show Only This Frame">
<!ENTITY showOnlyThisFrameCmd.accesskey "S">
<!ENTITY reloadCmd.commandkey "r">

View File

@ -2,8 +2,8 @@
<!ENTITY enter.label "Enter the web location (URL), or specify the local file you would like to open:">
<!ENTITY chooseFile.label "Choose File…">
<!ENTITY newWindow.label "New Window">
<!ENTITY newTab.label "New Tab">
<!ENTITY newWindow.label "New Window">
<!ENTITY topTab.label "Current Tab">
<!ENTITY caption.label "Open Web Location">
<!ENTITY openWhere.label "Open in:">

View File

@ -1,7 +1,7 @@
searchtip=Search using %S
cmd_clearHistory=Clear Search History
cmd_clearHistory_accesskey=C
cmd_clearHistory_accesskey=H
cmd_showSuggestions=Show Suggestions
cmd_showSuggestions_accesskey=S

View File

@ -1259,15 +1259,6 @@ statusbarpanel#statusbar-display {
-moz-image-region: rect(0, 144px, 16px, 128px);
}
#context_newTab {
list-style-image: url("chrome://browser/skin/Toolbar-small.png");
-moz-image-region: rect(0px 64px 16px 48px);
}
#context_newTab[disabled] {
-moz-image-region: rect(16px 64px 32px 48px);
}
#context_reloadTab {
list-style-image: url("moz-icon://stock/gtk-refresh?size=menu");
}

View File

@ -174,6 +174,12 @@ groupbox.treebox .groupbox-body {
#imagetree {
min-height: 10em;
margin-top: 2px;
margin-bottom: 0;
}
#mediaSplitter {
-moz-appearance: none;
height: .8em;
}
#mediaGrid {

View File

@ -122,6 +122,11 @@ groupbox.treebox .groupbox-body {
/* Media Tab */
#imagetree {
min-height: 10em;
margin-bottom: 0;
}
#mediaSplitter {
background: none;
}
#mediaGrid {

View File

@ -39,9 +39,9 @@
}
#toolbar-menubar:not(:-moz-lwtheme),
#navigator-toolbox[tabsontop="true"] > #TabsToolbar:not(:-moz-lwtheme),
#navigator-toolbox:not([tabsontop="true"]) > #nav-bar:not(:-moz-lwtheme),
#navigator-toolbox:not([tabsontop="true"]) > #nav-bar + #customToolbars + #PersonalToolbar[collapsed="true"] + #TabsToolbar:last-child:not(:-moz-lwtheme) {
#TabsToolbar[tabsontop="true"]:not(:-moz-lwtheme),
#navigator-toolbox[tabsontop="false"] > #nav-bar:not(:-moz-lwtheme),
#nav-bar + #customToolbars + #PersonalToolbar[collapsed="true"] + #TabsToolbar[tabsontop="false"]:last-child:not(:-moz-lwtheme) {
background: transparent !important;
color: black;
text-shadow: 0 0 .7em white, 0 0 .7em white, 0 1px 0 rgba(255,255,255,.4);
@ -54,9 +54,9 @@
/* Make the window draggable by glassed toolbars (bug 555081) */
#toolbar-menubar:not([autohide="true"]),
#navigator-toolbox[tabsontop="true"] > #TabsToolbar,
#navigator-toolbox:not([tabsontop="true"]) > #nav-bar,
#navigator-toolbox:not([tabsontop="true"]) > #nav-bar + #customToolbars + #PersonalToolbar[collapsed="true"] + #TabsToolbar:last-child,
#TabsToolbar[tabsontop="true"],
#navigator-toolbox[tabsontop="false"] > #nav-bar,
#nav-bar + #customToolbars + #PersonalToolbar[collapsed="true"] + #TabsToolbar[tabsontop="false"]:last-child,
#navigator-toolbox > toolbar:not(#toolbar-menubar):-moz-lwtheme {
-moz-binding: url("chrome://global/content/bindings/toolbar.xml#toolbar-drag");
}

View File

@ -80,11 +80,12 @@
padding-bottom: 1px;
}
#nav-bar:not(:-moz-lwtheme) {
#nav-bar:not(:-moz-lwtheme),
#navigator-toolbox[tabsontop="true"] > #nav-bar {
background-image: -moz-linear-gradient(@toolbarHighlight@, rgba(255,255,255,0));
}
#navigator-toolbox:not([tabsontop="true"]) > #toolbar-menubar:not(:-moz-lwtheme) {
#navigator-toolbox[tabsontop="false"] > #toolbar-menubar:not(:-moz-lwtheme) {
background-image: -moz-linear-gradient(@toolbarHighlight@, @toolbarHighlight@);
}
@ -1092,11 +1093,11 @@ richlistitem[type="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-i
#TabsToolbar {
min-height: 0;
padding: 0;
-moz-box-shadow: 0 -1px ThreeDShadow inset;
}
#TabsToolbar:not(:-moz-lwtheme),
#navigator-toolbox:not([tabsontop="true"]) > #TabsToolbar {
#TabsToolbar[tabsontop="false"] {
-moz-box-shadow: 0 -1px ThreeDShadow inset;
background-image: -moz-linear-gradient(transparent, transparent 10%,
rgba(0,0,0,.03) 50%, rgba(0,0,0,.1) 90%, rgba(0,0,0,.2));
}
@ -1145,21 +1146,26 @@ richlistitem[type="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-i
.tabbrowser-tab:-moz-lwtheme-darktext,
.tabs-newtab-button:-moz-lwtheme-darktext {
background-image: -moz-linear-gradient(left, transparent, transparent 1px,
rgba(255,255,255,.4) 1px, rgba(255,255,255,.4));
rgba(60%,60%,60%,.5) 1px, rgba(60%,60%,60%,.5));
}
.tabbrowser-tab:-moz-lwtheme-darktext:not([selected="true"]):hover,
.tabs-newtab-button:-moz-lwtheme-darktext:hover {
background-image: -moz-linear-gradient(left, transparent, transparent 1px,
rgba(255,255,255,.6) 1px, rgba(255,255,255,.6));
rgba(80%,80%,80%,.5) 1px, rgba(80%,80%,80%,.5));
}
.tabbrowser-tab[selected="true"] {
.tabbrowser-tab[selected="true"]:-moz-lwtheme {
background-image: -moz-linear-gradient(left, transparent, transparent 1px,
@toolbarHighlight@ 1px, @toolbarHighlight@);
}
#tabbrowser-tabs[tabsontop="false"] > .tabbrowser-tab[selected="true"]:not(:-moz-lwtheme) {
background-image: -moz-linear-gradient(left, transparent, transparent 1px, white 1px, white);
color: black;
}
#navigator-toolbox[tabsontop="true"] > #TabsToolbar > #tabbrowser-tabs > .tabbrowser-tab[selected="true"]:not(:-moz-lwtheme) {
#tabbrowser-tabs[tabsontop="true"] > .tabbrowser-tab[selected="true"]:not(:-moz-lwtheme) {
background-image: -moz-radial-gradient(center top, white, rgba(255,255,255,0) 60%),
-moz-linear-gradient(left, transparent, transparent 1px,
@toolbarHighlight@ 1px, @toolbarHighlight@),
@ -1170,11 +1176,7 @@ richlistitem[type="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-i
color: -moz-dialogText;
}
.tabbrowser-tab:-moz-lwtheme[selected="true"] {
text-shadow: none;
}
.tabbrowser-tab:-moz-lwtheme:not([selected="true"]) {
.tabbrowser-tab:-moz-lwtheme {
color: inherit;
}

View File

@ -188,6 +188,13 @@ groupbox tree {
/* Media Tab */
#imagetree {
min-height: 10em;
margin-bottom: 0;
}
#mediaSplitter {
border-style: none;
background: none;
height: .8em;
}
#mediaGrid {

View File

@ -1401,12 +1401,15 @@ host_%.$(OBJ_SUFFIX): %.mm $(GLOBAL_DEPS)
@$(MAKE_DEPS_AUTO_CC)
$(ELOG) $(CC) $(OUTOPTION)$@ -c $(COMPILE_CFLAGS) $(_VPATH_SRCS)
# DEFINES and ACDEFINES are needed here to enable conditional compilation of Q_OBJECTs:
# 'moc' only knows about #defines it gets on the command line (-D...), not in
# included headers like mozilla-config.h
moc_%.cpp: %.h $(GLOBAL_DEPS)
$(MOC) $< $(OUTOPTION)$@
$(MOC) $(DEFINES) $(ACDEFINES) $< $(OUTOPTION)$@
moc_%.cc: %.cc $(GLOBAL_DEPS)
$(REPORT_BUILD)
$(ELOG) $(MOC) $(_VPATH_SRCS:.cc=.h) $(OUTOPTION)$@
$(ELOG) $(MOC) $(DEFINES) $(ACDEFINES) $(_VPATH_SRCS:.cc=.h) $(OUTOPTION)$@
ifdef ASFILES
# The AS_DASH_C_FLAG is needed cause not all assemblers (Solaris) accept

View File

@ -132,7 +132,7 @@ GCONF_VERSION=1.2.1
GIO_VERSION=2.0
STARTUP_NOTIFICATION_VERSION=0.8
DBUS_VERSION=0.60
SQLITE_VERSION=3.6.23.1
SQLITE_VERSION=3.7.0
LIBNOTIFY_VERSION=0.4
MSMANIFEST_TOOL=
@ -905,7 +905,7 @@ EOF
AC_MSG_RESULT("yes")
else
AC_MSG_RESULT("no")
AC_MSG_ERROR([You are targeting Windows version 0x$MOZ_WINSDK_TARGETVER, but your SDK only supports up to version $MOZ_WINSDK_MAXVER. Install and use an updated SDK, or target a lower version using --with-windows-version. See https://developer.mozilla.org/En/Windows_SDK_versions for more details on fixing this.])
AC_MSG_ERROR([You are targeting Windows version 0x$MOZ_WINSDK_TARGETVER, but your SDK only supports up to version $MOZ_WINSDK_MAXVER. Install and use an updated SDK, or target a lower version using --with-windows-version. Alternatively, try running the Windows SDK Configuration Tool and selecting a newer SDK. See https://developer.mozilla.org/En/Windows_SDK_versions for more details on fixing this.])
fi
AC_DEFINE_UNQUOTED(MOZ_WINSDK_TARGETVER,0x$MOZ_WINSDK_TARGETVER)

View File

@ -84,7 +84,7 @@ class Element : public nsIContent
{
public:
#ifdef MOZILLA_INTERNAL_API
Element(nsINodeInfo* aNodeInfo) : nsIContent(aNodeInfo) {}
Element(already_AddRefed<nsINodeInfo> aNodeInfo) : nsIContent(aNodeInfo) {}
#endif // MOZILLA_INTERNAL_API
};

View File

@ -108,6 +108,7 @@ XPIDLSRCS = \
nsIDOMParser.idl \
nsIDOMSerializer.idl \
nsISelection2.idl \
nsISelection3.idl \
nsISelectionController.idl \
nsISelectionDisplay.idl \
nsISelectionListener.idl \

View File

@ -66,10 +66,10 @@ class nsGenericHTMLElement;
nsresult
NS_NewElement(nsIContent** aResult, PRInt32 aElementType,
nsINodeInfo* aNodeInfo, PRUint32 aFromParser);
already_AddRefed<nsINodeInfo> aNodeInfo, PRUint32 aFromParser);
nsresult
NS_NewXMLElement(nsIContent** aResult, nsINodeInfo* aNodeInfo);
NS_NewXMLElement(nsIContent** aResult, already_AddRefed<nsINodeInfo> aNodeInfo);
/**
* aNodeInfoManager must not be null.
@ -108,36 +108,39 @@ NS_NewXMLCDATASection(nsIContent** aInstancePtrResult,
nsNodeInfoManager *aNodeInfoManager);
nsresult
NS_NewHTMLElement(nsIContent** aResult, nsINodeInfo *aNodeInfo,
NS_NewHTMLElement(nsIContent** aResult, already_AddRefed<nsINodeInfo> aNodeInfo,
PRUint32 aFromParser);
// First argument should be nsHTMLTag, but that adds dependency to parser
// for a bunch of files.
already_AddRefed<nsGenericHTMLElement>
CreateHTMLElement(PRUint32 aNodeType, nsINodeInfo *aNodeInfo,
CreateHTMLElement(PRUint32 aNodeType, already_AddRefed<nsINodeInfo> aNodeInfo,
PRUint32 aFromParser);
#ifdef MOZ_MATHML
nsresult
NS_NewMathMLElement(nsIContent** aResult, nsINodeInfo* aNodeInfo);
NS_NewMathMLElement(nsIContent** aResult,
already_AddRefed<nsINodeInfo> aNodeInfo);
#endif
#ifdef MOZ_XUL
nsresult
NS_NewXULElement(nsIContent** aResult, nsINodeInfo* aNodeInfo);
NS_NewXULElement(nsIContent** aResult, already_AddRefed<nsINodeInfo> aNodeInfo);
#endif
#ifdef MOZ_SVG
nsresult
NS_NewSVGElement(nsIContent** aResult, nsINodeInfo* aNodeInfo,
NS_NewSVGElement(nsIContent** aResult, already_AddRefed<nsINodeInfo> aNodeInfo,
PRUint32 aFromParser);
#endif
nsresult
NS_NewGenConImageContent(nsIContent** aResult, nsINodeInfo* aNodeInfo,
NS_NewGenConImageContent(nsIContent** aResult,
already_AddRefed<nsINodeInfo> aNodeInfo,
imgIRequest* aImageRequest);
nsresult
NS_NewXMLEventsElement(nsIContent** aResult, nsINodeInfo* aNodeInfo);
NS_NewXMLEventsElement(nsIContent** aResult,
already_AddRefed<nsINodeInfo> aNodeInfo);
#endif // nsContentCreatorFunctions_h__

View File

@ -1573,17 +1573,33 @@ public:
// If non-null aHolder will keep the jsval alive
// while there's a ref to it
nsIXPConnectJSObjectHolder** aHolder = nsnull,
PRBool aAllowWrapping = PR_FALSE);
PRBool aAllowWrapping = PR_FALSE)
{
return WrapNative(cx, scope, native, nsnull, aIID, vp, aHolder,
aAllowWrapping);
}
// Same as the WrapNative above, but use this one if aIID is nsISupports' IID.
static nsresult WrapNative(JSContext *cx, JSObject *scope,
nsISupports *native, jsval *vp,
nsISupports *native, jsval *vp,
// If non-null aHolder will keep the jsval alive
// while there's a ref to it
nsIXPConnectJSObjectHolder** aHolder = nsnull,
PRBool aAllowWrapping = PR_FALSE)
{
return WrapNative(cx, scope, native, nsnull, vp, aHolder, aAllowWrapping);
return WrapNative(cx, scope, native, nsnull, nsnull, vp, aHolder,
aAllowWrapping);
}
static nsresult WrapNative(JSContext *cx, JSObject *scope,
nsISupports *native, nsWrapperCache *cache,
jsval *vp,
// If non-null aHolder will keep the jsval alive
// while there's a ref to it
nsIXPConnectJSObjectHolder** aHolder = nsnull,
PRBool aAllowWrapping = PR_FALSE)
{
return WrapNative(cx, scope, native, cache, nsnull, vp, aHolder,
aAllowWrapping);
}
static void StripNullChars(const nsAString& aInStr, nsAString& aOutStr);
@ -1674,6 +1690,12 @@ private:
static PRBool CanCallerAccess(nsIPrincipal* aSubjectPrincipal,
nsIPrincipal* aPrincipal);
static nsresult WrapNative(JSContext *cx, JSObject *scope,
nsISupports *native, nsWrapperCache *cache,
const nsIID* aIID, jsval *vp,
nsIXPConnectJSObjectHolder** aHolder,
PRBool aAllowWrapping);
static nsIDOMScriptObjectFactory *sDOMScriptObjectFactory;
static nsIXPConnect *sXPConnect;

View File

@ -76,7 +76,7 @@ public:
protected:
#ifdef MOZILLA_INTERNAL_API
nsIAttribute(nsDOMAttributeMap *aAttrMap, nsINodeInfo *aNodeInfo)
nsIAttribute(nsDOMAttributeMap *aAttrMap, already_AddRefed<nsINodeInfo> aNodeInfo)
: nsINode(aNodeInfo), mAttrMap(aAttrMap)
{
}

View File

@ -71,8 +71,8 @@ enum nsLinkState {
// IID for the nsIContent interface
#define NS_ICONTENT_IID \
{ 0x1450010b, 0xcdca, 0x451c, \
{ 0xba, 0xdc, 0x07, 0x90, 0x89, 0x7b, 0xce, 0xb8 } }
{ 0xdd254504, 0xe273, 0x4923, \
{ 0x9e, 0xc1, 0xd8, 0x42, 0x1a, 0x66, 0x35, 0xf1 } }
/**
* A node of content in a document's content model. This interface
@ -84,11 +84,11 @@ public:
// If you're using the external API, the only thing you can know about
// nsIContent is that it exists with an IID
nsIContent(nsINodeInfo *aNodeInfo)
nsIContent(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsINode(aNodeInfo),
mPrimaryFrame(nsnull)
{
NS_ASSERTION(aNodeInfo,
NS_ASSERTION(mNodeInfo,
"No nsINodeInfo passed to nsIContent, PREPARE TO CRASH!!!");
}
#endif // MOZILLA_INTERNAL_API
@ -928,6 +928,19 @@ public:
virtual PRBool IsEqualNode(nsINode* aOther);
/**
* If this content has independent selection, e.g., if this is input field
* or textarea, this return TRUE. Otherwise, false.
*/
PRBool HasIndependentSelection();
/**
* If the content is a part of HTML editor, this returns editing
* host content. When the content is in designMode, this returns its body
* element. Also, when the content isn't editable, this returns null.
*/
nsIContent* GetEditingHost();
protected:
/**
* Hook for implementing GetID. This is guaranteed to only be

View File

@ -118,8 +118,8 @@ class Element;
#define NS_IDOCUMENT_IID \
{ 0x19df0b2c, 0xf89a, 0x4c83, \
{ 0x82, 0x29, 0x3a, 0xe0, 0xb6, 0x42, 0x71, 0x9c } }
{ 0xda512fdc, 0x2d83, 0x44b0, \
{ 0xb0, 0x99, 0x00, 0xc6, 0xbb, 0x72, 0x39, 0xed } }
// Flag for AddStyleSheet().
#define NS_STYLESHEET_FROM_CATALOG (1 << 0)
@ -830,7 +830,7 @@ public:
* for that document (currently XHTML in HTML documents and XUL in XUL
* documents), otherwise we use the type specified by the namespace ID.
*/
virtual nsresult CreateElem(nsIAtom *aName, nsIAtom *aPrefix,
virtual nsresult CreateElem(const nsAString& aName, nsIAtom *aPrefix,
PRInt32 aNamespaceID,
PRBool aDocumentDefaultType,
nsIContent** aResult) = 0;

View File

@ -45,8 +45,8 @@ class nsIDocument;
class nsINode;
#define NS_IMUTATION_OBSERVER_IID \
{0x365d600b, 0x868a, 0x452a, \
{0x8d, 0xe8, 0xf4, 0x6f, 0xad, 0x8f, 0xee, 0x53 } }
{ 0x85eea794, 0xed8e, 0x4e1b, \
{ 0xa1, 0x28, 0xd0, 0x93, 0x00, 0xae, 0x51, 0xaa } }
/**
* Information details about a characterdata change. Basically, we
@ -117,6 +117,12 @@ public:
* @param aDocument The owner-document of aContent. Can be null.
* @param aContent The piece of content that changed. Is never null.
* @param aInfo The structure with information details about the change.
*
* @note Callers of this method might not hold a strong reference to the
* observer. The observer is responsible for making sure it stays
* alive for the duration of the call as needed. The observer may
* assume that this call will happen when there are script blockers on
* the stack.
*/
virtual void CharacterDataWillChange(nsIDocument *aDocument,
nsIContent* aContent,
@ -133,6 +139,12 @@ public:
* @param aDocument The owner-document of aContent. Can be null.
* @param aContent The piece of content that changed. Is never null.
* @param aInfo The structure with information details about the change.
*
* @note Callers of this method might not hold a strong reference to the
* observer. The observer is responsible for making sure it stays
* alive for the duration of the call as needed. The observer may
* assume that this call will happen when there are script blockers on
* the stack.
*/
virtual void CharacterDataChanged(nsIDocument *aDocument,
nsIContent* aContent,
@ -152,6 +164,12 @@ public:
* @param aModType Whether or not the attribute will be added, changed, or
* removed. The constants are defined in
* nsIDOMMutationEvent.h.
*
* @note Callers of this method might not hold a strong reference to the
* observer. The observer is responsible for making sure it stays
* alive for the duration of the call as needed. The observer may
* assume that this call will happen when there are script blockers on
* the stack.
*/
virtual void AttributeWillChange(nsIDocument* aDocument,
nsIContent* aContent,
@ -169,6 +187,12 @@ public:
* @param aModType Whether or not the attribute was added, changed, or
* removed. The constants are defined in
* nsIDOMMutationEvent.h.
*
* @note Callers of this method might not hold a strong reference to the
* observer. The observer is responsible for making sure it stays
* alive for the duration of the call as needed. The observer may
* assume that this call will happen when there are script blockers on
* the stack.
*/
virtual void AttributeChanged(nsIDocument* aDocument,
nsIContent* aContent,
@ -186,6 +210,12 @@ public:
* @param aFirstNewContent the node at aIndexInContainer in aContainer.
* @param aNewIndexInContainer the index in the container of the first
* new child
*
* @note Callers of this method might not hold a strong reference to the
* observer. The observer is responsible for making sure it stays
* alive for the duration of the call as needed. The observer may
* assume that this call will happen when there are script blockers on
* the stack.
*/
virtual void ContentAppended(nsIDocument *aDocument,
nsIContent* aContainer,
@ -204,6 +234,12 @@ public:
* aDocument
* @param aChild The newly inserted child.
* @param aIndexInContainer The index in the container of the new child.
*
* @note Callers of this method might not hold a strong reference to the
* observer. The observer is responsible for making sure it stays
* alive for the duration of the call as needed. The observer may
* assume that this call will happen when there are script blockers on
* the stack.
*/
virtual void ContentInserted(nsIDocument *aDocument,
nsIContent* aContainer,
@ -223,11 +259,20 @@ public:
* @param aChild The child that was removed.
* @param aIndexInContainer The index in the container which the child used
* to have.
* @param aPreviousSibling The previous sibling to the child that was removed.
* Can be null if there was no previous sibling.
*
* @note Callers of this method might not hold a strong reference to the
* observer. The observer is responsible for making sure it stays
* alive for the duration of the call as needed. The observer may
* assume that this call will happen when there are script blockers on
* the stack.
*/
virtual void ContentRemoved(nsIDocument *aDocument,
nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer) = 0;
PRInt32 aIndexInContainer,
nsIContent* aPreviousSibling) = 0;
/**
* The node is in the process of being destroyed. Calling QI on the node is
@ -241,6 +286,10 @@ public:
* removed from the observed node, use the ContentRemoved notification.
*
* @param aNode The node being destroyed.
*
* @note Callers of this method might not hold a strong reference to
* the observer. The observer is responsible for making sure it
* stays alive for the duration of the call as needed.
*/
virtual void NodeWillBeDestroyed(const nsINode *aNode) = 0;
@ -254,6 +303,10 @@ public:
* parent chain changed.
*
* @param aContent The piece of content that had its parent changed.
*
* @note Callers of this method might not hold a strong reference to
* the observer. The observer is responsible for making sure it
* stays alive for the duration of the call as needed.
*/
virtual void ParentChainChanged(nsIContent *aContent) = 0;
@ -301,7 +354,8 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIMutationObserver, NS_IMUTATION_OBSERVER_IID)
virtual void ContentRemoved(nsIDocument* aDocument, \
nsIContent* aContainer, \
nsIContent* aChild, \
PRInt32 aIndexInContainer);
PRInt32 aIndexInContainer, \
nsIContent* aPreviousSibling);
#define NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED \
virtual void NodeWillBeDestroyed(const nsINode* aNode);
@ -373,7 +427,8 @@ void \
_class::ContentRemoved(nsIDocument* aDocument, \
nsIContent* aContainer, \
nsIContent* aChild, \
PRInt32 aIndexInContainer) \
PRInt32 aIndexInContainer, \
nsIContent* aPreviousSibling) \
{ \
} \
void \

View File

@ -69,6 +69,7 @@ class nsIEditor;
class nsIVariant;
class nsIDOMUserDataHandler;
class nsAttrAndChildArray;
class nsXPCClassInfo;
namespace mozilla {
namespace dom {
@ -293,8 +294,8 @@ private:
// IID for the nsINode interface
#define NS_INODE_IID \
{ 0x58695b2f, 0x39bd, 0x434d, \
{ 0xa2, 0x0b, 0xde, 0xd3, 0xa8, 0xa0, 0xb6, 0x95 } }
{ 0x2a8dc794, 0x9178, 0x400e, \
{ 0x81, 0xff, 0x55, 0x30, 0x30, 0xb6, 0x74, 0x3b } }
/**
* An internal interface that abstracts some DOMNode-related parts that both
@ -313,15 +314,16 @@ public:
friend class nsAttrAndChildArray;
#ifdef MOZILLA_INTERNAL_API
nsINode(nsINodeInfo* aNodeInfo)
: mNodeInfo(aNodeInfo),
mParentPtrBits(0),
mFlagsOrSlots(NODE_DOESNT_HAVE_SLOTS),
mNextSibling(nsnull),
mPreviousSibling(nsnull),
mFirstChild(nsnull)
nsINode(already_AddRefed<nsINodeInfo> aNodeInfo)
: mNodeInfo(aNodeInfo),
mParentPtrBits(0),
mFlagsOrSlots(NODE_DOESNT_HAVE_SLOTS),
mNextSibling(nsnull),
mPreviousSibling(nsnull),
mFirstChild(nsnull)
{
}
#endif
virtual ~nsINode();
@ -1145,6 +1147,8 @@ public:
NS_NOTREACHED("How did we get here?");
}
// Optimized way to get classinfo. May return null.
virtual nsXPCClassInfo* GetClassInfo() = 0;
protected:
// Override this function to create a custom slots class.

View File

@ -310,14 +310,26 @@ protected:
class nsNodeInfoInner
{
public:
nsNodeInfoInner()
: mName(nsnull), mPrefix(nsnull), mNamespaceID(kNameSpaceID_Unknown),
mNameString(nsnull)
{
}
nsNodeInfoInner(nsIAtom *aName, nsIAtom *aPrefix, PRInt32 aNamespaceID)
: mName(aName), mPrefix(aPrefix), mNamespaceID(aNamespaceID)
: mName(aName), mPrefix(aPrefix), mNamespaceID(aNamespaceID),
mNameString(nsnull)
{
}
nsNodeInfoInner(const nsAString& aTmpName, nsIAtom *aPrefix, PRInt32 aNamespaceID)
: mName(nsnull), mPrefix(aPrefix), mNamespaceID(aNamespaceID),
mNameString(&aTmpName)
{
}
nsIAtom* mName;
nsIAtom* mPrefix;
PRInt32 mNamespaceID;
const nsAString* mNameString;
};
// nsNodeInfoManager needs to pass mInner to the hash table.

View File

@ -46,10 +46,10 @@ interface nsIDOMRange;
* Interface for manipulating and querying the current selected range
* of nodes within the document.
*
* @version 1.1
* @version 1.0
*/
[scriptable, uuid(24bb8c1c-407c-4a97-b652-af767d847716)]
[scriptable, uuid(B2C7ED59-8634-4352-9E37-5484C8B6E4E1)]
interface nsISelection : nsISupports
{
/**
@ -154,27 +154,6 @@ interface nsISelection : nsISupports
*/
void deleteFromDocument();
/**
* Modifies the selection. Note that the parameters are case-insensitive.
*
* @param alter can be one of { "move", "extend" }
* - "move" collapses the selection to the end of the selection and
* applies the movement direction/granularity to the collapsed
* selection.
* - "extend" leaves the start of the selection unchanged, and applies
* movement direction/granularity to the end of the selection.
* @param direction can be one of { "forward", "backward", "left", "right" }
* @param granularity can be one of { "character", "word",
* "line", "lineboundary" }
*
* @returns NS_ERROR_NOT_IMPLEMENTED if the granularity is "sentence",
* "sentenceboundary", "paragraph", "paragraphboundary", or
* "documentboundary". Returns NS_ERROR_INVALID_ARG if alter, direction,
* or granularity has an unrecognized value.
*/
void modify(in DOMString alter, in DOMString direction,
in DOMString granularity);
/**
* Modifies the cursor Bidi level after a change in keyboard direction
* @param langRTL is PR_TRUE if the new language is right-to-left or

View File

@ -0,0 +1,65 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** 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 Selection code.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Justin Lebar <justin.lebar@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of 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 ***** */
#include "nsISupports.idl"
[scriptable, uuid(94ac0cb4-95b4-11df-8e13-0026b9792740)]
interface nsISelection3 : nsISupports
{
/**
* Modifies the selection. Note that the parameters are case-insensitive.
*
* @param alter can be one of { "move", "extend" }
* - "move" collapses the selection to the end of the selection and
* applies the movement direction/granularity to the collapsed
* selection.
* - "extend" leaves the start of the selection unchanged, and applies
* movement direction/granularity to the end of the selection.
* @param direction can be one of { "forward", "backward", "left", "right" }
* @param granularity can be one of { "character", "word",
* "line", "lineboundary" }
*
* @returns NS_ERROR_NOT_IMPLEMENTED if the granularity is "sentence",
* "sentenceboundary", "paragraph", "paragraphboundary", or
* "documentboundary". Returns NS_ERROR_INVALID_ARG if alter, direction,
* or granularity has an unrecognized value.
*/
void modify(in DOMString alter, in DOMString direction,
in DOMString granularity);
};

View File

@ -48,7 +48,7 @@ class nsCommentNode : public nsGenericDOMDataNode,
public nsIDOMComment
{
public:
nsCommentNode(nsINodeInfo *aNodeInfo);
nsCommentNode(already_AddRefed<nsINodeInfo> aNodeInfo);
virtual ~nsCommentNode();
// nsISupports
@ -66,6 +66,7 @@ public:
// nsIContent
virtual PRBool IsNodeOfType(PRUint32 aFlags) const;
virtual nsXPCClassInfo* GetClassInfo();
#ifdef DEBUG
virtual void List(FILE* out, PRInt32 aIndent) const;
virtual void DumpContent(FILE* out = stdout, PRInt32 aIndent = 0,
@ -87,7 +88,7 @@ NS_NewCommentNode(nsIContent** aInstancePtrResult,
nsCOMPtr<nsINodeInfo> ni = aNodeInfoManager->GetCommentNodeInfo();
NS_ENSURE_TRUE(ni, NS_ERROR_OUT_OF_MEMORY);
nsCommentNode *instance = new nsCommentNode(ni);
nsCommentNode *instance = new nsCommentNode(ni.forget());
if (!instance) {
return NS_ERROR_OUT_OF_MEMORY;
}
@ -97,7 +98,7 @@ NS_NewCommentNode(nsIContent** aInstancePtrResult,
return NS_OK;
}
nsCommentNode::nsCommentNode(nsINodeInfo *aNodeInfo)
nsCommentNode::nsCommentNode(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsGenericDOMDataNode(aNodeInfo)
{
}
@ -106,7 +107,7 @@ nsCommentNode::~nsCommentNode()
{
}
DOMCI_DATA(Comment, nsCommentNode)
DOMCI_NODE_DATA(Comment, nsCommentNode)
// QueryInterface implementation for nsCommentNode
NS_INTERFACE_TABLE_HEAD(nsCommentNode)
@ -155,7 +156,8 @@ nsCommentNode::GetNodeType(PRUint16* aNodeType)
nsGenericDOMDataNode*
nsCommentNode::CloneDataNode(nsINodeInfo *aNodeInfo, PRBool aCloneText) const
{
nsCommentNode *it = new nsCommentNode(aNodeInfo);
nsCOMPtr<nsINodeInfo> ni = aNodeInfo;
nsCommentNode *it = new nsCommentNode(ni.forget());
if (it && aCloneText) {
it->mText = mText;
}

View File

@ -586,7 +586,7 @@ nsContentList::GetNodeAt(PRUint32 aIndex)
return Item(aIndex, PR_TRUE);
}
nsISupports*
nsIContent*
nsContentList::GetNodeAt(PRUint32 aIndex, nsresult* aResult)
{
*aResult = NS_OK;
@ -594,10 +594,14 @@ nsContentList::GetNodeAt(PRUint32 aIndex, nsresult* aResult)
}
nsISupports*
nsContentList::GetNamedItem(const nsAString& aName, nsresult* aResult)
nsContentList::GetNamedItem(const nsAString& aName, nsWrapperCache **aCache,
nsresult* aResult)
{
*aResult = NS_OK;
return NamedItem(aName, PR_TRUE);
nsIContent *item;
*aCache = item = NamedItem(aName, PR_TRUE);
return item;
}
void
@ -750,7 +754,8 @@ void
nsContentList::ContentRemoved(nsIDocument *aDocument,
nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer)
PRInt32 aIndexInContainer,
nsIContent* aPreviousSibling)
{
// Note that aContainer can be null here if we are removing from
// the document itself; any attempted optimizations to this method

View File

@ -269,8 +269,10 @@ public:
virtual PRInt32 IndexOf(nsIContent* aContent);
// nsIHTMLCollection
virtual nsISupports* GetNodeAt(PRUint32 aIndex, nsresult* aResult);
virtual nsISupports* GetNamedItem(const nsAString& aName, nsresult* aResult);
virtual nsIContent* GetNodeAt(PRUint32 aIndex, nsresult* aResult);
virtual nsISupports* GetNamedItem(const nsAString& aName,
nsWrapperCache** aCache,
nsresult* aResult);
// nsContentList public methods
NS_HIDDEN_(nsINode*) GetParentObject() { return mRootNode; }

View File

@ -1600,12 +1600,10 @@ nsContentSink::DropParserAndPerfHint(void)
// Do this hack to make sure that the parser
// doesn't get destroyed, accidently, before
// the circularity, between sink & parser, is
// actually borken.
nsCOMPtr<nsIParser> kungFuDeathGrip(mParser);
// actually broken.
// Drop our reference to the parser to get rid of a circular
// reference.
mParser = nsnull;
nsCOMPtr<nsIParser> kungFuDeathGrip(mParser.forget());
if (mDynamicLowerValue) {
// Reset the performance hint which was set to FALSE

View File

@ -3793,15 +3793,16 @@ nsContentUtils::CreateContextualFragment(nsINode* aContextNode,
}
}
nsCOMPtr<nsIContent> fragment = do_QueryInterface(frag);
if (contextAsContent) {
parser->ParseFragment(aFragment,
frag,
fragment,
contextAsContent->Tag(),
contextAsContent->GetNameSpaceID(),
(document->GetCompatibilityMode() == eCompatibility_NavQuirks));
} else {
parser->ParseFragment(aFragment,
frag,
fragment,
nsGkAtoms::body,
kNameSpaceID_XHTML,
(document->GetCompatibilityMode() == eCompatibility_NavQuirks));
@ -5352,7 +5353,7 @@ nsContentUtils::DispatchXULCommand(nsIContent* aTarget,
// static
nsresult
nsContentUtils::WrapNative(JSContext *cx, JSObject *scope, nsISupports *native,
const nsIID* aIID, jsval *vp,
nsWrapperCache *cache, const nsIID* aIID, jsval *vp,
nsIXPConnectJSObjectHolder **aHolder,
PRBool aAllowWrapping)
{
@ -5389,7 +5390,7 @@ nsContentUtils::WrapNative(JSContext *cx, JSObject *scope, nsISupports *native,
rv = sThreadJSContextStack->Push(cx);
}
if (NS_SUCCEEDED(rv)) {
rv = sXPConnect->WrapNativeToJSVal(cx, scope, native, aIID,
rv = sXPConnect->WrapNativeToJSVal(cx, scope, native, cache, aIID,
aAllowWrapping, vp, aHolder);
if (push) {
sThreadJSContextStack->Pop(nsnull);
@ -5966,6 +5967,7 @@ AllocClassMatchingInfo(nsINode* aRootNode,
}
info->mCaseTreatment =
aRootNode->GetOwnerDoc() &&
aRootNode->GetOwnerDoc()->GetCompatibilityMode() == eCompatibility_NavQuirks ?
eIgnoreCase : eCaseMatters;
return info;

View File

@ -64,7 +64,7 @@
PRBool nsDOMAttribute::sInitialized;
nsDOMAttribute::nsDOMAttribute(nsDOMAttributeMap *aAttrMap,
nsINodeInfo *aNodeInfo,
already_AddRefed<nsINodeInfo> aNodeInfo,
const nsAString &aValue)
: nsIAttribute(aAttrMap, aNodeInfo), mValue(aValue), mChild(nsnull)
{
@ -124,7 +124,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMAttribute)
NS_IMPL_CYCLE_COLLECTION_UNLINK_USERDATA
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
DOMCI_DATA(Attr, nsDOMAttribute)
DOMCI_NODE_DATA(Attr, nsDOMAttribute)
// QueryInterface implementation for nsDOMAttribute
NS_INTERFACE_TABLE_HEAD(nsDOMAttribute)
@ -415,7 +415,8 @@ nsDOMAttribute::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const
nsAutoString value;
const_cast<nsDOMAttribute*>(this)->GetValue(value);
*aResult = new nsDOMAttribute(nsnull, aNodeInfo, value);
nsCOMPtr<nsINodeInfo> ni = aNodeInfo;
*aResult = new nsDOMAttribute(nsnull, ni.forget(), value);
if (!*aResult) {
return NS_ERROR_OUT_OF_MEMORY;
}
@ -764,6 +765,8 @@ nsDOMAttribute::AttributeChanged(nsIDocument* aDocument,
return;
}
nsCOMPtr<nsIMutationObserver> kungFuDeathGrip(this);
// Just blow away our mChild and recreate it if needed
if (mChild) {
static_cast<nsTextNode*>(mChild)->UnbindFromAttribute();

View File

@ -63,7 +63,8 @@ class nsDOMAttribute : public nsIAttribute,
public nsStubMutationObserver
{
public:
nsDOMAttribute(nsDOMAttributeMap* aAttrMap, nsINodeInfo *aNodeInfo,
nsDOMAttribute(nsDOMAttributeMap* aAttrMap,
already_AddRefed<nsINodeInfo> aNodeInfo,
const nsAString& aValue);
virtual ~nsDOMAttribute();
@ -122,6 +123,7 @@ public:
NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
virtual nsXPCClassInfo* GetClassInfo();
protected:
virtual mozilla::dom::Element* GetNameSpaceElement()
{

View File

@ -179,7 +179,9 @@ nsDOMAttributeMap::RemoveAttribute(nsINodeInfo* aNodeInfo, nsIDOMNode** aReturn)
// As we are removing the attribute we need to set the current value in
// the attribute node.
mContent->GetAttr(aNodeInfo->NamespaceID(), aNodeInfo->NameAtom(), value);
nsCOMPtr<nsIDOMNode> newAttr = new nsDOMAttribute(nsnull, aNodeInfo, value);
nsCOMPtr<nsINodeInfo> ni = aNodeInfo;
nsCOMPtr<nsIDOMNode> newAttr =
new nsDOMAttribute(nsnull, ni.forget(), value);
if (!newAttr) {
return NS_ERROR_OUT_OF_MEMORY;
}
@ -207,8 +209,9 @@ nsDOMAttributeMap::GetAttribute(nsINodeInfo* aNodeInfo)
nsDOMAttribute* node = mAttributeCache.GetWeak(attr);
if (!node) {
nsCOMPtr<nsINodeInfo> ni = aNodeInfo;
nsRefPtr<nsDOMAttribute> newAttr =
new nsDOMAttribute(this, aNodeInfo, EmptyString());
new nsDOMAttribute(this, ni.forget(), EmptyString());
if (newAttr && mAttributeCache.Put(attr, newAttr)) {
node = newAttr;
}

View File

@ -89,7 +89,7 @@ NS_NewDOMDocumentType(nsIDOMDocumentType** aDocType,
kNameSpaceID_None);
NS_ENSURE_TRUE(ni, NS_ERROR_OUT_OF_MEMORY);
*aDocType = new nsDOMDocumentType(ni, aName, aEntities, aNotations,
*aDocType = new nsDOMDocumentType(ni.forget(), aName, aEntities, aNotations,
aPublicId, aSystemId, aInternalSubset);
if (!*aDocType) {
return NS_ERROR_OUT_OF_MEMORY;
@ -100,7 +100,7 @@ NS_NewDOMDocumentType(nsIDOMDocumentType** aDocType,
return NS_OK;
}
nsDOMDocumentType::nsDOMDocumentType(nsINodeInfo *aNodeInfo,
nsDOMDocumentType::nsDOMDocumentType(already_AddRefed<nsINodeInfo> aNodeInfo,
nsIAtom *aName,
nsIDOMNamedNodeMap *aEntities,
nsIDOMNamedNodeMap *aNotations,
@ -121,7 +121,7 @@ nsDOMDocumentType::~nsDOMDocumentType()
{
}
DOMCI_DATA(DocumentType, nsDOMDocumentType)
DOMCI_NODE_DATA(DocumentType, nsDOMDocumentType)
// QueryInterface implementation for nsDOMDocumentType
NS_INTERFACE_TABLE_HEAD(nsDOMDocumentType)
@ -236,7 +236,8 @@ nsDOMDocumentType::GetNodeType(PRUint16* aNodeType)
nsGenericDOMDataNode*
nsDOMDocumentType::CloneDataNode(nsINodeInfo *aNodeInfo, PRBool aCloneText) const
{
return new nsDOMDocumentType(aNodeInfo, mName, mEntities, mNotations,
nsCOMPtr<nsINodeInfo> ni = aNodeInfo;
return new nsDOMDocumentType(ni.forget(), mName, mEntities, mNotations,
mPublicId, mSystemId, mInternalSubset);
}

View File

@ -57,7 +57,7 @@ class nsDOMDocumentType : public nsGenericDOMDataNode,
public nsIDOMDocumentType
{
public:
nsDOMDocumentType(nsINodeInfo* aNodeInfo,
nsDOMDocumentType(already_AddRefed<nsINodeInfo> aNodeInfo,
nsIAtom *aName,
nsIDOMNamedNodeMap *aEntities,
nsIDOMNamedNodeMap *aNotations,
@ -83,7 +83,7 @@ public:
nsIContent *aBindingParent,
PRBool aCompileEventHandlers);
virtual nsXPCClassInfo* GetClassInfo();
protected:
nsCOMPtr<nsIAtom> mName;
nsCOMPtr<nsIDOMNamedNodeMap> mEntities;

View File

@ -1907,11 +1907,13 @@ nsDocument::ResetToURI(nsIURI *aURI, nsILoadGroup *aLoadGroup,
for (PRInt32 i = PRInt32(count) - 1; i >= 0; i--) {
nsCOMPtr<nsIContent> content = mChildren.ChildAt(i);
nsIContent* previousSibling = content->GetPreviousSibling();
if (nsINode::GetFirstChild() == content) {
mFirstChild = content->GetNextSibling();
}
mChildren.RemoveChildAt(i);
nsNodeUtils::ContentRemoved(this, content, i);
nsNodeUtils::ContentRemoved(this, content, i, previousSibling);
content->UnbindFromTree();
}
}
@ -2162,9 +2164,79 @@ nsDocument::StartDocumentLoad(const char* aCommand, nsIChannel* aChannel,
mChannel = aChannel;
nsresult rv = InitCSP();
nsresult rv = CheckFrameOptions();
NS_ENSURE_SUCCESS(rv, rv);
rv = InitCSP();
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
// Check if X-Frame-Options permits this document to be loaded as a subdocument.
nsresult nsDocument::CheckFrameOptions()
{
nsAutoString xfoHeaderValue;
this->GetHeaderData(nsGkAtoms::headerXFO, xfoHeaderValue);
// return early if header does not have one of the two values with meaning
if (!xfoHeaderValue.LowerCaseEqualsLiteral("deny") &&
!xfoHeaderValue.LowerCaseEqualsLiteral("sameorigin"))
return NS_OK;
nsCOMPtr<nsIDocShell> docShell = do_QueryReferent(mDocumentContainer);
if (docShell) {
PRBool framingAllowed = true;
// We need to check the location of this window and the location of the top
// window, if we're not the top. X-F-O: SAMEORIGIN requires that the
// document must be same-origin with top window. X-F-O: DENY requires that
// the document must never be framed.
nsCOMPtr<nsIDOMWindow> thisWindow = do_GetInterface(docShell);
nsCOMPtr<nsIDOMWindow> topWindow;
thisWindow->GetTop(getter_AddRefs(topWindow));
// if the document is in the top window, it's not in a frame.
if (thisWindow == topWindow)
return NS_OK;
// If the value of the header is DENY, then the document
// should never be permitted to load as a subdocument.
if (xfoHeaderValue.LowerCaseEqualsLiteral("deny")) {
framingAllowed = false;
}
else if (xfoHeaderValue.LowerCaseEqualsLiteral("sameorigin")) {
// If the X-Frame-Options value is SAMEORIGIN, then the top frame in the
// parent chain must be from the same origin as this document.
nsCOMPtr<nsIURI> uri = static_cast<nsIDocument*>(this)->GetDocumentURI();
nsCOMPtr<nsIDOMDocument> topDOMDoc;
topWindow->GetDocument(getter_AddRefs(topDOMDoc));
nsCOMPtr<nsIDocument> topDoc = do_QueryInterface(topDOMDoc);
if (topDoc) {
nsCOMPtr<nsIURI> topUri = topDoc->GetDocumentURI();
nsresult rv = nsContentUtils::GetSecurityManager()->
CheckSameOriginURI(uri, topUri, PR_TRUE);
if (NS_FAILED(rv)) {
framingAllowed = false;
}
}
}
if (!framingAllowed) {
// cancel the load and display about:blank
mChannel->Cancel(NS_BINDING_ABORTED);
nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(docShell));
if (webNav) {
webNav->LoadURI(NS_LITERAL_STRING("about:blank").get(),
0, nsnull, nsnull, nsnull);
}
return NS_ERROR_CONTENT_BLOCKED;
}
}
return NS_OK;
}
@ -4020,23 +4092,43 @@ nsDocument::CreateElement(const nsAString& aTagName,
nsIDOMElement** aReturn)
{
*aReturn = nsnull;
nsCOMPtr<nsIContent> content;
nsresult rv = CreateElement(aTagName, getter_AddRefs(content));
NS_ENSURE_SUCCESS(rv, rv);
return CallQueryInterface(content, aReturn);
}
PRBool IsLowercaseASCII(const nsAString& aValue)
{
PRInt32 len = aValue.Length();
for (PRInt32 i = 0; i < len; ++i) {
PRUnichar c = aValue[i];
if (!(0x0061 <= (c) && ((c) <= 0x007a))) {
return PR_FALSE;
}
}
return PR_TRUE;
}
nsresult
nsDocument::CreateElement(const nsAString& aTagName,
nsIContent** aReturn)
{
*aReturn = nsnull;
nsresult rv = nsContentUtils::CheckQName(aTagName, PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
NS_ASSERTION(!IsHTML(),
"nsDocument::CreateElement() called on document that is not "
"case sensitive. Fix caller, or fix "
"nsDocument::CreateElement()!");
PRBool needsLowercase = IsHTML() && !IsLowercaseASCII(aTagName);
nsAutoString lcTagName;
if (needsLowercase) {
ToLowerCase(aTagName, lcTagName);
}
nsCOMPtr<nsIAtom> name = do_GetAtom(aTagName);
nsCOMPtr<nsIContent> content;
rv = CreateElem(name, nsnull, GetDefaultNamespaceID(), PR_TRUE,
getter_AddRefs(content));
NS_ENSURE_SUCCESS(rv, rv);
return CallQueryInterface(content, aReturn);
rv = CreateElem(needsLowercase ? lcTagName : aTagName, nsnull,
IsHTML() ? kNameSpaceID_XHTML : GetDefaultNamespaceID(),
PR_TRUE, aReturn);
return rv;
}
NS_IMETHODIMP
@ -4054,8 +4146,8 @@ nsDocument::CreateElementNS(const nsAString& aNamespaceURI,
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIContent> content;
NS_NewElement(getter_AddRefs(content), nodeInfo->NamespaceID(), nodeInfo,
PR_FALSE);
PRInt32 ns = nodeInfo->NamespaceID();
NS_NewElement(getter_AddRefs(content), ns, nodeInfo.forget(), PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
return CallQueryInterface(content, aReturn);
@ -4065,17 +4157,20 @@ NS_IMETHODIMP
nsDocument::CreateTextNode(const nsAString& aData, nsIDOMText** aReturn)
{
*aReturn = nsnull;
nsCOMPtr<nsIContent> content;
nsresult rv = CreateTextNode(aData, getter_AddRefs(content));
NS_ENSURE_SUCCESS(rv, rv);
return CallQueryInterface(content, aReturn);
}
nsCOMPtr<nsIContent> text;
nsresult rv = NS_NewTextNode(getter_AddRefs(text), mNodeInfoManager);
nsresult
nsDocument::CreateTextNode(const nsAString& aData, nsIContent** aReturn)
{
nsresult rv = NS_NewTextNode(aReturn, mNodeInfoManager);
if (NS_SUCCEEDED(rv)) {
// Don't notify; this node is still being created.
text->SetText(aData, PR_FALSE);
rv = CallQueryInterface(text, aReturn);
(*aReturn)->SetText(aData, PR_FALSE);
}
return rv;
}
@ -4175,7 +4270,7 @@ nsDocument::CreateAttribute(const nsAString& aName,
getter_AddRefs(nodeInfo));
NS_ENSURE_SUCCESS(rv, rv);
attribute = new nsDOMAttribute(nsnull, nodeInfo, value);
attribute = new nsDOMAttribute(nsnull, nodeInfo.forget(), value);
NS_ENSURE_TRUE(attribute, NS_ERROR_OUT_OF_MEMORY);
return CallQueryInterface(attribute, aReturn);
@ -4197,7 +4292,8 @@ nsDocument::CreateAttributeNS(const nsAString & aNamespaceURI,
NS_ENSURE_SUCCESS(rv, rv);
nsAutoString value;
nsDOMAttribute* attribute = new nsDOMAttribute(nsnull, nodeInfo, value);
nsDOMAttribute* attribute =
new nsDOMAttribute(nsnull, nodeInfo.forget(), value);
NS_ENSURE_TRUE(attribute, NS_ERROR_OUT_OF_MEMORY);
return CallQueryInterface(attribute, aResult);
@ -4910,7 +5006,7 @@ nsDocument::SetTitle(const nsAString& aTitle)
kNameSpaceID_XHTML);
if (!titleInfo)
return NS_OK;
title = NS_NewHTMLTitleElement(titleInfo);
title = NS_NewHTMLTitleElement(titleInfo.forget());
if (!title)
return NS_OK;
}
@ -5468,13 +5564,9 @@ nsDocument::CloneNode(PRBool aDeep, nsIDOMNode** aReturn)
NS_IMETHODIMP
nsDocument::Normalize()
{
PRInt32 count = mChildren.ChildCount();
for (PRInt32 i = 0; i < count; ++i) {
for (PRInt32 i = 0; i < mChildren.ChildCount(); ++i) {
nsCOMPtr<nsIDOMNode> node(do_QueryInterface(mChildren.ChildAt(i)));
if (node) {
node->Normalize();
}
node->Normalize();
}
return NS_OK;
@ -6442,6 +6534,7 @@ nsDocument::RetrieveRelevantHeaders(nsIChannel *aChannel)
"x-dns-prefetch-control",
"x-content-security-policy",
"x-content-security-policy-report-only",
"x-frame-options",
// add more http headers if you need
// XXXbz don't add content-location support without reading bug
// 238654 and its dependencies/dups first.
@ -6510,7 +6603,7 @@ nsDocument::RetrieveRelevantHeaders(nsIChannel *aChannel)
}
nsresult
nsDocument::CreateElem(nsIAtom *aName, nsIAtom *aPrefix, PRInt32 aNamespaceID,
nsDocument::CreateElem(const nsAString& aName, nsIAtom *aPrefix, PRInt32 aNamespaceID,
PRBool aDocumentDefaultType, nsIContent **aResult)
{
#ifdef DEBUG
@ -6519,7 +6612,7 @@ nsDocument::CreateElem(nsIAtom *aName, nsIAtom *aPrefix, PRInt32 aNamespaceID,
aPrefix->ToString(qName);
qName.Append(':');
}
qName.Append(nsAtomString(aName));
qName.Append(aName);
// Note: "a:b:c" is a valid name in non-namespaces XML, and
// nsDocument::CreateElement can call us with such a name and no prefix,
@ -6536,10 +6629,11 @@ nsDocument::CreateElem(nsIAtom *aName, nsIAtom *aPrefix, PRInt32 aNamespaceID,
aNamespaceID;
nsCOMPtr<nsINodeInfo> nodeInfo;
nodeInfo = mNodeInfoManager->GetNodeInfo(aName, aPrefix, aNamespaceID);
mNodeInfoManager->GetNodeInfo(aName, aPrefix, aNamespaceID,
getter_AddRefs(nodeInfo));
NS_ENSURE_TRUE(nodeInfo, NS_ERROR_OUT_OF_MEMORY);
return NS_NewElement(aResult, elementType, nodeInfo, PR_FALSE);
return NS_NewElement(aResult, elementType, nodeInfo.forget(), PR_FALSE);
}
PRBool

View File

@ -834,11 +834,16 @@ public:
virtual nsresult AddXMLEventsContent(nsIContent * aXMLEventsElement);
virtual nsresult CreateElem(nsIAtom *aName, nsIAtom *aPrefix,
virtual nsresult CreateElem(const nsAString& aName, nsIAtom *aPrefix,
PRInt32 aNamespaceID,
PRBool aDocumentDefaultType,
nsIContent **aResult);
nsresult CreateElement(const nsAString& aTagName,
nsIContent** aReturn);
nsresult CreateTextNode(const nsAString& aData, nsIContent** aReturn);
virtual NS_HIDDEN_(nsresult) Sanitize();
virtual NS_HIDDEN_(void) EnumerateSubDocuments(nsSubDocEnumFunc aCallback,
@ -1019,9 +1024,9 @@ protected:
virtual nsPIDOMWindow *GetInnerWindowInternal();
virtual nsIScriptGlobalObject* GetScriptHandlingObjectInternal() const;
#define NS_DOCUMENT_NOTIFY_OBSERVERS(func_, params_) \
NS_OBSERVER_ARRAY_NOTIFY_OBSERVERS(mObservers, nsIDocumentObserver, \
func_, params_);
#define NS_DOCUMENT_NOTIFY_OBSERVERS(func_, params_) \
NS_OBSERVER_ARRAY_NOTIFY_XPCOM_OBSERVERS(mObservers, nsIDocumentObserver, \
func_, params_);
#ifdef DEBUG
void VerifyRootContentState();
@ -1143,6 +1148,7 @@ private:
void PostUnblockOnloadEvent();
void DoUnblockOnload();
nsresult CheckFrameOptions();
nsresult InitCSP();
/**

View File

@ -59,7 +59,7 @@ class nsDocumentFragment : public nsGenericElement,
public nsIDOMDocumentFragment
{
public:
nsDocumentFragment(nsINodeInfo *aNodeInfo);
nsDocumentFragment(already_AddRefed<nsINodeInfo> aNodeInfo);
virtual ~nsDocumentFragment();
// nsISupports
@ -154,6 +154,8 @@ public:
virtual PRBool IsNodeOfType(PRUint32 aFlags) const;
virtual nsXPCClassInfo* GetClassInfo();
virtual nsIAtom* DoGetID() const;
virtual nsIAtom *GetIDAttributeName() const;
@ -172,7 +174,7 @@ NS_NewDocumentFragment(nsIDOMDocumentFragment** aInstancePtrResult,
nsnull, kNameSpaceID_None);
NS_ENSURE_TRUE(nodeInfo, NS_ERROR_OUT_OF_MEMORY);
nsDocumentFragment *it = new nsDocumentFragment(nodeInfo);
nsDocumentFragment *it = new nsDocumentFragment(nodeInfo.forget());
if (!it) {
return NS_ERROR_OUT_OF_MEMORY;
}
@ -182,7 +184,7 @@ NS_NewDocumentFragment(nsIDOMDocumentFragment** aInstancePtrResult,
return NS_OK;
}
nsDocumentFragment::nsDocumentFragment(nsINodeInfo *aNodeInfo)
nsDocumentFragment::nsDocumentFragment(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsGenericElement(aNodeInfo)
{
UnsetFlags(NODE_IS_ELEMENT);
@ -210,7 +212,7 @@ nsDocumentFragment::GetIDAttributeName() const
return nsnull;
}
DOMCI_DATA(DocumentFragment, nsDocumentFragment)
DOMCI_NODE_DATA(DocumentFragment, nsDocumentFragment)
// QueryInterface implementation for nsDocumentFragment
NS_INTERFACE_TABLE_HEAD(nsDocumentFragment)

View File

@ -52,7 +52,7 @@ class nsGenConImageContent : public nsXMLElement,
public nsImageLoadingContent
{
public:
nsGenConImageContent(nsINodeInfo* aNodeInfo)
nsGenConImageContent(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsXMLElement(aNodeInfo)
{
}
@ -77,7 +77,7 @@ NS_IMPL_ISUPPORTS_INHERITED3(nsGenConImageContent, nsXMLElement,
nsIImageLoadingContent, imgIContainerObserver, imgIDecoderObserver)
nsresult
NS_NewGenConImageContent(nsIContent** aResult, nsINodeInfo* aNodeInfo,
NS_NewGenConImageContent(nsIContent** aResult, already_AddRefed<nsINodeInfo> aNodeInfo,
imgIRequest* aImageRequest)
{
NS_PRECONDITION(aImageRequest, "Must have request!");

View File

@ -67,7 +67,7 @@
#include "pldhash.h"
#include "prprf.h"
nsGenericDOMDataNode::nsGenericDOMDataNode(nsINodeInfo *aNodeInfo)
nsGenericDOMDataNode::nsGenericDOMDataNode(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsIContent(aNodeInfo)
{
}

View File

@ -86,7 +86,7 @@ class nsGenericDOMDataNode : public nsIContent
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
nsGenericDOMDataNode(nsINodeInfo *aNodeInfo);
nsGenericDOMDataNode(already_AddRefed<nsINodeInfo> aNodeInfo);
virtual ~nsGenericDOMDataNode();
// Implementation for nsIDOMNode
@ -366,7 +366,8 @@ private:
class nsGenericTextNode : public nsGenericDOMDataNode
{
public:
nsGenericTextNode(nsINodeInfo *aNodeInfo) : nsGenericDOMDataNode(aNodeInfo)
nsGenericTextNode(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsGenericDOMDataNode(aNodeInfo)
{
}

View File

@ -366,8 +366,7 @@ nsINode::GetSelectionRootContent(nsIPresShell* aPresShell)
return nsnull;
}
nsIFrame* frame = static_cast<nsIContent*>(this)->GetPrimaryFrame();
if (frame && frame->GetStateBits() & NS_FRAME_INDEPENDENT_SELECTION) {
if (static_cast<nsIContent*>(this)->HasIndependentSelection()) {
// This node should be a descendant of input/textarea editor.
nsIContent* content = GetTextEditorRootContent();
if (content)
@ -388,15 +387,9 @@ nsINode::GetSelectionRootContent(nsIPresShell* aPresShell)
editorRoot :
GetRootForContentSubtree(static_cast<nsIContent*>(this));
}
// If the current document is not editable, but current content is
// editable, we should assume that the child of the nearest non-editable
// ancestor is selection root.
nsIContent* content = static_cast<nsIContent*>(this);
for (nsIContent* parent = GetParent();
parent && parent->HasFlag(NODE_IS_EDITABLE);
parent = content->GetParent())
content = parent;
return content;
// If the document isn't editable but this is editable, this is in
// contenteditable. Use the editing host element for selection root.
return static_cast<nsIContent*>(this)->GetEditingHost();
}
}
@ -830,14 +823,13 @@ nsIContent::GetDesiredIMEState()
if (!IsEditableInternal()) {
return IME_STATUS_DISABLE;
}
nsIContent *editableAncestor = nsnull;
for (nsIContent* parent = GetParent();
parent && parent->HasFlag(NODE_IS_EDITABLE);
parent = parent->GetParent()) {
editableAncestor = parent;
}
// NOTE: The content for independent editors (e.g., input[type=text],
// textarea) must override this method, so, we don't need to worry about
// that here.
nsIContent *editableAncestor = GetEditingHost();
// This is in another editable content, use the result of it.
if (editableAncestor) {
if (editableAncestor && editableAncestor != this) {
return editableAncestor->GetDesiredIMEState();
}
nsIDocument* doc = GetCurrentDoc();
@ -865,6 +857,35 @@ nsIContent::GetDesiredIMEState()
return state;
}
PRBool
nsIContent::HasIndependentSelection()
{
nsIFrame* frame = GetPrimaryFrame();
return (frame && frame->GetStateBits() & NS_FRAME_INDEPENDENT_SELECTION);
}
nsIContent*
nsIContent::GetEditingHost()
{
// If this isn't editable, return NULL.
NS_ENSURE_TRUE(HasFlag(NODE_IS_EDITABLE), nsnull);
nsIDocument* doc = GetCurrentDoc();
NS_ENSURE_TRUE(doc, nsnull);
// If this is in designMode, we should return <body>
if (doc->HasFlag(NODE_IS_EDITABLE)) {
return doc->GetBodyElement();
}
nsIContent* content = this;
for (nsIContent* parent = GetParent();
parent && parent->HasFlag(NODE_IS_EDITABLE);
parent = content->GetParent()) {
content = parent;
}
return content;
}
nsresult
nsIContent::LookupNamespaceURI(const nsAString& aNamespacePrefix,
nsAString& aNamespaceURI) const
@ -2067,7 +2088,7 @@ nsGenericElement::nsDOMSlots::~nsDOMSlots()
}
}
nsGenericElement::nsGenericElement(nsINodeInfo *aNodeInfo)
nsGenericElement::nsGenericElement(already_AddRefed<nsINodeInfo> aNodeInfo)
: Element(aNodeInfo)
{
// Set the default scriptID to JS - but skip SetScriptTypeID as it
@ -3676,6 +3697,8 @@ nsINode::doRemoveChildAt(PRUint32 aIndex, PRBool aNotify,
}
}
nsIContent* previousSibling = aKid->GetPreviousSibling();
if (GetFirstChild() == aKid) {
mFirstChild = aKid->GetNextSibling();
}
@ -3683,7 +3706,7 @@ nsINode::doRemoveChildAt(PRUint32 aIndex, PRBool aNotify,
aChildArray.RemoveChildAt(aIndex);
if (aNotify) {
nsNodeUtils::ContentRemoved(this, aKid, aIndex);
nsNodeUtils::ContentRemoved(this, aKid, aIndex, previousSibling);
}
aKid->UnbindFromTree();

View File

@ -325,7 +325,7 @@ class nsNSElementTearoff;
class nsGenericElement : public mozilla::dom::Element
{
public:
nsGenericElement(nsINodeInfo *aNodeInfo);
nsGenericElement(already_AddRefed<nsINodeInfo> aNodeInfo);
virtual ~nsGenericElement();
friend class nsNSElementTearoff;
@ -1084,8 +1084,8 @@ nsresult \
_elementName::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const \
{ \
*aResult = nsnull; \
\
_elementName *it = new _elementName(aNodeInfo); \
nsCOMPtr<nsINodeInfo> ni = aNodeInfo; \
_elementName *it = new _elementName(ni.forget()); \
if (!it) { \
return NS_ERROR_OUT_OF_MEMORY; \
} \
@ -1104,8 +1104,8 @@ nsresult \
_elementName::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const \
{ \
*aResult = nsnull; \
\
_elementName *it = new _elementName(aNodeInfo); \
nsCOMPtr<nsINodeInfo> ni = aNodeInfo; \
_elementName *it = new _elementName(ni.forget()); \
if (!it) { \
return NS_ERROR_OUT_OF_MEMORY; \
} \
@ -1120,6 +1120,14 @@ _elementName::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const \
return rv; \
}
#define DOMCI_NODE_DATA(_interface, _class) \
DOMCI_DATA(_interface, _class) \
nsXPCClassInfo* _class::GetClassInfo() \
{ \
return static_cast<nsXPCClassInfo*>( \
NS_GetDOMClassInfoInstance(eDOMClassInfo_##_interface##_id)); \
}
/**
* Yet another tearoff class for nsGenericElement
* to implement additional interfaces

View File

@ -1025,6 +1025,7 @@ GK_ATOM(wrap, "wrap")
GK_ATOM(headerDNSPrefetchControl,"x-dns-prefetch-control")
GK_ATOM(headerCSP, "x-content-security-policy")
GK_ATOM(headerCSPReportOnly, "x-content-security-policy-report-only")
GK_ATOM(headerXFO, "x-frame-options")
GK_ATOM(xml, "xml")
GK_ATOM(xmlns, "xmlns")
GK_ATOM(xmp, "xmp")

View File

@ -60,7 +60,7 @@ class nsMappedAttributeElement : public nsMappedAttributeElementBase
protected:
nsMappedAttributeElement(nsINodeInfo *aNodeInfo)
nsMappedAttributeElement(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsMappedAttributeElementBase(aNodeInfo)
{}

View File

@ -227,7 +227,7 @@ NameSpaceManagerImpl::GetNameSpaceID(const nsAString& aURI)
nsresult
NS_NewElement(nsIContent** aResult, PRInt32 aElementType,
nsINodeInfo* aNodeInfo, PRUint32 aFromParser)
already_AddRefed<nsINodeInfo> aNodeInfo, PRUint32 aFromParser)
{
if (aElementType == kNameSpaceID_XHTML) {
return NS_NewHTMLElement(aResult, aNodeInfo, aFromParser);

View File

@ -53,6 +53,7 @@
#include "nsComponentManagerUtils.h"
#include "nsLayoutStatics.h"
#include "nsBindingManager.h"
#include "nsHashKeys.h"
#ifdef MOZ_LOGGING
// so we can get logging even in release builds
@ -72,8 +73,10 @@ nsNodeInfoManager::GetNodeInfoInnerHashValue(const void *key)
const nsINodeInfo::nsNodeInfoInner *node =
reinterpret_cast<const nsINodeInfo::nsNodeInfoInner *>(key);
// Is this an acceptable hash value?
return (PLHashNumber(NS_PTR_TO_INT32(node->mName)) & 0xffff) >> 8;
if (node->mName) {
return HashString(nsAtomString(node->mName));
}
return HashString(*(node->mNameString));
}
@ -87,9 +90,21 @@ nsNodeInfoManager::NodeInfoInnerKeyCompare(const void *key1, const void *key2)
const nsINodeInfo::nsNodeInfoInner *node2 =
reinterpret_cast<const nsINodeInfo::nsNodeInfoInner *>(key2);
return (node1->mName == node2->mName &&
node1->mPrefix == node2->mPrefix &&
node1->mNamespaceID == node2->mNamespaceID);
if (node1->mPrefix != node2->mPrefix ||
node1->mNamespaceID != node2->mNamespaceID) {
return 0;
}
if (node1->mName) {
if (node2->mName) {
return (node1->mName == node2->mName);
}
return (node1->mName->Equals(*(node2->mNameString)));
}
if (node2->mName) {
return (node2->mName->Equals(*(node1->mNameString)));
}
return (node1->mNameString->Equals(*(node2->mNameString)));
}
@ -229,9 +244,35 @@ nsresult
nsNodeInfoManager::GetNodeInfo(const nsAString& aName, nsIAtom *aPrefix,
PRInt32 aNamespaceID, nsINodeInfo** aNodeInfo)
{
nsCOMPtr<nsIAtom> name = do_GetAtom(aName);
*aNodeInfo = nsNodeInfoManager::GetNodeInfo(name, aPrefix, aNamespaceID).get();
return *aNodeInfo ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
NS_ASSERTION(!aName.IsEmpty(),
"Don't pass an empty string to GetNodeInfo, fix caller.");
nsINodeInfo::nsNodeInfoInner tmpKey(aName, aPrefix, aNamespaceID);
void *node = PL_HashTableLookup(mNodeInfoHash, &tmpKey);
if (node) {
nsINodeInfo* nodeInfo = static_cast<nsINodeInfo *>(node);
NS_ADDREF(*aNodeInfo = nodeInfo);
return NS_OK;
}
nsRefPtr<nsNodeInfo> newNodeInfo = nsNodeInfo::Create();
NS_ENSURE_TRUE(newNodeInfo, nsnull);
nsCOMPtr<nsIAtom> nameAtom = do_GetAtom(aName);
nsresult rv = newNodeInfo->Init(nameAtom, aPrefix, aNamespaceID, this);
NS_ENSURE_SUCCESS(rv, rv);
PLHashEntry *he;
he = PL_HashTableAdd(mNodeInfoHash, &newNodeInfo->mInner, newNodeInfo);
NS_ENSURE_TRUE(he, NS_ERROR_FAILURE);
newNodeInfo.forget(aNodeInfo);
return NS_OK;
}

View File

@ -65,19 +65,27 @@ nsNodeIterator::NodePointer::NodePointer(nsINode *aNode,
PRBool nsNodeIterator::NodePointer::MoveToNext(nsINode *aRoot)
{
NS_ASSERTION(mNode, "Iterating an uninitialized NodePointer");
if (!mNode)
return PR_FALSE;
if (mBeforeNode) {
mBeforeNode = PR_FALSE;
return PR_TRUE;
}
return MoveForward(aRoot, mNode, -1);
nsINode* child = mNode->GetFirstChild();
if (child) {
mNode = child;
return PR_TRUE;
}
return MoveForward(aRoot, mNode);
}
PRBool nsNodeIterator::NodePointer::MoveToPrevious(nsINode *aRoot)
{
NS_ASSERTION(mNode, "Iterating an uninitialized NodePointer");
if (!mNode)
return PR_FALSE;
if (!mBeforeNode) {
mBeforeNode = PR_TRUE;
@ -87,109 +95,72 @@ PRBool nsNodeIterator::NodePointer::MoveToPrevious(nsINode *aRoot)
if (mNode == aRoot)
return PR_FALSE;
NS_ASSERTION(mNodeParent == mNode->GetNodeParent(), "Parent node incorrect in MoveToPrevious");
NS_ASSERTION(mIndexInParent == mNodeParent->IndexOf(mNode), "Index mismatch in MoveToPrevious");
MoveBackward(mNodeParent, mIndexInParent);
MoveBackward(mNode->GetNodeParent(), mNode->GetPreviousSibling());
return PR_TRUE;
}
void nsNodeIterator::NodePointer::AdjustAfterInsertion(nsINode *aRoot,
nsINode *aContainer,
PRInt32 aIndexInContainer)
{
// If mNode is null or the root there is nothing to do. This also prevents
// valgrind from complaining about consuming uninitialized memory for
// mNodeParent and mIndexInParent
if (!mNode || mNode == aRoot)
return;
// check if earlier sibling was added
if (aContainer == mNodeParent && aIndexInContainer <= mIndexInParent)
mIndexInParent++;
}
void nsNodeIterator::NodePointer::AdjustAfterRemoval(nsINode *aRoot,
nsINode *aContainer,
nsIContent *aChild,
PRInt32 aIndexInContainer)
nsIContent *aPreviousSibling)
{
// If mNode is null or the root there is nothing to do. This also prevents
// valgrind from complaining about consuming uninitialized memory for
// mNodeParent and mIndexInParent
// If mNode is null or the root there is nothing to do.
if (!mNode || mNode == aRoot)
return;
// Check if earlier sibling was removed.
if (aContainer == mNodeParent && aIndexInContainer < mIndexInParent) {
--mIndexInParent;
return;
}
// check if ancestor was removed
if (!nsContentUtils::ContentIsDescendantOf(mNode, aChild))
return;
if (mBeforeNode) {
if (MoveForward(aRoot, aContainer, aIndexInContainer-1))
// Try the next sibling
nsINode *nextSibling = aPreviousSibling ? aPreviousSibling->GetNextSibling()
: aContainer->GetFirstChild();
if (nextSibling) {
mNode = nextSibling;
return;
}
// Next try siblings of ancestors
if (MoveForward(aRoot, aContainer))
return;
// No suitable node was found so try going backwards
mBeforeNode = PR_FALSE;
}
MoveBackward(aContainer, aIndexInContainer);
MoveBackward(aContainer, aPreviousSibling);
}
PRBool nsNodeIterator::NodePointer::MoveForward(nsINode *aRoot, nsINode *aParent, PRInt32 aChildNum)
PRBool nsNodeIterator::NodePointer::MoveForward(nsINode *aRoot, nsINode *aNode)
{
while (1) {
nsINode *node = aParent->GetChildAt(aChildNum+1);
if (node) {
mNode = node;
mIndexInParent = aChildNum+1;
mNodeParent = aParent;
return PR_TRUE;
}
if (aParent == aRoot)
if (aNode == aRoot)
break;
node = aParent;
if (node == mNode) {
NS_ASSERTION(mNodeParent == mNode->GetNodeParent(), "Parent node incorrect in MoveForward");
NS_ASSERTION(mIndexInParent == mNodeParent->IndexOf(mNode), "Index mismatch in MoveForward");
aParent = mNodeParent;
aChildNum = mIndexInParent;
} else {
aParent = node->GetNodeParent();
aChildNum = aParent->IndexOf(node);
nsINode *sibling = aNode->GetNextSibling();
if (sibling) {
mNode = sibling;
return PR_TRUE;
}
aNode = aNode->GetNodeParent();
}
return PR_FALSE;
}
void nsNodeIterator::NodePointer::MoveBackward(nsINode *aParent, PRInt32 aChildNum)
void nsNodeIterator::NodePointer::MoveBackward(nsINode *aParent, nsINode *aNode)
{
nsINode *sibling = aParent->GetChildAt(aChildNum-1);
mNode = aParent;
if (sibling) {
if (aNode) {
do {
mIndexInParent = aChildNum-1;
mNodeParent = mNode;
mNode = sibling;
aChildNum = mNode->GetChildCount();
sibling = mNode->GetChildAt(aChildNum-1);
} while (sibling);
mNode = aNode;
aNode = aNode->GetLastChild();
} while (aNode);
} else {
mNodeParent = mNode->GetNodeParent();
if (mNodeParent)
mIndexInParent = mNodeParent->IndexOf(mNode);
mNode = aParent;
}
}
@ -267,8 +238,7 @@ NS_IMETHODIMP nsNodeIterator::GetFilter(nsIDOMNodeFilter **aFilter)
{
NS_ENSURE_ARG_POINTER(aFilter);
nsCOMPtr<nsIDOMNodeFilter> filter = mFilter;
filter.swap((*aFilter = nsnull));
NS_IF_ADDREF(*aFilter = mFilter);
return NS_OK;
}
@ -364,25 +334,14 @@ NS_IMETHODIMP nsNodeIterator::GetPointerBeforeReferenceNode(PRBool *aBeforeNode)
* nsIMutationObserver interface
*/
void nsNodeIterator::ContentInserted(nsIDocument *aDocument,
nsIContent *aContainer,
nsIContent *aChild,
PRInt32 aIndexInContainer)
{
nsINode *container = NODE_FROM(aContainer, aDocument);
mPointer.AdjustAfterInsertion(mRoot, container, aIndexInContainer);
mWorkingPointer.AdjustAfterInsertion(mRoot, container, aIndexInContainer);
}
void nsNodeIterator::ContentRemoved(nsIDocument *aDocument,
nsIContent *aContainer,
nsIContent *aChild,
PRInt32 aIndexInContainer)
PRInt32 aIndexInContainer,
nsIContent *aPreviousSibling)
{
nsINode *container = NODE_FROM(aContainer, aDocument);
mPointer.AdjustAfterRemoval(mRoot, container, aChild, aIndexInContainer);
mWorkingPointer.AdjustAfterRemoval(mRoot, container, aChild, aIndexInContainer);
mPointer.AdjustAfterRemoval(mRoot, container, aChild, aPreviousSibling);
mWorkingPointer.AdjustAfterRemoval(mRoot, container, aChild, aPreviousSibling);
}

View File

@ -67,7 +67,6 @@ public:
PRBool aExpandEntityReferences);
virtual ~nsNodeIterator();
NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsNodeIterator, nsIDOMNodeIterator)
@ -81,22 +80,15 @@ private:
PRBool MoveToNext(nsINode *aRoot);
PRBool MoveToPrevious(nsINode *aRoot);
PRBool MoveForward(nsINode *aRoot, nsINode *aParent, PRInt32 aChildNum);
void MoveBackward(nsINode *aParent, PRInt32 aChildNum);
PRBool MoveForward(nsINode *aRoot, nsINode *aNode);
void MoveBackward(nsINode *aParent, nsINode *aNode);
void AdjustAfterInsertion(nsINode *aRoot, nsINode *aContainer, PRInt32 aIndexInContainer);
void AdjustAfterRemoval(nsINode *aRoot, nsINode *aContainer, nsIContent *aChild, PRInt32 aIndexInContainer);
void AdjustAfterRemoval(nsINode *aRoot, nsINode *aContainer, nsIContent *aChild, nsIContent *aPreviousSibling);
void Clear() { mNode = nsnull; }
nsINode *mNode;
// pointer to the parent of mNode. Can be dangling if mNode is null or
// points to the root
nsINode *mNodeParent;
PRBool mBeforeNode;
// mNode's index in mNodeParent. Uninitialized if mNodeParent is null
// or dangling (per above comment).
PRInt32 mIndexInParent;
};
inline nsresult

View File

@ -86,7 +86,6 @@ using namespace mozilla::dom;
} while (node); \
PR_END_MACRO
void
nsNodeUtils::CharacterDataWillChange(nsIContent* aContent,
CharacterDataChangeInfo* aInfo)
@ -168,7 +167,8 @@ nsNodeUtils::ContentInserted(nsINode* aContainer,
void
nsNodeUtils::ContentRemoved(nsINode* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer)
PRInt32 aIndexInContainer,
nsIContent* aPreviousSibling)
{
NS_PRECONDITION(aContainer->IsNodeOfType(nsINode::eCONTENT) ||
aContainer->IsNodeOfType(nsINode::eDOCUMENT),
@ -186,7 +186,8 @@ nsNodeUtils::ContentRemoved(nsINode* aContainer,
}
IMPL_MUTATION_NOTIFICATION(ContentRemoved, aContainer,
(document, container, aChild, aIndexInContainer));
(document, container, aChild, aIndexInContainer,
aPreviousSibling));
}
void

View File

@ -126,7 +126,8 @@ public:
*/
static void ContentRemoved(nsINode* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer);
PRInt32 aIndexInContainer,
nsIContent* aPreviousSibling);
/**
* Send ParentChainChanged notifications to nsIMutationObservers
* @param aContent The piece of content that had its parent changed.

View File

@ -544,7 +544,11 @@ nsObjectLoadingContent::OnStartRequest(nsIRequest *aRequest,
// end up trying to dispatch to a nsFrameLoader, which will complain that
// it couldn't find a way to handle application/octet-stream
chan->SetContentType(mContentType);
nsCAutoString typeHint, dummy;
NS_ParseContentType(mContentType, typeHint, dummy);
if (!typeHint.IsEmpty()) {
chan->SetContentType(typeHint);
}
} else {
mContentType = channelType;
}
@ -1437,7 +1441,11 @@ nsObjectLoadingContent::LoadObject(nsIURI* aURI,
// MIME Type hint
if (!aTypeHint.IsEmpty()) {
chan->SetContentType(aTypeHint);
nsCAutoString typeHint, dummy;
NS_ParseContentType(aTypeHint, typeHint, dummy);
if (!typeHint.IsEmpty()) {
chan->SetContentType(typeHint);
}
}
// Set up the channel's principal and such, like nsDocShell::DoURILoad does

View File

@ -315,7 +315,8 @@ void
nsRange::ContentRemoved(nsIDocument* aDocument,
nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer)
PRInt32 aIndexInContainer,
nsIContent* aPreviousSibling)
{
NS_ASSERTION(mIsPositioned, "shouldn't be notified if not positioned");
@ -353,6 +354,8 @@ nsRange::ParentChainChanged(nsIContent *aContent)
NS_ASSERTION(newRoot, "No valid boundary or root found!");
NS_ASSERTION(newRoot == IsValidBoundary(mEndParent),
"Start parent and end parent give different root!");
// This is safe without holding a strong ref to self as long as the change
// of mRoot is the last thing in DoSetRange.
DoSetRange(mStartParent, mStartOffset, mEndParent, mEndOffset, newRoot);
}
@ -473,6 +476,8 @@ nsRange::DoSetRange(nsINode* aStartN, PRInt32 aStartOffset,
mEndParent = aEndN;
mEndOffset = aEndOffset;
mIsPositioned = !!mStartParent;
// This needs to be the last thing this function does. See comment
// in ParentChainChanged.
mRoot = aRoot;
}

View File

@ -97,20 +97,12 @@ public:
virtual nsresult SetStart(nsINode* aParent, PRInt32 aOffset);
virtual nsresult SetEnd(nsINode* aParent, PRInt32 aOffset);
virtual nsresult CloneRange(nsIRange** aNewRange) const;
// nsIMutationObserver methods
virtual void CharacterDataChanged(nsIDocument* aDocument,
nsIContent* aContent,
CharacterDataChangeInfo* aChangeInfo);
virtual void ContentInserted(nsIDocument* aDocument,
nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer);
virtual void ContentRemoved(nsIDocument* aDocument,
nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer);
virtual void ParentChainChanged(nsIContent *aContent);
NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED
NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
NS_DECL_NSIMUTATIONOBSERVER_PARENTCHAINCHANGED
private:
// no copy's or assigns

View File

@ -58,7 +58,7 @@ class nsStyledElement : public nsStyledElementBase
protected:
inline nsStyledElement(nsINodeInfo *aNodeInfo)
inline nsStyledElement(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsStyledElementBase(aNodeInfo)
{}

View File

@ -59,7 +59,7 @@ class nsAttributeTextNode : public nsTextNode,
public:
NS_DECL_ISUPPORTS_INHERITED
nsAttributeTextNode(nsINodeInfo *aNodeInfo,
nsAttributeTextNode(already_AddRefed<nsINodeInfo> aNodeInfo,
PRInt32 aNameSpaceID,
nsIAtom* aAttrName) :
nsTextNode(aNodeInfo),
@ -87,7 +87,8 @@ public:
virtual nsGenericDOMDataNode *CloneDataNode(nsINodeInfo *aNodeInfo,
PRBool aCloneText) const
{
nsAttributeTextNode *it = new nsAttributeTextNode(aNodeInfo,
nsCOMPtr<nsINodeInfo> ni = aNodeInfo;
nsAttributeTextNode *it = new nsAttributeTextNode(ni.forget(),
mNameSpaceID,
mAttrName);
if (it && aCloneText) {
@ -129,7 +130,7 @@ NS_NewTextNode(nsIContent** aInstancePtrResult,
return NS_ERROR_OUT_OF_MEMORY;
}
nsIContent *instance = new nsTextNode(ni);
nsTextNode *instance = new nsTextNode(ni.forget());
if (!instance) {
return NS_ERROR_OUT_OF_MEMORY;
}
@ -139,7 +140,7 @@ NS_NewTextNode(nsIContent** aInstancePtrResult,
return NS_OK;
}
nsTextNode::nsTextNode(nsINodeInfo *aNodeInfo)
nsTextNode::nsTextNode(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsGenericTextNode(aNodeInfo)
{
}
@ -151,7 +152,7 @@ nsTextNode::~nsTextNode()
NS_IMPL_ADDREF_INHERITED(nsTextNode, nsGenericDOMDataNode)
NS_IMPL_RELEASE_INHERITED(nsTextNode, nsGenericDOMDataNode)
DOMCI_DATA(Text, nsTextNode)
DOMCI_NODE_DATA(Text, nsTextNode)
// QueryInterface implementation for nsTextNode
NS_INTERFACE_TABLE_HEAD(nsTextNode)
@ -197,7 +198,8 @@ nsTextNode::IsNodeOfType(PRUint32 aFlags) const
nsGenericDOMDataNode*
nsTextNode::CloneDataNode(nsINodeInfo *aNodeInfo, PRBool aCloneText) const
{
nsTextNode *it = new nsTextNode(aNodeInfo);
nsCOMPtr<nsINodeInfo> ni = aNodeInfo;
nsTextNode *it = new nsTextNode(ni.forget());
if (it && aCloneText) {
it->mText = mText;
}
@ -281,7 +283,8 @@ NS_NewAttributeContent(nsNodeInfoManager *aNodeInfoManager,
return NS_ERROR_OUT_OF_MEMORY;
}
nsAttributeTextNode* textNode = new nsAttributeTextNode(ni, aNameSpaceID,
nsAttributeTextNode* textNode = new nsAttributeTextNode(ni.forget(),
aNameSpaceID,
aAttrName);
if (!textNode) {
return NS_ERROR_OUT_OF_MEMORY;
@ -341,15 +344,12 @@ nsAttributeTextNode::AttributeChanged(nsIDocument* aDocument,
{
if (aNameSpaceID == mNameSpaceID && aAttribute == mAttrName &&
aContent == mGrandparent) {
// Since UpdateText notifies, do it asynchronously. Note that if we get
// unbound while the event is up that's ok -- we'll just have no
// grandparent when it fires, and will do nothing.
// XXXbz ideally we'd either process this on layout flushes or do it right
// after nsIMutationObserver notifications are over or something, instead
// of doing it fully async.
// Since UpdateText notifies, do it when it's safe to run script. Note
// that if we get unbound while the event is up that's ok -- we'll just
// have no grandparent when it fires, and will do nothing.
void (nsAttributeTextNode::*update)() = &nsAttributeTextNode::UpdateText;
nsCOMPtr<nsIRunnable> ev = NS_NewRunnableMethod(this, update);
NS_DispatchToCurrentThread(ev);
nsContentUtils::AddScriptRunner(ev);
}
}

View File

@ -57,7 +57,7 @@ class nsTextNode : public nsGenericTextNode,
public nsIDOMText
{
public:
nsTextNode(nsINodeInfo *aNodeInfo);
nsTextNode(already_AddRefed<nsINodeInfo> aNodeInfo);
virtual ~nsTextNode();
// nsISupports
@ -78,6 +78,8 @@ public:
nsresult BindToAttribute(nsIAttribute* aAttr);
nsresult UnbindFromAttribute();
virtual nsXPCClassInfo* GetClassInfo();
#ifdef DEBUG
virtual void List(FILE* out, PRInt32 aIndent) const;
virtual void DumpContent(FILE* out, PRInt32 aIndent, PRBool aDumpAll) const;

View File

@ -1,6 +1,6 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* ***** BEGIN LICENSE BLOCK *****
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set ts=4 et sw=4 tw=80: */
/* ***** 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
@ -22,6 +22,7 @@
*
* Contributor(s):
* Jonas Sicking <sicking@bigfoot.com> (Original Author)
* Craig Topper <craig.topper@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
@ -47,9 +48,6 @@
#include "nsIDOMNodeFilter.h"
#include "nsDOMError.h"
#include "nsIContent.h"
#include "nsIDocument.h"
#include "nsContentUtils.h"
/*
@ -61,8 +59,7 @@ nsTreeWalker::nsTreeWalker(nsINode *aRoot,
nsIDOMNodeFilter *aFilter,
PRBool aExpandEntityReferences) :
nsTraversal(aRoot, aWhatToShow, aFilter, aExpandEntityReferences),
mCurrentNode(aRoot),
mPossibleIndexesPos(-1)
mCurrentNode(aRoot)
{
}
@ -119,8 +116,7 @@ NS_IMETHODIMP nsTreeWalker::GetFilter(nsIDOMNodeFilter * *aFilter)
{
NS_ENSURE_ARG_POINTER(aFilter);
nsCOMPtr<nsIDOMNodeFilter> filter = mFilter;
filter.swap((*aFilter = nsnull));
NS_IF_ADDREF(*aFilter = mFilter);
return NS_OK;
}
@ -152,8 +148,6 @@ NS_IMETHODIMP nsTreeWalker::SetCurrentNode(nsIDOMNode * aCurrentNode)
NS_ENSURE_SUCCESS(rv, rv);
mCurrentNode = do_QueryInterface(aCurrentNode);
mPossibleIndexes.Clear();
mPossibleIndexesPos = -1;
return NS_OK;
}
@ -166,16 +160,13 @@ NS_IMETHODIMP nsTreeWalker::SetCurrentNode(nsIDOMNode * aCurrentNode)
NS_IMETHODIMP nsTreeWalker::ParentNode(nsIDOMNode **_retval)
{
*_retval = nsnull;
nsresult rv;
PRInt32 indexPos = mPossibleIndexesPos;
nsCOMPtr<nsINode> node = mCurrentNode;
while (node && node != mRoot) {
node = node->GetNodeParent();
indexPos--;
if (node) {
PRInt16 filtered;
@ -183,8 +174,6 @@ NS_IMETHODIMP nsTreeWalker::ParentNode(nsIDOMNode **_retval)
NS_ENSURE_SUCCESS(rv, rv);
if (filtered == nsIDOMNodeFilter::FILTER_ACCEPT) {
mCurrentNode = node;
mPossibleIndexesPos = indexPos >= 0 ? indexPos : -1;
return CallQueryInterface(node, _retval);
}
}
@ -196,374 +185,260 @@ NS_IMETHODIMP nsTreeWalker::ParentNode(nsIDOMNode **_retval)
/* nsIDOMNode firstChild (); */
NS_IMETHODIMP nsTreeWalker::FirstChild(nsIDOMNode **_retval)
{
*_retval = nsnull;
nsCOMPtr<nsINode> result;
nsresult rv = FirstChildOf(mCurrentNode,
PR_FALSE,
mPossibleIndexesPos + 1,
getter_AddRefs(result));
NS_ENSURE_SUCCESS(rv, rv);
return result ? CallQueryInterface(result, _retval) : NS_OK;
return FirstChildInternal(PR_FALSE, _retval);
}
/* nsIDOMNode lastChild (); */
NS_IMETHODIMP nsTreeWalker::LastChild(nsIDOMNode **_retval)
{
*_retval = nsnull;
nsCOMPtr<nsINode> result;
nsresult rv = FirstChildOf(mCurrentNode,
PR_TRUE,
mPossibleIndexesPos + 1,
getter_AddRefs(result));
NS_ENSURE_SUCCESS(rv, rv);
return result ? CallQueryInterface(result, _retval) : NS_OK;
return FirstChildInternal(PR_TRUE, _retval);
}
/* nsIDOMNode previousSibling (); */
NS_IMETHODIMP nsTreeWalker::PreviousSibling(nsIDOMNode **_retval)
{
*_retval = nsnull;
nsCOMPtr<nsINode> result;
nsresult rv = NextSiblingOf(mCurrentNode,
PR_TRUE,
mPossibleIndexesPos,
getter_AddRefs(result));
NS_ENSURE_SUCCESS(rv, rv);
return result ? CallQueryInterface(result, _retval) : NS_OK;
return NextSiblingInternal(PR_TRUE, _retval);
}
/* nsIDOMNode nextSibling (); */
NS_IMETHODIMP nsTreeWalker::NextSibling(nsIDOMNode **_retval)
{
*_retval = nsnull;
nsCOMPtr<nsINode> result;
nsresult rv = NextSiblingOf(mCurrentNode,
PR_FALSE,
mPossibleIndexesPos,
getter_AddRefs(result));
NS_ENSURE_SUCCESS(rv, rv);
return result ? CallQueryInterface(result, _retval) : NS_OK;
return NextSiblingInternal(PR_FALSE, _retval);
}
/* nsIDOMNode previousNode (); */
NS_IMETHODIMP nsTreeWalker::PreviousNode(nsIDOMNode **_retval)
{
nsresult rv;
PRInt16 filtered;
*_retval = nsnull;
nsCOMPtr<nsINode> result;
nsresult rv = NextInDocumentOrderOf(mCurrentNode,
PR_TRUE,
mPossibleIndexesPos,
getter_AddRefs(result));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsINode> node = mCurrentNode;
return result ? CallQueryInterface(result, _retval) : NS_OK;
while (node != mRoot) {
while (nsINode *previousSibling = node->GetPreviousSibling()) {
node = previousSibling;
rv = TestNode(node, &filtered);
NS_ENSURE_SUCCESS(rv, rv);
nsINode *lastChild;
while (filtered != nsIDOMNodeFilter::FILTER_REJECT &&
(lastChild = node->GetLastChild())) {
node = lastChild;
rv = TestNode(node, &filtered);
NS_ENSURE_SUCCESS(rv, rv);
}
if (filtered == nsIDOMNodeFilter::FILTER_ACCEPT) {
mCurrentNode = node;
return CallQueryInterface(node, _retval);
}
}
if (node == mRoot)
break;
node = node->GetNodeParent();
if (!node)
break;
rv = TestNode(node, &filtered);
NS_ENSURE_SUCCESS(rv, rv);
if (filtered == nsIDOMNodeFilter::FILTER_ACCEPT) {
mCurrentNode = node;
return CallQueryInterface(node, _retval);
}
}
return NS_OK;
}
/* nsIDOMNode nextNode (); */
NS_IMETHODIMP nsTreeWalker::NextNode(nsIDOMNode **_retval)
{
nsresult rv;
PRInt16 filtered = nsIDOMNodeFilter::FILTER_ACCEPT; // pre-init for inner loop
*_retval = nsnull;
nsCOMPtr<nsINode> result;
nsresult rv = NextInDocumentOrderOf(mCurrentNode,
PR_FALSE,
mPossibleIndexesPos,
getter_AddRefs(result));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsINode> node = mCurrentNode;
return result ? CallQueryInterface(result, _retval) : NS_OK;
while (1) {
nsINode *firstChild;
while (filtered != nsIDOMNodeFilter::FILTER_REJECT &&
(firstChild = node->GetFirstChild())) {
node = firstChild;
rv = TestNode(node, &filtered);
NS_ENSURE_SUCCESS(rv, rv);
if (filtered == nsIDOMNodeFilter::FILTER_ACCEPT) {
// Node found
mCurrentNode = node;
return CallQueryInterface(node, _retval);
}
}
nsINode *sibling = nsnull;
nsINode *temp = node;
do {
if (temp == mRoot)
break;
sibling = temp->GetNextSibling();
if (sibling)
break;
temp = temp->GetNodeParent();
} while (temp);
if (!sibling)
break;
node = sibling;
// Found a sibling. Either ours or ancestor's
rv = TestNode(node, &filtered);
NS_ENSURE_SUCCESS(rv, rv);
if (filtered == nsIDOMNodeFilter::FILTER_ACCEPT) {
// Node found
mCurrentNode = node;
return CallQueryInterface(node, _retval);
}
}
return NS_OK;
}
/*
* nsTreeWalker helper functions
*/
/*
* Finds the first child of aNode and returns it. If a child is
* found, mCurrentNode is set to that child.
* @param aNode Node to search for children.
* @param aReversed Reverses search to find the last child instead
* of first.
* @param aIndexPos Position of aNode in mPossibleIndexes.
* Implements FirstChild and LastChild which only vary in which direction
* they search.
* @param aReversed Controls whether we search forwards or backwards
* @param _retval Returned node. Null if no child is found
* @returns Errorcode
*/
nsresult
nsTreeWalker::FirstChildOf(nsINode* aNode,
PRBool aReversed,
PRInt32 aIndexPos,
nsINode** _retval)
{
*_retval = nsnull;
PRInt32 start = aReversed ? (PRInt32)aNode->GetChildCount() : -1;
return ChildOf(aNode, start, aReversed, aIndexPos, _retval);
}
/*
* Finds the following sibling of aNode and returns it. If a sibling
* is found, mCurrentNode is set to that node.
* @param aNode Node to start search at.
* @param aReversed Reverses search to find the previous sibling
* instead of next.
* @param aIndexPos Position of aNode in mPossibleIndexes.
* @param _retval Returned node. Null if no sibling is found
* @returns Errorcode
*/
nsresult
nsTreeWalker::NextSiblingOf(nsINode* aNode,
PRBool aReversed,
PRInt32 aIndexPos,
nsINode** _retval)
nsresult nsTreeWalker::FirstChildInternal(PRBool aReversed, nsIDOMNode **_retval)
{
nsresult rv;
nsCOMPtr<nsINode> node = aNode;
PRInt16 filtered;
PRInt32 childNum;
if (node == mRoot) {
*_retval = nsnull;
return NS_OK;
}
while (1) {
nsCOMPtr<nsINode> parent = node->GetNodeParent();
if (!parent)
break;
childNum = IndexOf(parent, node, aIndexPos);
NS_ENSURE_TRUE(childNum >= 0, NS_ERROR_UNEXPECTED);
// Search siblings
rv = ChildOf(parent, childNum, aReversed, aIndexPos, _retval);
NS_ENSURE_SUCCESS(rv, rv);
if (*_retval)
return NS_OK;
// Is parent the root?
if (parent == mRoot)
break;
// Is parent transparent in filtered view?
rv = TestNode(parent, &filtered);
NS_ENSURE_SUCCESS(rv, rv);
if (filtered == nsIDOMNodeFilter::FILTER_ACCEPT)
break;
node = parent;
aIndexPos = aIndexPos < 0 ? -1 : aIndexPos-1;
}
*_retval = nsnull;
return NS_OK;
}
/*
* Finds the next node in document order of aNode and returns it.
* If a node is found, mCurrentNode is set to that node.
* @param aNode Node to start search at.
* @param aReversed Reverses search to find the preceding node
* instead of next.
* @param aIndexPos Position of aNode in mPossibleIndexes.
* @param _retval Returned node. Null if no node is found
* @returns Errorcode
*/
nsresult
nsTreeWalker::NextInDocumentOrderOf(nsINode* aNode,
PRBool aReversed,
PRInt32 aIndexPos,
nsINode** _retval)
{
nsresult rv;
nsCOMPtr<nsINode> node = aReversed ? mCurrentNode->GetLastChild()
: mCurrentNode->GetFirstChild();
if (!aReversed) {
rv = FirstChildOf(aNode, aReversed, aIndexPos+1, _retval);
NS_ENSURE_SUCCESS(rv, rv);
if (*_retval)
return NS_OK;
}
if (aNode == mRoot){
*_retval = nsnull;
return NS_OK;
}
nsCOMPtr<nsINode> node = aNode;
nsCOMPtr<nsINode> currentNodeBackup = mCurrentNode;
PRInt16 filtered;
PRInt32 childNum;
while (1) {
// Get our index in the parent
nsCOMPtr<nsINode> parent = node->GetNodeParent();
if (!parent)
break;
childNum = IndexOf(parent, node, aIndexPos);
NS_ENSURE_TRUE(childNum >= 0, NS_ERROR_UNEXPECTED);
// Search siblings
nsCOMPtr<nsINode> sibling;
rv = ChildOf(parent, childNum, aReversed, aIndexPos,
getter_AddRefs(sibling));
NS_ENSURE_SUCCESS(rv, rv);
if (sibling) {
if (aReversed) {
// in reversed walking we first test if there are
// any children. I don't like this piece of code :(
nsCOMPtr<nsINode> child = sibling;
while (child) {
sibling = child;
rv = FirstChildOf(sibling,
PR_TRUE,
aIndexPos,
getter_AddRefs(child));
if (NS_FAILED(rv)) {
// ChildOf set mCurrentNode and then something
// failed. Restore the old value before returning
mCurrentNode = currentNodeBackup;
mPossibleIndexesPos = -1;
return rv;
}
}
}
*_retval = sibling;
NS_ADDREF(*_retval);
return NS_OK;
}
aIndexPos = aIndexPos < 0 ? -1 : aIndexPos-1;
if (aReversed) {
// Is parent transparent in filtered view?
rv = TestNode(parent, &filtered);
NS_ENSURE_SUCCESS(rv, rv);
if (filtered == nsIDOMNodeFilter::FILTER_ACCEPT) {
mCurrentNode = parent;
mPossibleIndexesPos = aIndexPos;
*_retval = parent;
NS_ADDREF(*_retval);
return NS_OK;
}
}
// Is parent the root?
if (parent == mRoot)
break;
node = parent;
}
*_retval = nsnull;
return NS_OK;
}
/*
* Finds the first child of aNode after child N and returns it. If a
* child is found, mCurrentNode is set to that child
* @param aNode Node to search for children
* @param childNum Child number to start search from. The child with
* this number is not searched
* @param aReversed Reverses search to find the last child instead
* of first
* @param aIndexPos Position of aNode in mPossibleIndexes
* @param _retval Returned node. Null if no child is found
* @returns Errorcode
*/
nsresult
nsTreeWalker::ChildOf(nsINode* aNode,
PRInt32 childNum,
PRBool aReversed,
PRInt32 aIndexPos,
nsINode** _retval)
{
PRInt16 filtered;
nsresult rv;
PRInt32 dir = aReversed ? -1 : 1;
// Step through all children
PRInt32 i = childNum;
while (1) {
i += dir;
nsCOMPtr<nsINode> child = aNode->GetChildAt(i);
if (!child) {
break;
}
rv = TestNode(child, &filtered);
while (node) {
rv = TestNode(node, &filtered);
NS_ENSURE_SUCCESS(rv, rv);
switch (filtered) {
case nsIDOMNodeFilter::FILTER_ACCEPT:
// Child found
mCurrentNode = child;
mPossibleIndexesPos = aIndexPos;
*_retval = child;
NS_ADDREF(*_retval);
SetChildIndex(aIndexPos, i);
return NS_OK;
case nsIDOMNodeFilter::FILTER_SKIP:
// Search children
rv = FirstChildOf(child, aReversed, aIndexPos+1, _retval);
NS_ENSURE_SUCCESS(rv, rv);
if (*_retval) {
SetChildIndex(aIndexPos, i);
return NS_OK;
// Node found
mCurrentNode = node;
return CallQueryInterface(node, _retval);
case nsIDOMNodeFilter::FILTER_SKIP: {
nsINode *child = aReversed ? node->GetLastChild()
: node->GetFirstChild();
if (child) {
node = child;
continue;
}
break;
}
break;
case nsIDOMNodeFilter::FILTER_REJECT:
// Keep searching
break;
default:
return NS_ERROR_UNEXPECTED;
}
do {
nsINode *sibling = aReversed ? node->GetPreviousSibling()
: node->GetNextSibling();
if (sibling) {
node = sibling;
break;
}
nsINode *parent = node->GetNodeParent();
if (!parent || parent == mRoot || parent == mCurrentNode) {
return NS_OK;
}
} while (node);
}
*_retval = nsnull;
return NS_OK;
}
/*
* Gets the child index of a node within its parent. Gets a possible index
* from mPossibleIndexes to gain speed. If the value in mPossibleIndexes
* isn't correct it'll get the index the usual way
* @param aParent in which to get the index
* @param aChild node to get the index of
* @param aIndexPos position in mPossibleIndexes that contains the possible.
* index
* @returns resulting index
* Implements NextSibling and PreviousSibling which only vary in which
* direction they search.
* @param aReversed Controls whether we search forwards or backwards
* @param _retval Returned node. Null if no child is found
* @returns Errorcode
*/
PRInt32 nsTreeWalker::IndexOf(nsINode* aParent,
nsINode* aChild,
PRInt32 aIndexPos)
nsresult nsTreeWalker::NextSiblingInternal(PRBool aReversed, nsIDOMNode **_retval)
{
if (aIndexPos >= 0 && aIndexPos < PRInt32(mPossibleIndexes.Length())) {
PRInt32 possibleIndex = mPossibleIndexes.ElementAt(aIndexPos);
if (aChild == aParent->GetChildAt(possibleIndex)) {
return possibleIndex;
nsresult rv;
PRInt16 filtered;
*_retval = nsnull;
nsCOMPtr<nsINode> node = mCurrentNode;
if (node == mRoot)
return NS_OK;
while (1) {
nsCOMPtr<nsINode> sibling = aReversed ? node->GetPreviousSibling()
: node->GetNextSibling();
while (sibling) {
rv = TestNode(sibling, &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;
}
sibling = aReversed ? sibling->GetPreviousSibling()
: sibling->GetNextSibling();
}
node = node->GetNodeParent();
if (!node || node == mRoot)
break;
// Is parent transparent in filtered view?
rv = TestNode(node, &filtered);
NS_ENSURE_SUCCESS(rv, rv);
if (filtered == nsIDOMNodeFilter::FILTER_ACCEPT)
break;
}
return aParent->IndexOf(aChild);
return NS_OK;
}

View File

@ -1,6 +1,6 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* ***** BEGIN LICENSE BLOCK *****
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set ts=4 et sw=4 tw=80: */
/* ***** 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
@ -22,6 +22,7 @@
*
* Contributor(s):
* Jonas Sicking <sicking@bigfoot.com> (Original Author)
* Craig Topper <craig.topper@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
@ -70,108 +71,24 @@ public:
private:
nsCOMPtr<nsINode> mCurrentNode;
/*
* Array with all child indexes up the tree. This should only be
* considered a hint and the value could be wrong.
*/
nsAutoTArray<PRInt32, 8> mPossibleIndexes;
/*
* Position of mCurrentNode in mPossibleIndexes
*/
PRInt32 mPossibleIndexesPos;
/*
* Finds the first child of aNode and returns it. If a child is
* found, mCurrentNode is set to that child.
* @param aNode Node to search for children.
* @param aReversed Reverses search to find the last child instead
* of first.
* @param aIndexPos Position of aNode in mPossibleIndexes.
* Implements FirstChild and LastChild which only vary in which direction
* they search.
* @param aReversed Controls whether we search forwards or backwards
* @param _retval Returned node. Null if no child is found
* @returns Errorcode
*/
nsresult FirstChildOf(nsINode* aNode,
PRBool aReversed,
PRInt32 aIndexPos,
nsINode** _retval);
nsresult FirstChildInternal(PRBool aReversed, nsIDOMNode **_retval);
/*
* Finds the following sibling of aNode and returns it. If a sibling
* is found, mCurrentNode is set to that node.
* @param aNode Node to start search at.
* @param aReversed Reverses search to find the previous sibling
* instead of next.
* @param aIndexPos Position of aNode in mPossibleIndexes.
* @param _retval Returned node. Null if no sibling is found
* @returns Errorcode
*/
nsresult NextSiblingOf(nsINode* aNode,
PRBool aReversed,
PRInt32 aIndexPos,
nsINode** _retval);
/*
* Finds the next node in document order of aNode and returns it.
* If a node is found, mCurrentNode is set to that node.
* @param aNode Node to start search at.
* @param aReversed Reverses search to find the preceding node
* instead of next.
* @param aIndexPos Position of aNode in mPossibleIndexes.
* @param _retval Returned node. Null if no node is found
* @returns Errorcode
*/
nsresult NextInDocumentOrderOf(nsINode* aNode,
PRBool aReversed,
PRInt32 aIndexPos,
nsINode** _retval);
/*
* Finds the first child of aNode after child N and returns it. If a
* child is found, mCurrentNode is set to that child
* @param aNode Node to search for children
* @param childNum Child number to start search from. The child with
* this number is not searched
* @param aReversed Reverses search to find the last child instead
* of first
* @param aIndexPos Position of aNode in mPossibleIndexes
* Implements NextSibling and PreviousSibling which only vary in which
* direction they search.
* @param aReversed Controls whether we search forwards or backwards
* @param _retval Returned node. Null if no child is found
* @returns Errorcode
*/
nsresult ChildOf(nsINode* aNode,
PRInt32 childNum,
PRBool aReversed,
PRInt32 aIndexPos,
nsINode** _retval);
/*
* Gets the child index of a node within its parent. Gets a possible index
* from mPossibleIndexes to gain speed. If the value in mPossibleIndexes
* isn't correct it'll get the index the usual way.
* @param aParent in which to get the index
* @param aChild node to get the index of
* @param aIndexPos position in mPossibleIndexes that contains the possible.
* index
* @returns resulting index
*/
PRInt32 IndexOf(nsINode* aParent,
nsINode* aChild,
PRInt32 aIndexPos);
/*
* Sets the child index at the specified level. It doesn't matter if this
* fails since mPossibleIndexes should only be considered a hint
* @param aIndexPos position in mPossibleIndexes to set
* @param aChildIndex child index at specified position
*/
void SetChildIndex(PRInt32 aIndexPos, PRInt32 aChildIndex)
{
if (aIndexPos >= 0 &&
mPossibleIndexes.EnsureLengthAtLeast(aIndexPos+1)) {
mPossibleIndexes.ElementAt(aIndexPos) = aChildIndex;
}
}
nsresult NextSiblingInternal(PRBool aReversed, nsIDOMNode **_retval);
};
#endif

View File

@ -241,12 +241,14 @@ public:
nsresult Disconnect();
// These are called always on the main thread (they dispatch themselves).
// ATTENTION, this method when called can release both the WebSocket object
// (i.e. mOwner) and its connection (i.e. *this*) if there are no strong event
// listeners.
// ATTENTION, these method when called can release both the WebSocket object
// (i.e. mOwner) and its connection (i.e. *this*).
DECL_RUNNABLE_ON_MAIN_THREAD_METHOD(Close)
DECL_RUNNABLE_ON_MAIN_THREAD_METHOD(FailConnection)
PRBool HasOutgoingMessages()
{ return mOutgoingMessages.GetSize() != 0; }
PRBool ClosedCleanly() { return mClosedCleanly; }
nsresult PostMessage(const nsString& aMessage);
@ -311,8 +313,6 @@ private:
const PRUnichar *aError,
const PRUnichar **aFormatStrings,
PRUint32 aFormatStringsLen);
PRBool SentAlreadyTheCloseFrame()
{ return mPostedCloseFrame && mOutgoingMessages.GetSize() == 0; }
// auth specific methods
DECL_RUNNABLE_ON_MAIN_THREAD_METHOD(ProcessAuthentication)
@ -327,6 +327,7 @@ private:
DECL_RUNNABLE_ON_MAIN_THREAD_METHOD(DispatchNewMessage)
DECL_RUNNABLE_ON_MAIN_THREAD_METHOD(Retry)
DECL_RUNNABLE_ON_MAIN_THREAD_METHOD(ResolveNextProxyAndConnect)
DECL_RUNNABLE_ON_MAIN_THREAD_METHOD(UpdateMustKeepAlive)
// called to cause the underlying socket to start speaking SSL
nsresult ProxyStartSSL();
@ -400,6 +401,7 @@ private:
PRPackedBool mAuthenticating;
PRPackedBool mPostedCloseFrame;
PRPackedBool mSentCloseFrame;
PRPackedBool mClosedCleanly;
/**
@ -658,6 +660,7 @@ nsWebSocketEstablishedConnection::nsWebSocketEstablishedConnection() :
mFailureStatus(NS_OK),
mAuthenticating(PR_FALSE),
mPostedCloseFrame(PR_FALSE),
mSentCloseFrame(PR_FALSE),
mClosedCleanly(PR_FALSE),
mStatus(CONN_NOT_CONNECTED)
{
@ -710,6 +713,8 @@ nsWebSocketEstablishedConnection::PostData(nsCString *aBuffer,
NS_ENSURE_SUCCESS(rv, rv);
}
UpdateMustKeepAlive();
return NS_OK;
}
@ -1214,7 +1219,7 @@ nsWebSocketEstablishedConnection::HandleNewInputString(PRUint32 aStart)
// check if it is the close frame
if (mLengthToDiscard == 0 && frameType == START_BYTE_OF_CLOSE_FRAME) {
mBytesInBuffer = 0;
if (SentAlreadyTheCloseFrame()) {
if (mSentCloseFrame) {
mClosedCleanly = PR_TRUE;
mStatus = CONN_CLOSED;
} else {
@ -2247,6 +2252,12 @@ IMPL_RUNNABLE_ON_MAIN_THREAD_METHOD_BEGIN(ResolveNextProxyAndConnect)
}
IMPL_RUNNABLE_ON_MAIN_THREAD_METHOD_END
IMPL_RUNNABLE_ON_MAIN_THREAD_METHOD_BEGIN(UpdateMustKeepAlive)
{
mOwner->UpdateMustKeepAlive();
}
IMPL_RUNNABLE_ON_MAIN_THREAD_METHOD_END
void
nsWebSocketEstablishedConnection::RemoveFromLoadGroup()
{
@ -2695,7 +2706,6 @@ nsWebSocketEstablishedConnection::OnOutputStreamReady(nsIAsyncOutputStream *aStr
strToSend->Length() - mBytesAlreadySentOfFirstOutString;
PRBool currentStrHasStartFrameByte =
(mBytesAlreadySentOfFirstOutString == 0);
PRBool strIsMessage = (frameToSend->mType == eUTF8MessageFrame);
if (sizeToSend != 0) {
PRUint32 written;
@ -2730,7 +2740,7 @@ nsWebSocketEstablishedConnection::OnOutputStreamReady(nsIAsyncOutputStream *aStr
return NS_BASE_STREAM_CLOSED;
}
if (strIsMessage) {
if (frameToSend->mType == eUTF8MessageFrame) {
PRBool currentStrHasEndFrameByte =
(mBytesAlreadySentOfFirstOutString + written ==
strToSend->Length());
@ -2760,17 +2770,20 @@ nsWebSocketEstablishedConnection::OnOutputStreamReady(nsIAsyncOutputStream *aStr
}
// ok, send the next string
if (frameToSend->mType == eCloseFrame) {
mSentCloseFrame = PR_TRUE;
}
mOutgoingMessages.PopFront();
delete frameToSend;
mBytesAlreadySentOfFirstOutString = 0;
UpdateMustKeepAlive();
}
if (mOutgoingMessages.GetSize() != 0) {
rv = mSocketOutput->AsyncWait(this, 0, 0, gWebSocketThread);
ENSURE_SUCCESS_AND_FAIL_IF_FAILED(rv, rv);
} else {
if (mStatus == CONN_SENDING_ACK_CLOSE_FRAME &&
SentAlreadyTheCloseFrame()) {
if (mStatus == CONN_SENDING_ACK_CLOSE_FRAME && mSentCloseFrame) {
mClosedCleanly = PR_TRUE;
mStatus = CONN_CLOSED;
return Close();
@ -2833,8 +2846,9 @@ nsWebSocketEstablishedConnection::GetInterface(const nsIID &aIID,
// nsWebSocket
////////////////////////////////////////////////////////////////////////////////
nsWebSocket::nsWebSocket() : mHasStrongEventListeners(PR_FALSE),
mCheckThereAreStrongEventListeners(PR_TRUE),
nsWebSocket::nsWebSocket() : mKeepingAlive(PR_FALSE),
mCheckMustKeepAlive(PR_TRUE),
mTriggeredCloseEvent(PR_FALSE),
mReadyState(nsIWebSocket::CONNECTING),
mOutgoingBufferedAmount(0)
{
@ -3063,6 +3077,8 @@ nsWebSocket::CreateAndDispatchCloseEvent(PRBool aWasClean)
{
nsresult rv;
mTriggeredCloseEvent = PR_TRUE;
rv = CheckInnerWindowCorrectness();
if (NS_FAILED(rv)) {
return NS_OK;
@ -3138,6 +3154,7 @@ nsWebSocket::SetReadyState(PRUint16 aNewReadyState)
rv = NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
if (NS_FAILED(rv)) {
NS_WARNING("Failed to dispatch the close event");
mTriggeredCloseEvent = PR_TRUE;
UpdateMustKeepAlive();
}
}
@ -3251,45 +3268,71 @@ nsWebSocket::SetProtocol(const nsString& aProtocol)
}
//-----------------------------------------------------------------------------
// Methods that keep alive the WebSocket object when there are
// onopen/onmessage event listeners.
// Methods that keep alive the WebSocket object when:
// 1. the object has registered event listeners that can be triggered
// ("strong event listeners");
// 2. there are outgoing not sent messages.
//-----------------------------------------------------------------------------
void
nsWebSocket::UpdateMustKeepAlive()
{
if (!mCheckThereAreStrongEventListeners) {
if (!mCheckMustKeepAlive) {
return;
}
if (mHasStrongEventListeners) {
if (!mListenerManager ||
((mReadyState != nsIWebSocket::CONNECTING ||
!mListenerManager->HasListenersFor(NS_LITERAL_STRING("open"))) &&
(mReadyState == nsIWebSocket::CLOSED ||
!mListenerManager->HasListenersFor(NS_LITERAL_STRING("message"))))) {
mHasStrongEventListeners = PR_FALSE;
static_cast<nsPIDOMEventTarget*>(this)->Release();
}
} else {
if ((mReadyState == nsIWebSocket::CONNECTING && mListenerManager &&
mListenerManager->HasListenersFor(NS_LITERAL_STRING("open"))) ||
(mReadyState != nsIWebSocket::CLOSED && mListenerManager &&
mListenerManager->HasListenersFor(NS_LITERAL_STRING("message")))) {
mHasStrongEventListeners = PR_TRUE;
static_cast<nsPIDOMEventTarget*>(this)->AddRef();
PRBool shouldKeepAlive = PR_FALSE;
if (mListenerManager) {
switch (mReadyState)
{
case nsIWebSocket::CONNECTING:
{
if (mListenerManager->HasListenersFor(NS_LITERAL_STRING("open")) ||
mListenerManager->HasListenersFor(NS_LITERAL_STRING("message")) ||
mListenerManager->HasListenersFor(NS_LITERAL_STRING("close"))) {
shouldKeepAlive = PR_TRUE;
}
}
break;
case nsIWebSocket::OPEN:
case nsIWebSocket::CLOSING:
{
if (mListenerManager->HasListenersFor(NS_LITERAL_STRING("message")) ||
mListenerManager->HasListenersFor(NS_LITERAL_STRING("close")) ||
mConnection->HasOutgoingMessages()) {
shouldKeepAlive = PR_TRUE;
}
}
break;
case nsIWebSocket::CLOSED:
{
shouldKeepAlive =
(!mTriggeredCloseEvent &&
mListenerManager->HasListenersFor(NS_LITERAL_STRING("close")));
}
}
}
if (mKeepingAlive && !shouldKeepAlive) {
mKeepingAlive = PR_FALSE;
static_cast<nsPIDOMEventTarget*>(this)->Release();
} else if (!mKeepingAlive && shouldKeepAlive) {
mKeepingAlive = PR_TRUE;
static_cast<nsPIDOMEventTarget*>(this)->AddRef();
}
}
void
nsWebSocket::DontKeepAliveAnyMore()
{
if (mHasStrongEventListeners) {
mCheckThereAreStrongEventListeners = PR_FALSE;
mHasStrongEventListeners = PR_FALSE;
if (mKeepingAlive) {
mKeepingAlive = PR_FALSE;
static_cast<nsPIDOMEventTarget*>(this)->Release();
}
mCheckMustKeepAlive = PR_FALSE;
}
NS_IMETHODIMP
@ -3431,8 +3474,8 @@ nsWebSocket::Close()
}
if (mReadyState == nsIWebSocket::CONNECTING) {
// FailConnection() can release the object if there are no strong event
// listeners, so we keep a reference before calling it
// FailConnection() can release the object, so we keep a reference
// before calling it
nsRefPtr<nsWebSocket> kungfuDeathGrip = this;
mConnection->FailConnection();

View File

@ -115,12 +115,12 @@ protected:
// called from mConnection accordingly to the situation
void SetReadyState(PRUint16 aNewReadyState);
// if there are onopen or onmessage event listeners ("strong event listeners")
// then this method keeps the object alive when js doesn't have strong
// references to it.
// if there are "strong event listeners" (see comment in nsWebSocket.cpp) or
// outgoing not sent messages then this method keeps the object alive
// when js doesn't have strong references to it.
void UpdateMustKeepAlive();
// Releases, if necessary, the strong event listeners. ATTENTION, when calling
// this method the object can be released (and possibly collected).
// ATTENTION, when calling this method the object can be released
// (and possibly collected).
void DontKeepAliveAnyMore();
nsRefPtr<nsDOMEventListenerWrapper> mOnOpenListener;
@ -133,8 +133,9 @@ protected:
PRPackedBool mSecure; // if true it is using SSL and the wss scheme,
// otherwise it is using the ws scheme with no SSL
PRPackedBool mHasStrongEventListeners;
PRPackedBool mCheckThereAreStrongEventListeners;
PRPackedBool mKeepingAlive;
PRPackedBool mCheckMustKeepAlive;
PRPackedBool mTriggeredCloseEvent;
nsCString mAsciiHost; // hostname
PRUint32 mPort;

View File

@ -403,6 +403,9 @@ _TEST_FILES2 = \
file_websocket_wsh.py \
file_websocket_http_resource.txt \
test_bug574596.html \
test_x-frame-options.html \
file_x-frame-options_main.html \
file_x-frame-options_page.sjs \
$(NULL)
# This test fails on the Mac for some reason

View File

@ -0,0 +1,19 @@
<html>
<head>
<title>X-Frame-Options tests</title>
<script type="text/javascript">
// This frame loading means all subframes have either loaded or errored out. We
// can now tell the test harness to check each subframe for the expected result.
window.addEventListener('load', parent.testFramesLoaded, false);
</script>
</head>
<body>
<iframe id="control1" src="http://mochi.test:8888/tests/content/base/test/file_x-frame-options_page.sjs?testid=control1"></iframe><br>
<iframe id="control2" src="http://example.com/tests/content/base/test/file_x-frame-options_page.sjs?testid=control2"></iframe><br>
<iframe id="deny" src="http://mochi.test:8888/tests/content/base/test/file_x-frame-options_page.sjs?testid=deny&xfo=deny"></iframe><br>
<iframe id="sameorigin1" src="http://mochi.test:8888/tests/content/base/test/file_x-frame-options_page.sjs?testid=sameorigin1&xfo=sameorigin"></iframe><br>
<iframe id="sameorigin2" src="http://example.com/tests/content/base/test/file_x-frame-options_page.sjs?testid=sameorigin2&xfo=sameorigin"></iframe><br>
</body>
</html>

View File

@ -0,0 +1,25 @@
// SJS file for X-Frame-Options mochitests
function handleRequest(request, response)
{
var query = {};
request.queryString.split('&').forEach(function (val) {
var [name, value] = val.split('=');
query[name] = unescape(value);
});
response.setHeader("Cache-Control", "no-cache", false);
response.setHeader("Content-Type", "text/html", false);
// X-Frame-Options header value
if (query['xfo'] == "deny") {
for (var i = 0 ; i < 0x7fffff ; i++) { }
response.setHeader("X-Frame-Options", "DENY", false);
}
else if (query['xfo'] == "sameorigin") {
response.setHeader("X-Frame-Options", "SAMEORIGIN", false);
}
// from the test harness we'll be checking for the presence of this element
// to test if the page loaded
response.write("<h1 id=\"test\">" + query["testid"] + "</h1>");
}

View File

@ -437,7 +437,7 @@ window._test17 = function()
{
var local_ws = new WebSocket("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test 17");
local_ws._testNumber = "local17";
current_test++;
local_ws._testNumber = current_test++;
status_test17 = "started";
@ -510,14 +510,18 @@ window._test20 = function()
{
var local_ws = new WebSocket("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test 20");
local_ws._testNumber = "local20";
current_test++;
local_ws._testNumber = current_test++;
local_ws.onerror = function()
{
ok(false, "onerror called on test " + e.target._testNumber + "!");
};
local_ws.onclose = shouldNotReceiveCloseEvent;
local_ws.onclose = function(e)
{
shouldCloseCleanly(e);
doTest(21);
};
local_ws = null;
window._test20 = null;
@ -527,7 +531,6 @@ window._test20 = function()
function test20()
{
window._test20();
doTest(21);
}
var timeoutTest21;
@ -535,7 +538,7 @@ var timeoutTest21;
window._test21 = function()
{
var local_ws = new WebSocket("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test 21");
current_test++;
local_ws._testNumber = current_test++;
local_ws.onopen = function(e)
{
@ -563,7 +566,11 @@ window._test21 = function()
forcegc();
};
local_ws.onclose = shouldNotReceiveCloseEvent;
local_ws.onclose = function(e)
{
shouldCloseCleanly(e);
doTest(22);
};
local_ws = null;
window._test21 = null;
@ -573,7 +580,6 @@ window._test21 = function()
function test21()
{
window._test21();
doTest(22);
}
function test22()

View File

@ -0,0 +1,50 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for X-Frame-Options response header</title>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<iframe style="width:100%;height:300px;" id="harness"></iframe>
<script class="testbody" type="text/javascript">
var path = "/tests/content/base/test/";
// contains { test_frame_id : expected_result }
var testExpectedResults = { "control1": true,
"control2": true,
"deny": false,
"sameorigin1": true,
"sameorigin2": false
};
var testFramesLoaded = function() {
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
var harness = document.getElementById("harness");
for (var t in testExpectedResults) {
var frame = harness.contentDocument.getElementById(t);
// test if frame loaded by checking for a contentDocument we can access
test = frame.contentDocument.getElementById("test");
is(test != null, testExpectedResults[t], "test "+t);
}
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
// load the test harness
document.getElementById("harness").src = "file_x-frame-options_main.html";
</script>
</pre>
</body>
</html>

View File

@ -109,13 +109,25 @@ Canvas2D_GetStyleHelper(JSContext *cx, JSObject *obj, jsval id, jsval *vp,
return xpc_qsStringToJsval(cx, resultString, vp);
case nsIDOMCanvasRenderingContext2D::CMG_STYLE_PATTERN:
return xpc_qsXPCOMObjectToJsval(lccx, resultInterface, xpc_qsGetWrapperCache(resultInterface),
&NS_GET_IID(nsIDOMCanvasPattern), &interfaces[k_nsIDOMCanvasPattern], vp);
{
nsWrapperCache* cache = xpc_qsGetWrapperCache(resultInterface);
qsObjectHelper helper(ToSupports(resultInterface));
helper.SetNode(resultInterface);
helper.SetCanonical(ToCanonicalSupports(resultInterface));
return xpc_qsXPCOMObjectToJsval(lccx, &helper, cache,
&NS_GET_IID(nsIDOMCanvasPattern),
&interfaces[k_nsIDOMCanvasPattern], vp);
}
case nsIDOMCanvasRenderingContext2D::CMG_STYLE_GRADIENT:
return xpc_qsXPCOMObjectToJsval(lccx, resultInterface, xpc_qsGetWrapperCache(resultInterface),
&NS_GET_IID(nsIDOMCanvasGradient), &interfaces[k_nsIDOMCanvasGradient], vp);
{
nsWrapperCache* cache = xpc_qsGetWrapperCache(resultInterface);
qsObjectHelper helper(ToSupports(resultInterface));
helper.SetNode(resultInterface);
helper.SetCanonical(ToCanonicalSupports(resultInterface));
return xpc_qsXPCOMObjectToJsval(lccx, &helper, cache,
&NS_GET_IID(nsIDOMCanvasGradient),
&interfaces[k_nsIDOMCanvasGradient], vp);
}
default:
return xpc_qsThrowGetterSetterFailed(cx, NS_ERROR_FAILURE, JSVAL_TO_OBJECT(*vp), id);
}

View File

@ -320,9 +320,9 @@ WebGLContext::SetDimensions(PRInt32 width, PRInt32 height)
gl->fViewport(0, 0, mWidth, mHeight);
gl->fClearColor(0.0f, 0.0f, 0.0f, 0.0f);
#ifdef USE_GLES2
gl->fClearDepthf(0.0f);
gl->fClearDepthf(1.0f);
#else
gl->fClearDepth(0.0f);
gl->fClearDepth(1.0f);
#endif
gl->fClearStencil(0);
gl->fClear(LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT | LOCAL_GL_STENCIL_BUFFER_BIT);

View File

@ -74,6 +74,7 @@
#include "nsCSSParser.h"
#include "nsICSSStyleRule.h"
#include "mozilla/css/Declaration.h"
#include "nsComputedDOMStyle.h"
#include "nsStyleSet.h"
@ -2243,28 +2244,36 @@ CreateFontStyleRule(const nsAString& aFont,
nsCSSParser parser;
NS_ENSURE_TRUE(parser, NS_ERROR_OUT_OF_MEMORY);
// aFont is to be parsed as the value of a CSS 'font' shorthand,
// and then any line-height setting in that shorthand is to be
// overridden with "normal". Because of the way style rules are
// stored, it is more efficient to fabricate a text string that
// can be processed in one go with ParseStyleAttribute than to
// make two calls to ParseDeclaration.
nsAutoString styleAttr(NS_LITERAL_STRING("font:"));
styleAttr.Append(aFont);
styleAttr.AppendLiteral(";line-height:normal");
nsCOMPtr<nsICSSStyleRule> rule;
PRBool changed;
nsIPrincipal* principal = aNode->NodePrincipal();
nsIDocument* document = aNode->GetOwnerDoc();
nsIURI* docURL = document->GetDocumentURI();
nsIURI* baseURL = document->GetDocBaseURI();
nsresult rv = parser.ParseStyleAttribute(styleAttr, docURL, baseURL,
principal, aResult);
nsresult rv = parser.ParseStyleAttribute(EmptyString(), docURL, baseURL,
principal, getter_AddRefs(rule));
if (NS_FAILED(rv))
return rv;
(*aResult)->RuleMatched();
rv = parser.ParseProperty(eCSSProperty_font, aFont, docURL, baseURL,
principal, rule->GetDeclaration(), &changed,
PR_FALSE);
if (NS_FAILED(rv))
return rv;
rv = parser.ParseProperty(eCSSProperty_line_height,
NS_LITERAL_STRING("normal"), docURL, baseURL,
principal, rule->GetDeclaration(), &changed,
PR_FALSE);
if (NS_FAILED(rv))
return rv;
rule->RuleMatched();
rule.forget(aResult);
return NS_OK;
}
@ -2299,6 +2308,23 @@ nsCanvasRenderingContext2D::SetFont(const nsAString& font)
if (NS_FAILED(rv))
return rv;
css::Declaration *declaration = rule->GetDeclaration();
// The easiest way to see whether we got a syntax error or whether
// we got 'inherit' or 'initial' is to look at font-size-adjust,
// which the shorthand resets to either 'none' or
// '-moz-system-font'.
// We know the declaration is not !important, so we can use
// GetNormalBlock().
const nsCSSValue *fsaVal =
declaration->GetNormalBlock()->
ValueStorageFor(eCSSProperty_font_size_adjust);
if (!fsaVal || (fsaVal->GetUnit() != eCSSUnit_None &&
fsaVal->GetUnit() != eCSSUnit_System_Font)) {
// We got an all-property value or a syntax error. The spec says
// this value must be ignored.
return NS_OK;
}
rules.AppendObject(rule);
nsStyleSet* styleSet = presShell->StyleSet();
@ -2367,7 +2393,13 @@ nsCanvasRenderingContext2D::SetFont(const nsAString& font)
&style,
presShell->GetPresContext()->GetUserFontSet());
NS_ASSERTION(CurrentState().fontGroup, "Could not get font group");
CurrentState().font = font;
// The font getter is required to be reserialized based on what we
// parsed (including having line-height removed). (Older drafts of
// the spec required font sizes be converted to pixels, but that no
// longer seems to be required.)
declaration->GetValue(eCSSProperty_font, CurrentState().font);
return NS_OK;
}

View File

@ -66,6 +66,7 @@ _TEST_FILES_0 = \
image_green-redirect \
image_green-redirect^headers^ \
test_drawImageIncomplete.html \
test_canvas_font_setter.html \
$(NULL)
# xor and lighter aren't well handled by cairo; they mostly work, but we don't want

View File

@ -0,0 +1,69 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=
-->
<head>
<title>Test for Bug </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=">Mozilla Bug </a>
<canvas id="display" height="200" width="200"></canvas>
<pre id="test">
<script type="application/javascript">
var canvas = document.getElementById("display");
var cx = canvas.getContext("2d");
is(cx.font, "10px sans-serif", "initial font of canvas context");
cx.font = "italic 16px sans-serif";
is(cx.font, "italic 16px sans-serif", "valid font should round-trip");
cx.font = "bold 12px serif; background: green";
is(cx.font, "italic 16px sans-serif", "invalid font should be ignored");
cx.font = "bold 12px/3.0 serif";
is(cx.font, "bold 12px serif", "line-height should be dropped");
cx.font = "inherit";
is(cx.font, "bold 12px serif", "inherit should be ignored");
cx.font = "boold 18px sans-serif";
is(cx.font, "bold 12px serif", "syntax error should be ignored");
cx.font = "menu";
todo_is(cx.font, "menu", "system fonts should work");
function textmeas() {
return cx.measureText("hello").width;
}
cx.font = "66px serif";
var w_at_66 = textmeas();
cx.font = "20px serif";
var w_at_20 = textmeas();
ok(w_at_66 > w_at_20, "text should be wider at 66px than at 20px");
canvas.style.fontSize = "33px";
cx.font = "2em serif";
is(cx.font, "2em serif", "serialization of em");
is(textmeas(), w_at_66, "em should be relative to canvas font size");
canvas.style.fontSize = "16px";
is(cx.font, "2em serif", "serialization of em");
is(textmeas(), w_at_66,
"em should be relative to canvas font size at time of setting");
document.body.removeChild(canvas);
is(cx.font, "2em serif", "serialization of em");
is(textmeas(), w_at_66,
"em should be relative to canvas font size at time of setting");
canvas.style.fontSize = "33px";
cx.font = "2em serif";
is(cx.font, "2em serif", "serialization of em");
is(textmeas(), w_at_20,
"em should be relative to 10px when canvas not in document");
document.body.appendChild(canvas);
</script>
</pre>
</body>
</html>

View File

@ -458,9 +458,10 @@ nsTextStateManager::ContentInserted(nsIDocument* aDocument,
void
nsTextStateManager::ContentRemoved(nsIDocument* aDocument,
nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer)
nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer,
nsIContent* aPreviousSibling)
{
PRUint32 offset = 0, childOffset = 1;
if (NS_FAILED(nsContentEventHandler::GetFlatTextOffsetOfRange(

View File

@ -42,7 +42,7 @@
class nsXMLEventsElement : public nsXMLElement {
public:
nsXMLEventsElement(nsINodeInfo *aNodeInfo);
nsXMLEventsElement(already_AddRefed<nsINodeInfo> aNodeInfo);
virtual ~nsXMLEventsElement();
NS_FORWARD_NSIDOMNODE(nsXMLElement::)
@ -53,7 +53,7 @@ public:
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
};
nsXMLEventsElement::nsXMLEventsElement(nsINodeInfo *aNodeInfo)
nsXMLEventsElement::nsXMLEventsElement(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsXMLElement(aNodeInfo)
{
}
@ -85,7 +85,8 @@ nsXMLEventsElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, nsIAtom* aPref
NS_IMPL_ELEMENT_CLONE(nsXMLEventsElement)
nsresult
NS_NewXMLEventsElement(nsIContent** aInstancePtrResult, nsINodeInfo *aNodeInfo)
NS_NewXMLEventsElement(nsIContent** aInstancePtrResult,
already_AddRefed<nsINodeInfo> aNodeInfo)
{
nsXMLEventsElement* it = new nsXMLEventsElement(aNodeInfo);
if (!it) {

View File

@ -306,6 +306,8 @@ PRBool nsXMLEventsManager::RemoveListener(nsIContent * aContent)
void nsXMLEventsManager::AddListeners(nsIDocument* aDocument)
{
nsCOMPtr<nsIMutationObserver> kungFuDeathGrip(this);
nsIContent *cur;
for (int i = 0; i < mIncomplete.Count(); ++i) {
cur = mIncomplete[i];
@ -315,41 +317,21 @@ void nsXMLEventsManager::AddListeners(nsIDocument* aDocument)
}
}
void
nsXMLEventsManager::BeginUpdate(nsIDocument* aDocument, nsUpdateType aUpdateType) {}
void
nsXMLEventsManager::EndUpdate(nsIDocument* aDocument, nsUpdateType aUpdateType) {}
void
nsXMLEventsManager::NodeWillBeDestroyed(const nsINode* aNode)
{
nsCOMPtr<nsIMutationObserver> kungFuDeathGrip(this);
mIncomplete.Clear();
mListeners.Enumerate(EnumAndUnregisterListener, this);
mListeners.Clear();
}
void
nsXMLEventsManager::BeginLoad(nsIDocument* aDocument) {}
void
nsXMLEventsManager::EndLoad(nsIDocument* aDocument)
{
AddListeners(aDocument);
}
NS_IMPL_NSIDOCUMENTOBSERVER_STATE_STUB(nsXMLEventsManager)
void
nsXMLEventsManager::CharacterDataWillChange(nsIDocument* aDocument,
nsIContent* aContent,
CharacterDataChangeInfo* aInfo) {}
void
nsXMLEventsManager::CharacterDataChanged(nsIDocument* aDocument,
nsIContent* aContent,
CharacterDataChangeInfo* aInfo) {}
void
nsXMLEventsManager::AttributeWillChange(nsIDocument* aDocument,
nsIContent* aContent,
PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aModType) {}
void
nsXMLEventsManager::AttributeChanged(nsIDocument* aDocument,
nsIContent* aContent,
@ -357,6 +339,8 @@ nsXMLEventsManager::AttributeChanged(nsIDocument* aDocument,
nsIAtom* aAttribute,
PRInt32 aModType)
{
nsCOMPtr<nsIMutationObserver> kungFuDeathGrip(this);
if (aNameSpaceID == kNameSpaceID_XMLEvents &&
(aAttribute == nsGkAtoms::event ||
aAttribute == nsGkAtoms::handler ||
@ -412,10 +396,11 @@ nsXMLEventsManager::ContentInserted(nsIDocument* aDocument,
}
void
nsXMLEventsManager::ContentRemoved(nsIDocument* aDocument,
nsXMLEventsManager::ContentRemoved(nsIDocument* aDocument,
nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer)
PRInt32 aIndexInContainer,
nsIContent* aPreviousSibling)
{
if (!aChild || !aChild->IsElement())
return;
@ -423,6 +408,8 @@ nsXMLEventsManager::ContentRemoved(nsIDocument* aDocument,
//And to remember: the same observer can be referenced by many
//XMLEventsListeners
nsCOMPtr<nsIMutationObserver> kungFuDeathGrip(this);
//If the content was an XML Events observer or handler
mListeners.Enumerate(EnumAndSetIncomplete, aChild);
@ -434,14 +421,6 @@ nsXMLEventsManager::ContentRemoved(nsIDocument* aDocument,
PRUint32 count = aChild->GetChildCount();
for (PRUint32 i = 0; i < count; ++i) {
ContentRemoved(aDocument, aChild, aChild->GetChildAt(i), i);
ContentRemoved(aDocument, aChild, aChild->GetChildAt(i), i, aChild->GetPreviousSibling());
}
}
void
nsXMLEventsManager::ParentChainChanged(nsIContent *aContent)
{
}
NS_IMPL_NSIDOCUMENTOBSERVER_STYLE_STUB(nsXMLEventsManager)

Some files were not shown because too many files have changed in this diff Show More