This commit is contained in:
Dan Witte 2010-08-23 17:30:33 -07:00
Родитель baac82f166 730b84ed87
Коммит f834c3dbbb
441 изменённых файлов: 7324 добавлений и 8157 удалений

Просмотреть файл

@ -52,3 +52,4 @@ dba2abb7db57078c5a4810884834d3056a5d56c2 last-mozilla-central
0327e126ea245112c0aa7283fee154e084866fb5 bsmedberg-static-xpcom-registration-base
0327e126ea245112c0aa7283fee154e084866fb5 bsmedberg-static-xpcom-registration-base
2f83edbbeef0de7dd901411d270da61106c8afae bsmedberg-static-xpcom-registration-base
138f593553b66c9f815e8f57870c19d6347f7702 UPDATE_PACKAGING_R12

Просмотреть файл

@ -103,6 +103,11 @@
label="&helpReleaseNotes.label;"
oncommand="openReleaseNotes()"
onclick="checkForMiddleClick(this, event);"/>
<menuitem id="feedbackPage"
accesskey="&helpFeedbackPage.accesskey;"
label="&helpFeedbackPage.label;"
oncommand="openFeedbackPage()"
onclick="checkForMiddleClick(this, event);"/>
<menuseparator id="updateSeparator"/>
#ifdef MOZ_UPDATER
<menuitem id="checkForUpdates"

Просмотреть файл

@ -559,10 +559,10 @@
label="&subscribeToPageMenuitem.label;"
oncommand="return FeedHandler.subscribeToFeed(null, event);"
onclick="checkForMiddleClick(this, event);"
disabled="true"/>
observes="singleFeedMenuitemState"/>
<menu id="subscribeToPageMenupopup"
label="&subscribeToPageMenupopup.label;"
hidden="true">
observes="multipleFeedsMenuState">
<menupopup id="subscribeToPageSubmenuMenupopup"
onpopupshowing="return FeedHandler.buildFeedList(event.target);"
oncommand="return FeedHandler.subscribeToFeed(null, event);"

Просмотреть файл

@ -189,6 +189,8 @@
<broadcaster id="blockedPopupsSeparator"/>
<broadcaster id="isImage"/>
<broadcaster id="isFrameImage"/>
<broadcaster id="singleFeedMenuitemState" disabled="true"/>
<broadcaster id="multipleFeedsMenuState" hidden="true"/>
</broadcasterset>
<keyset id="mainKeyset">

Просмотреть файл

@ -6638,16 +6638,22 @@ var FeedHandler = {
}
},
get _feedMenuitem() {
delete this._feedMenuitem;
return this._feedMenuitem = document.getElementById("singleFeedMenuitemState");
},
get _feedMenupopup() {
delete this._feedMenupopup;
return this._feedMenupopup = document.getElementById("multipleFeedsMenuState");
},
/**
* Update the browser UI to show whether or not feeds are available when
* a page is loaded or the user switches tabs to a page that has feeds.
*/
updateFeeds: function() {
var feedButton = document.getElementById("feed-button");
if (!this._feedMenuitem)
this._feedMenuitem = document.getElementById("subscribeToPageMenuitem");
if (!this._feedMenupopup)
this._feedMenupopup = document.getElementById("subscribeToPageMenupopup");
var feeds = gBrowser.selectedBrowser.feeds;
if (!feeds || feeds.length == 0) {

Просмотреть файл

@ -620,11 +620,11 @@
label="&subscribeToPageMenuitem.label;"
oncommand="return FeedHandler.subscribeToFeed(null, event);"
onclick="checkForMiddleClick(this, event);"
disabled="true"/>
observes="singleFeedMenuitemState"/>
<menu id="appmenu_subscribeToPageMenu"
class="menu-iconic"
label="&subscribeToPageMenupopup.label;"
hidden="true">
observes="multipleFeedsMenuState">
<menupopup id="appmenu_subscribeToPageMenupopup"
onpopupshowing="return FeedHandler.buildFeedList(event.target);"
oncommand="return FeedHandler.subscribeToFeed(null, event);"

Просмотреть файл

@ -127,7 +127,7 @@ function test3() {
new TabOpenListener("about:addons", test4, prepareTest5);
EventUtils.synthesizeMouse(gTestBrowser.contentDocument.getElementById("test"),
0, 0, {}, gTestBrowser.contentWindow);
5, 5, {}, gTestBrowser.contentWindow);
}
function test4(tab, win) {

Просмотреть файл

@ -418,6 +418,47 @@ var tests = [
gBrowser.selectedTab = this.oldSelectedTab;
}
},
// Test that nested icon nodes correctly activate popups
{ // Test #14
run: function() {
// Add a temporary box as the anchor with a button
this.box = document.createElement("box");
PopupNotifications.iconBox.appendChild(this.box);
let button = document.createElement("button");
button.setAttribute("label", "Please click me!");
this.box.appendChild(button);
// The notification should open up on the box
this.notifyObj = new basicNotification();
this.notifyObj.anchorID = this.box.id = "nested-box";
this.notifyObj.options = {dismissed: true};
this.notification = showNotification(this.notifyObj);
EventUtils.synthesizeMouse(button, 1, 1, {});
},
onShown: function(popup) {
checkPopup(popup, this.notifyObj);
dismissNotification(popup);
},
onHidden: function(popup) {
this.notification.remove();
this.box.parentNode.removeChild(this.box);
}
},
// Test that popupnotifications without popups have anchor icons shown
{ // Test #15
run: function() {
let notifyObj = new basicNotification();
notifyObj.anchorID = "geo-notification-icon";
notifyObj.options = {neverShow: true};
showNotification(notifyObj);
},
updateNotShowing: function() {
isnot(document.getElementById("geo-notification-icon").boxObject.width, 0,
"geo anchor should be visible");
}
},
];
function showNotification(notifyObj) {

Просмотреть файл

@ -11,7 +11,7 @@ Cc["@mozilla.org/moz/jssubscript-loader;1"].getService(Ci.mozIJSSubScriptLoader)
function test() {
var hoursSinceMidnight = new Date().getHours();
var minutesSinceMidnight = new Date().getMinutes();
var minutesSinceMidnight = hoursSinceMidnight * 60 + new Date().getMinutes();
setupHistory();
setupFormHistory();

Просмотреть файл

@ -452,6 +452,15 @@ function openTroubleshootingPage()
openUILinkIn("about:support", "tab");
}
/**
* Opens the feedback page for this version of the application.
*/
function openFeedbackPage()
{
openUILinkIn("http://input.mozilla.com/sad", "tab");
}
#ifdef MOZ_UPDATER
/**
* Opens the update manager and checks for updates to the application.

Просмотреть файл

@ -1,3 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- ***** BEGIN LICENSE BLOCK *****
- Version: MPL 1.1/GPL 2.0/LGPL 2.1
-
@ -34,7 +35,6 @@
-
- ***** END LICENSE BLOCK ***** -->
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE bindings [
<!ENTITY % feedDTD
SYSTEM "chrome://browser/locale/feeds/subscribe.dtd">

Просмотреть файл

@ -57,6 +57,8 @@ _TEST_FILES = test_bug408328.html \
bug368464-data.xml \
test_bug494328.html \
bug494328-data.xml \
test_bug589543.html \
bug589543-data.xml \
test_registerHandler.html \
$(NULL)

Просмотреть файл

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Example Feed</title>
<link href="http://example.org/"/>
<updated>2010-08-22T18:30:02Z</updated>
<author>
<name>John Doe</name>
</author>
<id>urn:uuid:e2df8375-99be-4848-b05e-b9d407555267</id>
<entry>
<title>Item</title>
<link href="http://example.org/first"/>
<id>urn:uuid:9e0f4bed-33d3-4a9d-97ab-ecaa31b3f14a</id>
<updated>2010-08-22T18:30:02Z</updated>
<summary>Some text.</summary>
</entry>
</feed>

Просмотреть файл

@ -0,0 +1,35 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=589543
-->
<head>
<title>Test feed preview subscribe UI</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=589543">Mozilla Bug 589543</a>
<p id="display"><iframe id="testFrame" src="bug589543-data.xml"></iframe></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
/** Test for Bug 589543 **/
SimpleTest.waitForExplicitFinish();
addLoadEvent(function() {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var doc = $("testFrame").contentDocument;
var daddy = doc.getElementById("feedSubscribeLine");
var popup = doc.getAnonymousElementByAttribute(daddy, "anonid", "handlersMenuPopup");
isnot(popup, null, "Feed preview should have a handlers popup");
});
addLoadEvent(SimpleTest.finish);
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -48,7 +48,7 @@ MOZ_MORKREADER=1
MOZ_SAFE_BROWSING=1
MOZ_SERVICES_SYNC=1
MOZ_APP_VERSION=$FIREFOX_VERSION
MOZ_EXTENSIONS_DEFAULT=" gnomevfs reporter"
MOZ_EXTENSIONS_DEFAULT=" gnomevfs"
# MOZ_APP_DISPLAYNAME will be set by branding/configure.sh
MOZ_BRANDING_DIRECTORY=browser/branding/nightly
MOZ_OFFICIAL_BRANDING_DIRECTORY=other-licenses/branding/firefox

Просмотреть файл

@ -412,7 +412,6 @@
#endif
@BINPATH@/chrome/toolkit@JAREXT@
@BINPATH@/chrome/toolkit.manifest
@BINPATH@/@PREF_DIR@/reporter.js
#ifdef XP_UNIX
#ifndef XP_MACOSX
@BINPATH@/chrome/icons/default/default16.png

Просмотреть файл

@ -74,6 +74,7 @@ components/xptitemp.dat
defaults/pref/all.js
defaults/pref/bug259708.js
defaults/pref/bug307259.js
defaults/pref/reporter.js
defaults/pref/security-prefs.js
defaults/pref/winpref.js
defaults/pref/xpinstall.js
@ -629,7 +630,6 @@ xpicleanup@BIN_SUFFIX@
defaults/pref/firefox-branding.js
defaults/pref/firefox.js
defaults/pref/firefox-l10n.js
defaults/pref/reporter.js
defaults/pref/services-sync.js
defaults/profile/bookmarks.html
defaults/profile/chrome/userChrome-example.css

Просмотреть файл

@ -187,7 +187,6 @@ libs-%:
$(NSINSTALL) -D $(DIST)/install
@$(MAKE) -C ../../toolkit/locales libs-$* BOTH_MANIFESTS=1
@$(MAKE) -C ../../services/sync/locales AB_CD=$* XPI_NAME=locale-$* BOTH_MANIFESTS=1
@$(MAKE) -C ../../extensions/reporter/locales libs AB_CD=$* XPI_NAME=locale-$* BOTH_MANIFESTS=1
@$(MAKE) -C ../../extensions/spellcheck/locales AB_CD=$* XPI_NAME=locale-$* BOTH_MANIFESTS=1
@$(MAKE) libs AB_CD=$* XPI_NAME=locale-$* PREF_DIR=defaults/pref BOTH_MANIFESTS=1
@$(MAKE) -C $(DEPTH)/$(MOZ_BRANDING_DIRECTORY)/locales AB_CD=$* XPI_NAME=locale-$* BOTH_MANIFESTS=1

Просмотреть файл

@ -1,10 +1,13 @@
af
ak
ar
as
be
bg
bn-BD
bn-IN
br
bs
ca
cs
cy
@ -12,6 +15,7 @@ da
de
el
en-GB
en-ZA
eo
es-AR
es-ES
@ -29,6 +33,7 @@ he
hi-IN
hr
hu
hy-AM
id
is
it
@ -38,6 +43,7 @@ ka
kn
ko
ku
lg
lt
lv
mk
@ -47,6 +53,7 @@ mr
nb-NO
nl
nn-NO
nso
oc
or
pa-IN
@ -59,6 +66,7 @@ ru
si
sk
sl
son
sq
sr
sv-SE

Просмотреть файл

@ -24,6 +24,9 @@
<!ENTITY helpTroubleshootingInfo.label "Troubleshooting Information">
<!ENTITY helpTroubleshootingInfo.accesskey "T">
<!ENTITY helpFeedbackPage.label "Submit Feedback…">
<!ENTITY helpFeedbackPage.accesskey "S">
<!ENTITY updateCmd.label "Check for Updates…">
<!ENTITY preferencesCmdMac.label "Preferences…">

Просмотреть файл

@ -159,6 +159,7 @@ class Automation(object):
def __init__(self):
self.log = _log
self.lastTestSeen = "automation.py"
self.haveDumpedScreen = False
def setServerInfo(self,
webServer = _DEFAULT_WEB_SERVER,
@ -655,8 +656,34 @@ user_pref("camino.use_system_proxy_settings", false); // Camino-only, harmless t
def killPid(self, pid):
os.kill(pid, signal.SIGKILL)
if UNIXISH:
def dumpScreen(self, utilityPath):
self.haveDumpedScreen = True;
screentopng = os.path.join(utilityPath, "screentopng")
try:
dumper = self.Process([screentopng], bufsize=-1,
stdout=subprocess.PIPE, close_fds=True)
except OSError, err:
self.log.info("Failed to start %s for screenshot: %s",
screentopng, err.strerror)
return
image = dumper.stdout.read()
status = dumper.wait()
if status != 0:
self.log.info("screentopng exited with code %d", status)
return
import base64
encoded = base64.b64encode(image)
self.log.info("SCREENSHOT: data:image/png;base64,%s", encoded)
def killAndGetStack(self, proc, utilityPath, debuggerInfo):
"""Kill the process, preferrably in a way that gets us a stack trace."""
if self.UNIXISH and not debuggerInfo and not self.haveDumpedScreen:
self.dumpScreen(utilityPath)
if self.CRASHREPORTER and not debuggerInfo:
if self.UNIXISH:
# ABRT will get picked up by Breakpad's signal handler
@ -710,6 +737,9 @@ user_pref("camino.use_system_proxy_settings", false); // Camino-only, harmless t
if stackFixerFunction:
line = stackFixerFunction(line)
self.log.info(line.rstrip())
if self.UNIXISH and not debuggerInfo and not self.haveDumpedScreen and "TEST-UNEXPECTED-FAIL" in line and "Test timed out." in line:
self.dumpScreen(utilityPath)
(line, didTimeout) = self.readWithTimeout(logsource, timeout)
if not hitMaxTime and maxTime and datetime.now() - startTime > timedelta(seconds = maxTime):
# Kill the application, but continue reading from stack fixer so as not to deadlock on stackFixerProcess.wait().

Просмотреть файл

@ -99,7 +99,6 @@ MOZ_DEBUG_DISABLE_DEFS = @MOZ_DEBUG_DISABLE_DEFS@
MOZ_DEBUG_FLAGS = @MOZ_DEBUG_FLAGS@
MOZ_DEBUG_LDFLAGS=@MOZ_DEBUG_LDFLAGS@
MOZ_EXTENSIONS = @MOZ_EXTENSIONS@
MOZ_IMG_DECODERS= @MOZ_IMG_DECODERS@
MOZ_IMG_ENCODERS= @MOZ_IMG_ENCODERS@
MOZ_JSDEBUGGER = @MOZ_JSDEBUGGER@
MOZ_IPC = @MOZ_IPC@
@ -313,6 +312,7 @@ XLDFLAGS = @XLDFLAGS@
XLIBS = @XLIBS@
XEXT_LIBS = @XEXT_LIBS@
XCOMPOSITE_LIBS = @XCOMPOSITE_LIBS@
XSS_LIBS = @XSS_LIBS@
WIN_TOP_SRC = @WIN_TOP_SRC@
CYGWIN_WRAPPER = @CYGWIN_WRAPPER@

Просмотреть файл

@ -891,6 +891,7 @@ wx/xrc/xmlres.h
X11/cursorfont.h
X11/extensions/Print.h
X11/extensions/shape.h
X11/extensions/scrnsaver.h
X11/extensions/XIElib.h
X11/extensions/XShm.h
X11/extensions/Xrender.h

Просмотреть файл

@ -3470,6 +3470,14 @@ else
AC_DEFINE(HAVE_XSHM)
fi
dnl ========================================================
dnl = Check for Xss
dnl ========================================================
AC_CHECK_HEADER(X11/extensions/scrnsaver.h,
AC_CHECK_LIB(Xss, XScreenSaverQueryInfo,
[XSS_LIBS="-lXss $XEXT_LIBS $XLIBS"
AC_DEFINE(HAVE_LIBXSS)],, $XEXT_LIBS $XLIBS))
dnl ========================================================
dnl = Check for XIE
dnl ========================================================
@ -3534,6 +3542,7 @@ AC_SUBST(XLDFLAGS)
AC_SUBST(XLIBS)
AC_SUBST(XEXT_LIBS)
AC_SUBST(XT_LIBS)
AC_SUBST(XSS_LIBS)
AC_MSG_CHECKING(for ARM SIMD support in compiler)
AC_TRY_COMPILE([],
@ -4876,7 +4885,6 @@ MOZ_ACTIVEX_SCRIPTING_SUPPORT=
MOZ_BRANDING_DIRECTORY=
MOZ_OFFICIAL_BRANDING=
MOZ_FEEDS=1
MOZ_IMG_DECODERS_DEFAULT="png gif jpeg bmp icon"
MOZ_IMG_ENCODERS_DEFAULT="png jpeg"
MOZ_INSTALLER=1
MOZ_IPC=1
@ -6309,41 +6317,6 @@ for extension in $MOZ_EXTENSIONS; do
fi
done
dnl ========================================================
dnl Image decoders
dnl ========================================================
case "$MOZ_WIDGET_TOOLKIT" in
beos|windows|os2|mac|cocoa)
;;
*)
if test -z "$MOZ_ENABLE_GTK2" -a -z "$MOZ_ENABLE_QT"; then
MOZ_IMG_DECODERS_DEFAULT=`echo $MOZ_IMG_DECODERS_DEFAULT | sed -e 's|icon||'`
fi
;;
esac
MOZ_ARG_ENABLE_STRING(image-decoders,
[ --enable-image-decoders[={mod1,mod2,default,all,none}]
Enable specific image decoders],
[ for option in `echo $enableval | sed 's/,/ /g'`; do
if test "$option" = "yes" -o "$option" = "all"; then
MOZ_IMG_DECODERS="$MOZ_IMG_DECODERS $MOZ_IMG_DECODERS_DEFAULT"
elif test "$option" = "no" -o "$option" = "none"; then
MOZ_IMG_DECODERS=""
elif test "$option" = "default"; then
MOZ_IMG_DECODERS="$MOZ_IMG_DECODERS $MOZ_IMG_DECODERS_DEFAULT"
elif test `echo "$option" | grep -c \^-` != 0; then
option=`echo $option | sed 's/^-//'`
MOZ_IMG_DECODERS=`echo "$MOZ_IMG_DECODERS" | sed "s/ ${option}//"`
else
MOZ_IMG_DECODERS="$MOZ_IMG_DECODERS $option"
fi
done],
MOZ_IMG_DECODERS="$MOZ_IMG_DECODERS_DEFAULT")
dnl Dupes are removed in the encoder section because it will also add decoders
dnl ========================================================
dnl Image encoders
dnl ========================================================
@ -6369,7 +6342,6 @@ done],
MOZ_IMG_ENCODERS="$MOZ_IMG_ENCODERS_DEFAULT")
dnl Remove dupes
MOZ_IMG_DECODERS=`${PERL} ${srcdir}/build/unix/uniq.pl ${MOZ_IMG_DECODERS}`
MOZ_IMG_ENCODERS=`${PERL} ${srcdir}/build/unix/uniq.pl ${MOZ_IMG_ENCODERS}`
dnl ========================================================
@ -8726,7 +8698,6 @@ AC_SUBST(MOZ_DEBUG_FLAGS)
AC_SUBST(MOZ_DEBUG_LDFLAGS)
AC_SUBST(WARNINGS_AS_ERRORS)
AC_SUBST(MOZ_EXTENSIONS)
AC_SUBST(MOZ_IMG_DECODERS)
AC_SUBST(MOZ_IMG_ENCODERS)
AC_SUBST(MOZ_JSDEBUGGER)
AC_SUBST(MOZ_PLUGINS)

Просмотреть файл

@ -206,7 +206,9 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_XTFSERVICE_CID);
#include "nsChannelPolicy.h"
#include "nsIContentSecurityPolicy.h"
#include "nsContentDLF.h"
#ifdef MOZ_MEDIA
#include "nsHTMLMediaElement.h"
#endif
using namespace mozilla::dom;
using namespace mozilla::layers;

Просмотреть файл

@ -535,6 +535,7 @@ nsFrameScriptExecutor::DestroyCx()
JS_DestroyContext(mCx);
}
mCx = nsnull;
mGlobal = nsnull;
}
static PLDHashOperator

Просмотреть файл

@ -219,6 +219,10 @@ nsInProcessTabChildGlobal::DelayedDisconnect()
static_cast<nsFrameMessageManager*>(mMessageManager.get())->Disconnect();
mMessageManager = nsnull;
}
if (mListenerManager) {
mListenerManager->Disconnect();
}
if (!mLoadingScript) {
if (mCx) {
DestroyCx();

Просмотреть файл

@ -38,7 +38,7 @@ function loadTestImage() {
var img1 = new Image();
img1.onload = function() { img1loaded = true; }
img1.onerror = function() {
is(img2errored, false, "Image 3 should not error before image 2");
is(img2errored, false, "Image 2 should not error before image 1");
img1errored = true;
}
img1.src = window.location.href + "?image1=true";

Просмотреть файл

@ -1887,7 +1887,7 @@ nsCanvasRenderingContext2D::ShadowInitialize(const gfxRect& extents, gfxAlphaBox
blurRadius.height, blurRadius.width);
drawExtents = drawExtents.Intersect(clipExtents - CurrentState().shadowOffset);
gfxContext* ctx = blur.Init(drawExtents, blurRadius, nsnull, nsnull);
gfxContext* ctx = blur.Init(drawExtents, gfxIntSize(0,0), blurRadius, nsnull, nsnull);
if (!ctx)
return nsnull;

Просмотреть файл

@ -101,8 +101,8 @@ PR_STATIC_ASSERT((PRUint32)eButtonElementTypesMax < (PRUint32)NS_FORM_INPUT_ELEM
PR_STATIC_ASSERT((PRUint32)eInputElementTypesMax < 1<<8);
#define NS_IFORMCONTROL_IID \
{ 0xc2f7723a, 0x106a, 0x47ef, \
{ 0xa9, 0xff, 0x4b, 0x4f, 0x73, 0x47, 0xe7, 0xa6 } }
{ 0x218eb090, 0x32eb, 0x4e2a, \
{ 0x96, 0x42, 0xcd, 0xcd, 0x33, 0xae, 0xdb, 0x95 } }
/**
* Interface which all form controls (e.g. buttons, checkboxes, text,
@ -207,6 +207,12 @@ public:
* @return Whether this is a labelable form control.
*/
virtual PRBool IsLabelableControl() const = 0;
/**
* Returns true if this is a submittable form control.
* @return Whether this is a submittable form control.
*/
virtual PRBool IsSubmittableControl() const = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIFormControl, NS_IFORMCONTROL_IID)

Просмотреть файл

@ -97,4 +97,11 @@ NS_GetRadioGetCheckedChangedVisitor(PRBool* aCheckedChanged,
nsIFormControl* aExcludeElement,
nsIRadioVisitor** aVisitor);
/**
* This visitor will make sure all radio into the group updates their
* value missing validity state.
*/
nsIRadioVisitor*
NS_GetRadioUpdateValueMissingVisitor(PRBool aNotify);
#endif // nsIRadioVisitor_h___

Просмотреть файл

@ -194,6 +194,11 @@ public:
*/
NS_IMETHOD_(void) SetPlaceholderClass(PRBool aVisible, PRBool aNotify) = 0;
/**
* Callback called whenever the value is changed.
*/
NS_IMETHOD_(void) OnValueChanged(PRBool aNotify) = 0;
static const PRInt32 DEFAULT_COLS = 20;
static const PRInt32 DEFAULT_ROWS = 1;
static const PRInt32 DEFAULT_ROWS_TEXTAREA = 2;

Просмотреть файл

@ -110,10 +110,9 @@ CPPSRCS = \
nsHTMLTableRowElement.cpp \
nsHTMLTableSectionElement.cpp \
nsHTMLTextAreaElement.cpp \
nsHTMLTimeRanges.cpp \
nsHTMLTitleElement.cpp \
nsDOMValidityState.cpp \
nsConstraintValidation.cpp \
nsIConstraintValidation.cpp \
$(NULL)
ifdef MOZ_MEDIA
@ -122,6 +121,7 @@ CPPSRCS += \
nsHTMLMediaElement.cpp \
nsHTMLMediaError.cpp \
nsHTMLSourceElement.cpp \
nsHTMLTimeRanges.cpp \
nsHTMLVideoElement.cpp \
$(NULL)
endif

Просмотреть файл

@ -1,143 +0,0 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Mozilla Foundation
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Mounir Lamouri <mounir.lamouri@mozilla.com> (original author)
*
* 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 ***** */
#ifndef nsConstraintValidition_h___
#define nsConstraintValidition_h___
#include "nsDOMValidityState.h"
#include "nsAutoPtr.h"
#include "nsString.h"
class nsGenericHTMLFormElement;
/**
* This interface is used for form elements implementing the
* validity constraint API.
* See: http://dev.w3.org/html5/spec/forms.html#the-constraint-validation-api
*/
class nsConstraintValidation
{
public:
virtual ~nsConstraintValidation();
nsresult GetValidity(nsIDOMValidityState** aValidity);
nsresult GetWillValidate(PRBool* aWillValidate,
nsGenericHTMLFormElement* aElement);
nsresult GetValidationMessage(nsAString & aValidationMessage,
nsGenericHTMLFormElement* aElement);
nsresult CheckValidity(PRBool* aValidity,
nsGenericHTMLFormElement* aElement);
nsresult SetCustomValidity(const nsAString & aError);
virtual PRBool IsValueMissing () { return PR_FALSE; }
virtual PRBool HasTypeMismatch () { return PR_FALSE; }
virtual PRBool HasPatternMismatch() { return PR_FALSE; }
virtual PRBool IsTooLong () { return PR_FALSE; }
virtual PRBool HasRangeUnderflow () { return PR_FALSE; }
virtual PRBool HasRangeOverflow () { return PR_FALSE; }
virtual PRBool HasStepMismatch () { return PR_FALSE; }
PRBool HasCustomError () const;
PRBool IsValid ();
protected:
enum ValidationMessageType
{
VALIDATION_MESSAGE_VALUE_MISSING,
VALIDATION_MESSAGE_TYPE_MISMATCH,
VALIDATION_MESSAGE_PATTERN_MISMATCH,
VALIDATION_MESSAGE_TOO_LONG,
VALIDATION_MESSAGE_RANGE_UNDERFLOW,
VALIDATION_MESSAGE_RANGE_OVERFLOW,
VALIDATION_MESSAGE_STEP_MISMATCH
};
PRBool IsCandidateForConstraintValidation(nsGenericHTMLFormElement* aElement);
virtual PRBool IsBarredFromConstraintValidation() { return PR_FALSE; }
virtual nsresult GetValidationMessage(nsAString& aValidationMessage,
ValidationMessageType aType) {
return NS_OK;
}
nsRefPtr<nsDOMValidityState> mValidity;
nsString mCustomValidity;
};
/**
* Use this macro for class inherit from nsConstraintValidation to forward
* functions to nsConstraintValidation.
*/
#define NS_FORWARD_NSCONSTRAINTVALIDATION \
NS_IMETHOD GetValidity(nsIDOMValidityState** aValidity) { \
return nsConstraintValidation::GetValidity(aValidity); \
} \
NS_IMETHOD GetWillValidate(PRBool* aWillValidate) { \
return nsConstraintValidation::GetWillValidate(aWillValidate, this); \
} \
NS_IMETHOD GetValidationMessage(nsAString& aValidationMessage) { \
return nsConstraintValidation::GetValidationMessage(aValidationMessage, this); \
} \
NS_IMETHOD SetCustomValidity(const nsAString& aError) { \
return nsConstraintValidation::SetCustomValidity(aError); \
} \
NS_IMETHOD CheckValidity(PRBool* aValidity) { \
return nsConstraintValidation::CheckValidity(aValidity, this); \
}
/* Use this macro when class declares functions from nsConstraintValidation */
#define NS_IMPL_NSCONSTRAINTVALIDATION(_from) \
NS_IMETHODIMP _from::GetValidity(nsIDOMValidityState** aValidity) { \
return nsConstraintValidation::GetValidity(aValidity); \
} \
NS_IMETHODIMP _from::GetWillValidate(PRBool* aWillValidate) { \
return nsConstraintValidation::GetWillValidate(aWillValidate, this); \
} \
NS_IMETHODIMP _from::GetValidationMessage(nsAString& aValidationMessage) { \
return nsConstraintValidation::GetValidationMessage(aValidationMessage, this); \
} \
NS_IMETHODIMP _from::SetCustomValidity(const nsAString& aError) { \
return nsConstraintValidation::SetCustomValidity(aError); \
} \
NS_IMETHODIMP _from::CheckValidity(PRBool* aValidity) { \
return nsConstraintValidation::CheckValidity(aValidity, this); \
}
#endif // nsConstraintValidation_h___

Просмотреть файл

@ -38,7 +38,6 @@
#include "nsDOMValidityState.h"
#include "nsDOMClassInfo.h"
#include "nsConstraintValidation.h"
DOMCI_DATA(ValidityState, nsDOMValidityState)
@ -52,7 +51,7 @@ NS_INTERFACE_MAP_BEGIN(nsDOMValidityState)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(ValidityState)
NS_INTERFACE_MAP_END
nsDOMValidityState::nsDOMValidityState(nsConstraintValidation* aConstraintValidation)
nsDOMValidityState::nsDOMValidityState(nsIConstraintValidation* aConstraintValidation)
: mConstraintValidation(aConstraintValidation)
{
}
@ -60,56 +59,56 @@ nsDOMValidityState::nsDOMValidityState(nsConstraintValidation* aConstraintValida
NS_IMETHODIMP
nsDOMValidityState::GetValueMissing(PRBool* aValueMissing)
{
*aValueMissing = mConstraintValidation && mConstraintValidation->IsValueMissing();
*aValueMissing = GetValidityState(nsIConstraintValidation::VALIDITY_STATE_VALUE_MISSING);
return NS_OK;
}
NS_IMETHODIMP
nsDOMValidityState::GetTypeMismatch(PRBool* aTypeMismatch)
{
*aTypeMismatch = mConstraintValidation && mConstraintValidation->HasTypeMismatch();
*aTypeMismatch = GetValidityState(nsIConstraintValidation::VALIDITY_STATE_TYPE_MISMATCH);
return NS_OK;
}
NS_IMETHODIMP
nsDOMValidityState::GetPatternMismatch(PRBool* aPatternMismatch)
{
*aPatternMismatch = mConstraintValidation && mConstraintValidation->HasPatternMismatch();
*aPatternMismatch = GetValidityState(nsIConstraintValidation::VALIDITY_STATE_PATTERN_MISMATCH);
return NS_OK;
}
NS_IMETHODIMP
nsDOMValidityState::GetTooLong(PRBool* aTooLong)
{
*aTooLong = mConstraintValidation && mConstraintValidation->IsTooLong();
*aTooLong = GetValidityState(nsIConstraintValidation::VALIDITY_STATE_TOO_LONG);
return NS_OK;
}
NS_IMETHODIMP
nsDOMValidityState::GetRangeUnderflow(PRBool* aRangeUnderflow)
{
*aRangeUnderflow = mConstraintValidation && mConstraintValidation->HasRangeUnderflow();
*aRangeUnderflow = GetValidityState(nsIConstraintValidation::VALIDITY_STATE_RANGE_UNDERFLOW);
return NS_OK;
}
NS_IMETHODIMP
nsDOMValidityState::GetRangeOverflow(PRBool* aRangeOverflow)
{
*aRangeOverflow = mConstraintValidation && mConstraintValidation->HasRangeOverflow();
*aRangeOverflow = GetValidityState(nsIConstraintValidation::VALIDITY_STATE_RANGE_OVERFLOW);
return NS_OK;
}
NS_IMETHODIMP
nsDOMValidityState::GetStepMismatch(PRBool* aStepMismatch)
{
*aStepMismatch = mConstraintValidation && mConstraintValidation->HasStepMismatch();
*aStepMismatch = GetValidityState(nsIConstraintValidation::VALIDITY_STATE_STEP_MISMATCH);
return NS_OK;
}
NS_IMETHODIMP
nsDOMValidityState::GetCustomError(PRBool* aCustomError)
{
*aCustomError = mConstraintValidation && mConstraintValidation->HasCustomError();
*aCustomError = GetValidityState(nsIConstraintValidation::VALIDITY_STATE_CUSTOM_ERROR);
return NS_OK;
}

Просмотреть файл

@ -39,8 +39,8 @@
#define nsDOMValidityState_h__
#include "nsIDOMValidityState.h"
#include "nsIConstraintValidation.h"
class nsConstraintValidation;
class nsDOMValidityState : public nsIDOMValidityState
{
@ -48,19 +48,32 @@ public:
NS_DECL_ISUPPORTS
NS_DECL_NSIDOMVALIDITYSTATE
friend class nsConstraintValidation;
friend class nsIConstraintValidation;
protected:
// This function should be called by nsConstraintValidation
// to set mConstraintValidation to null to be sure it will not be called.
void Disconnect()
nsDOMValidityState(nsIConstraintValidation* aConstraintValidation);
/**
* This function should be called by nsIConstraintValidation
* to set mConstraintValidation to null to be sure
* it will not be used when the object is destroyed.
*/
inline void Disconnect()
{
mConstraintValidation = nsnull;
}
nsDOMValidityState(nsConstraintValidation* aConstraintValidation);
/**
* Helper function to get a validity state from constraint validation instance.
*/
inline PRBool GetValidityState(nsIConstraintValidation::ValidityStateType aState) const
{
return mConstraintValidation &&
mConstraintValidation->GetValidityState(aState);
}
nsConstraintValidation* mConstraintValidation;
// Weak reference to owner which will call Disconnect() when being destroyed.
nsIConstraintValidation* mConstraintValidation;
};
#endif // nsDOMValidityState_h__

Просмотреть файл

@ -2727,6 +2727,18 @@ nsGenericHTMLFormElement::IsLabelableControl() const
type != NS_FORM_OBJECT;
}
PRBool
nsGenericHTMLFormElement::IsSubmittableControl() const
{
// TODO: keygen should be in that list, see bug 101019.
PRInt32 type = GetType();
return type == NS_FORM_OBJECT ||
type == NS_FORM_TEXTAREA ||
type == NS_FORM_SELECT ||
type & NS_FORM_BUTTON_ELEMENT ||
type & NS_FORM_INPUT_ELEMENT;
}
PRInt32
nsGenericHTMLFormElement::IntrinsicState() const
{

Просмотреть файл

@ -829,6 +829,8 @@ public:
PRBool IsLabelableControl() const;
PRBool IsSubmittableControl() const;
// nsIContent
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,

Просмотреть файл

@ -62,7 +62,7 @@
#include "nsLayoutErrors.h"
#include "nsFocusManager.h"
#include "nsHTMLFormElement.h"
#include "nsConstraintValidation.h"
#include "nsIConstraintValidation.h"
#define NS_IN_SUBMIT_CLICK (1 << 0)
#define NS_OUTER_ACTIVATE_EVENT (1 << 1)
@ -79,7 +79,7 @@ static const nsAttrValue::EnumTable* kButtonDefaultType = &kButtonTypeTable[2];
class nsHTMLButtonElement : public nsGenericHTMLFormElement,
public nsIDOMHTMLButtonElement,
public nsConstraintValidation
public nsIConstraintValidation
{
public:
nsHTMLButtonElement(already_AddRefed<nsINodeInfo> aNodeInfo);
@ -133,8 +133,8 @@ public:
virtual void DoneCreatingElement();
virtual nsXPCClassInfo* GetClassInfo();
// nsConstraintValidation
PRBool IsBarredFromConstraintValidation();
// nsIConstraintValidation
PRBool IsBarredFromConstraintValidation() const;
protected:
virtual PRBool AcceptAutofocus() const
@ -183,14 +183,15 @@ DOMCI_NODE_DATA(HTMLButtonElement, nsHTMLButtonElement)
// QueryInterface implementation for nsHTMLButtonElement
NS_INTERFACE_TABLE_HEAD(nsHTMLButtonElement)
NS_HTML_CONTENT_INTERFACE_TABLE1(nsHTMLButtonElement,
nsIDOMHTMLButtonElement)
NS_HTML_CONTENT_INTERFACE_TABLE2(nsHTMLButtonElement,
nsIDOMHTMLButtonElement,
nsIConstraintValidation)
NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLButtonElement,
nsGenericHTMLFormElement)
NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLButtonElement)
// nsConstraintValidation
NS_IMPL_NSCONSTRAINTVALIDATION(nsHTMLButtonElement)
// nsIConstraintValidation
NS_IMPL_NSICONSTRAINTVALIDATION_EXCEPT_SETCUSTOMVALIDITY(nsHTMLButtonElement)
// nsIDOMHTMLButtonElement
@ -611,9 +612,19 @@ nsresult
nsHTMLButtonElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString* aValue, PRBool aNotify)
{
if (!aValue && aNameSpaceID == kNameSpaceID_None &&
aName == nsGkAtoms::type) {
mType = kButtonDefaultType->value;
if (aNameSpaceID == kNameSpaceID_None &&
aName == nsGkAtoms::type) {
if (!aValue) {
mType = kButtonDefaultType->value;
}
if (aNotify) {
nsIDocument* doc = GetCurrentDoc();
if (doc) {
doc->ContentStatesChanged(this, nsnull,
NS_EVENT_STATE_VALID | NS_EVENT_STATE_INVALID);
}
}
}
return nsGenericHTMLFormElement::AfterSetAttr(aNameSpaceID, aName,
@ -651,13 +662,33 @@ nsHTMLButtonElement::RestoreState(nsPresState* aState)
PRInt32
nsHTMLButtonElement::IntrinsicState() const
{
return NS_EVENT_STATE_OPTIONAL | nsGenericHTMLFormElement::IntrinsicState();
PRInt32 state = nsGenericHTMLFormElement::IntrinsicState();
if (IsCandidateForConstraintValidation()) {
state |= IsValid() ? NS_EVENT_STATE_VALID : NS_EVENT_STATE_INVALID;
}
return state | NS_EVENT_STATE_OPTIONAL;
}
// nsConstraintValidation
// nsIConstraintValidation
NS_IMETHODIMP
nsHTMLButtonElement::SetCustomValidity(const nsAString& aError)
{
nsIConstraintValidation::SetCustomValidity(aError);
nsIDocument* doc = GetCurrentDoc();
if (doc) {
doc->ContentStatesChanged(this, nsnull, NS_EVENT_STATE_INVALID |
NS_EVENT_STATE_VALID);
}
return NS_OK;
}
PRBool
nsHTMLButtonElement::IsBarredFromConstraintValidation()
nsHTMLButtonElement::IsBarredFromConstraintValidation() const
{
return (mType == NS_FORM_BUTTON_BUTTON ||
mType == NS_FORM_BUTTON_RESET);

Просмотреть файл

@ -41,12 +41,12 @@
#include "nsStyleConsts.h"
#include "nsIForm.h"
#include "nsIFormControl.h"
#include "nsConstraintValidation.h"
#include "nsIConstraintValidation.h"
class nsHTMLFieldSetElement : public nsGenericHTMLFormElement,
public nsIDOMHTMLFieldSetElement,
public nsConstraintValidation
public nsIConstraintValidation
{
public:
nsHTMLFieldSetElement(already_AddRefed<nsINodeInfo> aNodeInfo);
@ -74,8 +74,8 @@ public:
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
virtual nsXPCClassInfo* GetClassInfo();
// nsConstraintValidation
PRBool IsBarredFromConstraintValidation() { return PR_TRUE; };
// nsIConstraintValidation
PRBool IsBarredFromConstraintValidation() const { return PR_TRUE; };
};
// construction, destruction
@ -102,8 +102,9 @@ DOMCI_NODE_DATA(HTMLFieldSetElement, nsHTMLFieldSetElement)
// QueryInterface implementation for nsHTMLFieldSetElement
NS_INTERFACE_TABLE_HEAD(nsHTMLFieldSetElement)
NS_HTML_CONTENT_INTERFACE_TABLE1(nsHTMLFieldSetElement,
nsIDOMHTMLFieldSetElement)
NS_HTML_CONTENT_INTERFACE_TABLE2(nsHTMLFieldSetElement,
nsIDOMHTMLFieldSetElement,
nsIConstraintValidation)
NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLFieldSetElement,
nsGenericHTMLFormElement)
NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLFieldSetElement)
@ -111,8 +112,8 @@ NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLFieldSetElement)
// nsIDOMHTMLFieldSetElement
// nsConstraintValidation
NS_IMPL_NSCONSTRAINTVALIDATION(nsHTMLFieldSetElement)
// nsIConstraintValidation
NS_IMPL_NSICONSTRAINTVALIDATION(nsHTMLFieldSetElement)
NS_IMPL_ELEMENT_CLONE(nsHTMLFieldSetElement)

Просмотреть файл

@ -79,6 +79,8 @@
#include "mozAutoDocUpdate.h"
#include "nsIHTMLCollection.h"
#include "nsIConstraintValidation.h"
static const int NS_FORM_CONTROL_LIST_HASHTABLE_SIZE = 16;
// nsHTMLFormElement
@ -405,6 +407,13 @@ nsHTMLFormElement::Reset()
return NS_OK;
}
NS_IMETHODIMP
nsHTMLFormElement::CheckValidity(PRBool* retVal)
{
*retVal = CheckFormValidity();
return NS_OK;
}
PRBool
nsHTMLFormElement::ParseAttribute(PRInt32 aNamespaceID,
nsIAtom* aAttribute,
@ -679,6 +688,16 @@ nsHTMLFormElement::DoSubmit(nsEvent* aEvent)
return NS_OK;
}
#ifdef DEBUG
if (!CheckFormValidity()) {
printf("= The form is not valid!\n");
#if 0
// TODO: uncomment this code whith a patch introducing a UI.
return NS_OK;
#endif // 0
}
#endif // DEBUG
// Mark us as submitting so that we don't try to submit again
mIsSubmitting = PR_TRUE;
NS_ASSERTION(!mWebProgress && !mSubmittingRequest, "Web progress / submitting request should not exist here!");
@ -1186,7 +1205,7 @@ nsHTMLFormElement::RemoveElement(nsGenericHTMLFormElement* aChild,
if (aChild->GetType() == NS_FORM_INPUT_RADIO) {
nsRefPtr<nsHTMLInputElement> radio =
static_cast<nsHTMLInputElement*>(aChild);
radio->WillRemoveFromRadioGroup();
radio->WillRemoveFromRadioGroup(aNotify);
}
// Determine whether to remove the child from the elements list
@ -1537,6 +1556,49 @@ nsHTMLFormElement::ForgetCurrentSubmission()
mWebProgress = nsnull;
}
PRBool
nsHTMLFormElement::CheckFormValidity() const
{
PRBool ret = PR_TRUE;
nsTArray<nsGenericHTMLFormElement*> sortedControls;
if (NS_FAILED(mControls->GetSortedControls(sortedControls))) {
return PR_FALSE;
}
PRUint32 len = sortedControls.Length();
// Hold a reference to the elements so they can't be deleted while calling
// the invalid events.
for (PRUint32 i = 0; i < len; ++i) {
static_cast<nsGenericHTMLElement*>(sortedControls[i])->AddRef();
}
for (PRUint32 i = 0; i < len; ++i) {
if (!sortedControls[i]->IsSubmittableControl()) {
continue;
}
nsCOMPtr<nsIConstraintValidation> cvElmt =
do_QueryInterface((nsGenericHTMLElement*)sortedControls[i]);
if (cvElmt && cvElmt->IsCandidateForConstraintValidation() &&
!cvElmt->IsValid()) {
ret = PR_FALSE;
nsContentUtils::DispatchTrustedEvent(sortedControls[i]->GetOwnerDoc(),
static_cast<nsIContent*>(sortedControls[i]),
NS_LITERAL_STRING("invalid"),
PR_FALSE, PR_TRUE);
}
}
// Release the references.
for (PRUint32 i = 0; i < len; ++i) {
static_cast<nsGenericHTMLElement*>(sortedControls[i])->Release();
}
return ret;
}
// nsIWebProgressListener
NS_IMETHODIMP
nsHTMLFormElement::OnStateChange(nsIWebProgress* aWebProgress,

Просмотреть файл

@ -330,6 +330,17 @@ protected:
*/
nsresult GetActionURL(nsIURI** aActionURL, nsIContent* aOriginatingElement);
/**
* Check the form validity following this algorithm:
* http://www.whatwg.org/specs/web-apps/current-work/#statically-validate-the-constraints
*
* TODO: add a [out] parameter to have the list of unhandled invalid controls
* but not needed until we have a UI to test it.
*
* @return Whether the form is currently valid.
*/
PRBool CheckFormValidity() const;
public:
/**
* Flush a possible pending submission. If there was a scripted submission

Просмотреть файл

@ -297,7 +297,7 @@ DOMCI_NODE_DATA(HTMLInputElement, nsHTMLInputElement)
// QueryInterface implementation for nsHTMLInputElement
NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsHTMLInputElement)
NS_HTML_CONTENT_INTERFACE_TABLE8(nsHTMLInputElement,
NS_HTML_CONTENT_INTERFACE_TABLE9(nsHTMLInputElement,
nsIDOMHTMLInputElement,
nsITextControlElement,
nsIFileControlElement,
@ -305,13 +305,14 @@ NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsHTMLInputElement)
imgIDecoderObserver,
nsIImageLoadingContent,
imgIContainerObserver,
nsIDOMNSEditableElement)
nsIDOMNSEditableElement,
nsIConstraintValidation)
NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLInputElement,
nsGenericHTMLFormElement)
NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLInputElement)
// nsConstraintValidation
NS_IMPL_NSCONSTRAINTVALIDATION(nsHTMLInputElement)
// nsIConstraintValidation
NS_IMPL_NSICONSTRAINTVALIDATION_EXCEPT_SETCUSTOMVALIDITY(nsHTMLInputElement)
// nsIDOMNode
@ -387,7 +388,7 @@ nsHTMLInputElement::BeforeSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
(aName == nsGkAtoms::type && !mForm)) &&
mType == NS_FORM_INPUT_RADIO &&
(mForm || !(GET_BOOLBIT(mBitField, BF_PARSER_CREATING)))) {
WillRemoveFromRadioGroup();
WillRemoveFromRadioGroup(aNotify);
} else if (aNotify && aName == nsGkAtoms::src &&
mType == NS_FORM_INPUT_IMAGE) {
if (aValue) {
@ -410,6 +411,9 @@ nsHTMLInputElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString* aValue,
PRBool aNotify)
{
// States changes that have to be passed to ContentStatesChanged().
PRInt32 states = 0;
if (aNameSpaceID == kNameSpaceID_None) {
//
// When name or type changes, radio should be added to radio group.
@ -449,13 +453,6 @@ nsHTMLInputElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
}
if (aName == nsGkAtoms::type) {
// Changing type means notifying on state changes. Just start a batch
// now.
nsIDocument* document = GetCurrentDoc();
MOZ_AUTO_DOC_UPDATE(document, UPDATE_CONTENT_STATE, aNotify);
UpdateEditableState();
if (!aValue) {
// We're now a text input. Note that we have to handle this manually,
// since removing an attribute (which is what happened, since aValue is
@ -492,41 +489,53 @@ nsHTMLInputElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
}
}
if (aNotify && document) {
// Changing type affects the applicability of some states. Just notify
// on them all now, just in case. Note that we can't rely on the
// notifications LoadImage or CancelImageRequests might have sent,
// because those didn't include all the possibly-changed states in the
// mask. We have to do this here because we just updated mType, so the
// code in nsGenericElement::SetAttrAndNotify didn't see the new
// states.
document->ContentStatesChanged(this, nsnull,
NS_EVENT_STATE_CHECKED |
NS_EVENT_STATE_DEFAULT |
NS_EVENT_STATE_BROKEN |
NS_EVENT_STATE_USERDISABLED |
NS_EVENT_STATE_SUPPRESSED |
NS_EVENT_STATE_LOADING |
NS_EVENT_STATE_INDETERMINATE |
NS_EVENT_STATE_MOZ_READONLY |
NS_EVENT_STATE_MOZ_READWRITE |
NS_EVENT_STATE_REQUIRED |
NS_EVENT_STATE_OPTIONAL);
}
// Changing type affects the applicability of some states. Just notify
// on them all now, just in case. Note that we can't rely on the
// notifications LoadImage or CancelImageRequests might have sent, because
// those didn't include all the possibly-changed states in the mask. We
// have to do this here because we just updated mType, so the code in
// nsGenericElement::SetAttrAndNotify didn't see the new states.
states |= NS_EVENT_STATE_CHECKED |
NS_EVENT_STATE_DEFAULT |
NS_EVENT_STATE_BROKEN |
NS_EVENT_STATE_USERDISABLED |
NS_EVENT_STATE_SUPPRESSED |
NS_EVENT_STATE_LOADING |
NS_EVENT_STATE_MOZ_READONLY |
NS_EVENT_STATE_MOZ_READWRITE |
NS_EVENT_STATE_REQUIRED |
NS_EVENT_STATE_OPTIONAL |
NS_EVENT_STATE_VALID |
NS_EVENT_STATE_INVALID |
NS_EVENT_STATE_INDETERMINATE;
}
// If readonly is changed for single line text controls, we need to handle
// :read-only / :read-write
if (aNotify && aName == nsGkAtoms::readonly &&
IsSingleLineTextControl(PR_FALSE)) {
UpdateEditableState();
if (aName == nsGkAtoms::required || aName == nsGkAtoms::disabled ||
aName == nsGkAtoms::readonly) {
UpdateValueMissingValidityState();
states |= NS_EVENT_STATE_REQUIRED | NS_EVENT_STATE_OPTIONAL |
NS_EVENT_STATE_VALID | NS_EVENT_STATE_INVALID;
} else if (aName == nsGkAtoms::maxlength) {
UpdateTooLongValidityState();
states |= NS_EVENT_STATE_VALID | NS_EVENT_STATE_INVALID;
} else if (aName == nsGkAtoms::pattern) {
UpdatePatternMismatchValidityState();
states |= NS_EVENT_STATE_VALID | NS_EVENT_STATE_INVALID;
}
nsIDocument* document = GetCurrentDoc();
if (document) {
mozAutoDocUpdate upd(document, UPDATE_CONTENT_STATE, PR_TRUE);
document->ContentStatesChanged(this, nsnull,
NS_EVENT_STATE_MOZ_READONLY |
NS_EVENT_STATE_MOZ_READWRITE);
if (aNotify) {
nsIDocument* doc = GetCurrentDoc();
MOZ_AUTO_DOC_UPDATE(doc, UPDATE_CONTENT_STATE, PR_TRUE);
if (aName == nsGkAtoms::type) {
UpdateEditableState();
} else if (IsSingleLineTextControl(PR_FALSE) && aName == nsGkAtoms::readonly) {
UpdateEditableState();
states |= NS_EVENT_STATE_MOZ_READONLY | NS_EVENT_STATE_MOZ_READWRITE;
}
if (doc && states) {
doc->ContentStatesChanged(this, nsnull, states);
}
}
}
@ -892,8 +901,9 @@ nsHTMLInputElement::SetFileNames(const nsTArray<nsString>& aFileNames)
}
UpdateFileList();
SetValueChanged(PR_TRUE);
UpdateAllValidityStates(PR_TRUE);
}
void
@ -1086,7 +1096,6 @@ nsHTMLInputElement::DoSetChecked(PRBool aChecked, PRBool aNotify,
if (aChecked) {
rv = RadioSetChecked(aNotify);
} else {
rv = SetCheckedInternal(PR_FALSE, aNotify);
nsCOMPtr<nsIRadioGroupContainer> container = GetRadioGroupContainer();
if (container) {
nsAutoString name;
@ -1094,9 +1103,13 @@ nsHTMLInputElement::DoSetChecked(PRBool aChecked, PRBool aNotify,
container->SetCurrentRadioButton(name, nsnull);
}
}
// SetCheckedInternal is going to ask all radios to update their
// validity state. We have to be sure the radio group container knows
// the currently selected radio.
SetCheckedInternal(PR_FALSE, aNotify);
}
} else {
rv = SetCheckedInternal(aChecked, aNotify);
SetCheckedInternal(aChecked, aNotify);
}
return rv;
@ -1118,27 +1131,26 @@ nsHTMLInputElement::RadioSetChecked(PRBool aNotify)
if (currentlySelected) {
// Pass PR_TRUE for the aNotify parameter since the currently selected
// button is already in the document.
rv = static_cast<nsHTMLInputElement*>
(static_cast<nsIDOMHTMLInputElement*>(currentlySelected))->SetCheckedInternal(PR_FALSE, PR_TRUE);
}
//
// Actually select this one
//
if (NS_SUCCEEDED(rv)) {
rv = SetCheckedInternal(PR_TRUE, aNotify);
static_cast<nsHTMLInputElement*>
(static_cast<nsIDOMHTMLInputElement*>(currentlySelected))->SetCheckedInternal(PR_FALSE, PR_TRUE);
}
//
// Let the group know that we are now the One True Radio Button
//
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIRadioGroupContainer> container = GetRadioGroupContainer();
nsAutoString name;
if (container && GetNameIfExists(name)) {
rv = container->SetCurrentRadioButton(name, this);
}
// SetCheckedInternal is going to ask all radios to update their
// validity state. We have to be sure the radio group container knows
// the currently selected radio.
if (NS_SUCCEEDED(rv)) {
SetCheckedInternal(PR_TRUE, aNotify);
}
return rv;
}
@ -1211,7 +1223,7 @@ nsHTMLInputElement::MaybeSubmitForm(nsPresContext* aPresContext)
return NS_OK;
}
nsresult
void
nsHTMLInputElement::SetCheckedInternal(PRBool aChecked, PRBool aNotify)
{
//
@ -1239,7 +1251,16 @@ nsHTMLInputElement::SetCheckedInternal(PRBool aChecked, PRBool aNotify)
}
}
return NS_OK;
if (mType == NS_FORM_INPUT_CHECKBOX) {
UpdateAllValidityStates(aNotify);
}
if (mType == NS_FORM_INPUT_RADIO) {
// OnValueChanged is going to be called for all radios in the radio group.
nsCOMPtr<nsIRadioVisitor> visitor =
NS_GetRadioUpdateValueMissingVisitor(aNotify);
VisitGroup(visitor, aNotify);
}
}
@ -2022,6 +2043,10 @@ nsHTMLInputElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
AddedToRadioGroup();
}
// An element can't suffer from value missing if it is not in a document.
// We have to check if we suffer from that as we are now in a document.
UpdateValueMissingValidityState();
return rv;
}
@ -2034,10 +2059,14 @@ nsHTMLInputElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
// of the case where we're removing from the document and we don't
// have a form
if (!mForm && mType == NS_FORM_INPUT_RADIO) {
WillRemoveFromRadioGroup();
WillRemoveFromRadioGroup(PR_FALSE);
}
nsGenericHTMLFormElement::UnbindFromTree(aDeep, aNullParent);
// GetCurrentDoc is returning nsnull so we can update the value
// missing validity state to reflect we are no longer into a doc.
UpdateValueMissingValidityState();
}
void
@ -2068,6 +2097,9 @@ nsHTMLInputElement::HandleTypeChange(PRUint8 aNewType)
// SetValueInternal is going to sanitize the value.
SetValueInternal(value, PR_FALSE, PR_FALSE);
}
// Do not notify, it will be done after if needed.
UpdateAllValidityStates(PR_FALSE);
}
void
@ -2760,6 +2792,10 @@ nsHTMLInputElement::IntrinsicState() const
state |= NS_EVENT_STATE_OPTIONAL;
}
if (IsCandidateForConstraintValidation()) {
state |= IsValid() ? NS_EVENT_STATE_VALID : NS_EVENT_STATE_INVALID;
}
return state;
}
@ -2875,7 +2911,7 @@ nsHTMLInputElement::AddedToRadioGroup(PRBool aNotify)
}
void
nsHTMLInputElement::WillRemoveFromRadioGroup()
nsHTMLInputElement::WillRemoveFromRadioGroup(PRBool aNotify)
{
//
// If the input element is not in a form and
@ -2904,6 +2940,12 @@ nsHTMLInputElement::WillRemoveFromRadioGroup()
if (container) {
container->SetCurrentRadioButton(name, nsnull);
}
// Removing a checked radio from the group can change the validity state.
// Let's ask other radio to update their value missing validity state.
nsCOMPtr<nsIRadioVisitor> visitor =
NS_GetRadioUpdateValueMissingVisitor(aNotify);
VisitGroup(visitor, PR_FALSE);
}
//
@ -3136,7 +3178,21 @@ nsHTMLInputElement::DoesPatternApply() const
return IsSingleLineTextControl(PR_FALSE);
}
// nsConstraintValidation
// nsIConstraintValidation
NS_IMETHODIMP
nsHTMLInputElement::SetCustomValidity(const nsAString& aError)
{
nsIConstraintValidation::SetCustomValidity(aError);
nsIDocument* doc = GetCurrentDoc();
if (doc) {
doc->ContentStatesChanged(this, nsnull, NS_EVENT_STATE_INVALID |
NS_EVENT_STATE_VALID);
}
return NS_OK;
}
PRBool
nsHTMLInputElement::IsTooLong()
@ -3151,7 +3207,7 @@ nsHTMLInputElement::IsTooLong()
GetMaxLength(&maxLength);
GetTextLength(&textLength);
return (maxLength >= 0) && (textLength > maxLength);
return maxLength >= 0 && textLength > maxLength;
}
PRBool
@ -3168,52 +3224,49 @@ nsHTMLInputElement::IsValueMissing()
}
nsAutoString value;
nsresult rv = GetValue(value);
NS_ENSURE_SUCCESS(rv, PR_FALSE);
NS_ENSURE_SUCCESS(GetValue(value), PR_FALSE);
return value.IsEmpty();
}
if (mType == NS_FORM_INPUT_CHECKBOX) {
return !GetChecked();
switch (mType)
{
case NS_FORM_INPUT_CHECKBOX:
return !GetChecked();
case NS_FORM_INPUT_RADIO:
{
nsCOMPtr<nsIDOMHTMLInputElement> selected = GetSelectedRadioButton();
return !selected;
}
case NS_FORM_INPUT_FILE:
{
nsCOMArray<nsIFile> files;
GetFileArray(files);
return !files.Count();
}
default:
return PR_FALSE;
}
if (mType == NS_FORM_INPUT_RADIO) {
nsCOMPtr<nsIDOMHTMLInputElement> selected = GetSelectedRadioButton();
return !selected;
}
if (mType == NS_FORM_INPUT_FILE) {
nsCOMArray<nsIFile> files;
GetFileArray(files);
return !files.Count();
}
return PR_FALSE;
}
PRBool
nsHTMLInputElement::HasTypeMismatch()
{
if (mType != NS_FORM_INPUT_EMAIL && mType != NS_FORM_INPUT_URL) {
return PR_FALSE;
}
nsAutoString value;
NS_ENSURE_SUCCESS(GetValue(value), PR_FALSE);
if (value.IsEmpty()) {
return PR_FALSE;
}
if (mType == NS_FORM_INPUT_EMAIL) {
nsAutoString value;
NS_ENSURE_SUCCESS(GetValue(value), PR_FALSE);
if (value.IsEmpty()) {
return PR_FALSE;
}
return HasAttr(kNameSpaceID_None, nsGkAtoms::multiple) ?
!IsValidEmailAddressList(value) :
!IsValidEmailAddress(value);
return HasAttr(kNameSpaceID_None, nsGkAtoms::multiple)
? !IsValidEmailAddressList(value) : !IsValidEmailAddress(value);
} else if (mType == NS_FORM_INPUT_URL) {
nsAutoString value;
NS_ENSURE_SUCCESS(GetValue(value), PR_FALSE);
if (value.IsEmpty()) {
return PR_FALSE;
}
/**
* TODO:
* The URL is not checked as the HTML5 specifications want it to be because
@ -3239,8 +3292,8 @@ PRBool
nsHTMLInputElement::HasPatternMismatch()
{
nsAutoString pattern;
if (!DoesPatternApply() || !GetAttr(kNameSpaceID_None, nsGkAtoms::pattern,
pattern)) {
if (!DoesPatternApply() ||
!GetAttr(kNameSpaceID_None, nsGkAtoms::pattern, pattern)) {
return PR_FALSE;
}
@ -3259,8 +3312,49 @@ nsHTMLInputElement::HasPatternMismatch()
return !IsPatternMatching(value, pattern, doc);
}
void
nsHTMLInputElement::UpdateTooLongValidityState()
{
SetValidityState(VALIDITY_STATE_TOO_LONG, IsTooLong());
}
void
nsHTMLInputElement::UpdateValueMissingValidityState()
{
SetValidityState(VALIDITY_STATE_VALUE_MISSING, IsValueMissing());
}
void
nsHTMLInputElement::UpdateTypeMismatchValidityState()
{
SetValidityState(VALIDITY_STATE_TYPE_MISMATCH, HasTypeMismatch());
}
void
nsHTMLInputElement::UpdatePatternMismatchValidityState()
{
SetValidityState(VALIDITY_STATE_PATTERN_MISMATCH, HasPatternMismatch());
}
void
nsHTMLInputElement::UpdateAllValidityStates(PRBool aNotify)
{
UpdateTooLongValidityState();
UpdateValueMissingValidityState();
UpdateTypeMismatchValidityState();
UpdatePatternMismatchValidityState();
if (aNotify) {
nsIDocument* doc = GetCurrentDoc();
if (doc) {
doc->ContentStatesChanged(this, nsnull,
NS_EVENT_STATE_VALID | NS_EVENT_STATE_INVALID);
}
}
}
PRBool
nsHTMLInputElement::IsBarredFromConstraintValidation()
nsHTMLInputElement::IsBarredFromConstraintValidation() const
{
return mType == NS_FORM_INPUT_HIDDEN ||
mType == NS_FORM_INPUT_BUTTON ||
@ -3270,13 +3364,13 @@ nsHTMLInputElement::IsBarredFromConstraintValidation()
nsresult
nsHTMLInputElement::GetValidationMessage(nsAString& aValidationMessage,
ValidationMessageType aType)
ValidityStateType aType)
{
nsresult rv = NS_OK;
switch (aType)
{
case VALIDATION_MESSAGE_TOO_LONG:
case VALIDITY_STATE_TOO_LONG:
{
nsXPIDLString message;
PRInt32 maxLength = -1;
@ -3297,7 +3391,7 @@ nsHTMLInputElement::GetValidationMessage(nsAString& aValidationMessage,
aValidationMessage = message;
break;
}
case VALIDATION_MESSAGE_VALUE_MISSING:
case VALIDITY_STATE_VALUE_MISSING:
{
nsXPIDLString message;
nsCAutoString key;
@ -3320,7 +3414,7 @@ nsHTMLInputElement::GetValidationMessage(nsAString& aValidationMessage,
aValidationMessage = message;
break;
}
case VALIDATION_MESSAGE_TYPE_MISMATCH:
case VALIDITY_STATE_TYPE_MISMATCH:
{
nsXPIDLString message;
nsCAutoString key;
@ -3336,7 +3430,7 @@ nsHTMLInputElement::GetValidationMessage(nsAString& aValidationMessage,
aValidationMessage = message;
break;
}
case VALIDATION_MESSAGE_PATTERN_MISMATCH:
case VALIDITY_STATE_PATTERN_MISMATCH:
{
nsXPIDLString message;
nsAutoString title;
@ -3355,7 +3449,7 @@ nsHTMLInputElement::GetValidationMessage(nsAString& aValidationMessage,
break;
}
default:
rv = nsConstraintValidation::GetValidationMessage(aValidationMessage, aType);
rv = nsIConstraintValidation::GetValidationMessage(aValidationMessage, aType);
}
return rv;
@ -3557,6 +3651,38 @@ protected:
nsIFormControl* mExcludeElement;
};
class nsRadioUpdateValueMissingVisitor : public nsRadioVisitor {
public:
nsRadioUpdateValueMissingVisitor(PRBool aNotify)
: nsRadioVisitor()
, mNotify(aNotify)
{ }
virtual ~nsRadioUpdateValueMissingVisitor() { };
NS_IMETHOD Visit(nsIFormControl* aRadio, PRBool* aStop)
{
/**
* The simplest way to update the value missing validity state is to do a
* global update of the validity state by simulationg a value change.
* OnValueChanged() is declared into nsITextControlElement. That may sound
* to be a weird way to update the validity states for radio controls but
* they are also implementing nsITextControlElement interface.
*
* When OnValueChanged() is called on a radio control, it will check if any
* radio in the group is checked. If none, the required radio will be
* suffering from being missing.
*/
nsCOMPtr<nsITextControlElement> textCtl(do_QueryInterface(aRadio));
NS_ASSERTION(textCtl, "Visit() passed a null or non-radio pointer");
textCtl->OnValueChanged(mNotify);
return NS_OK;
}
protected:
PRBool mNotify;
};
nsresult
NS_GetRadioSetCheckedChangedVisitor(PRBool aCheckedChanged,
nsIRadioVisitor** aVisitor)
@ -3627,6 +3753,22 @@ NS_GetRadioGetCheckedChangedVisitor(PRBool* aCheckedChanged,
return NS_OK;
}
/*
* This method is a factory: it lets callers to create an instance of
* nsRadioUpdateValueMissing without the class declaration and definition.
*
* TODO:
* Do we really need factories for radio visitors? Or at least, we should move
* that somewhere else because it feels like it's here only because the radio
* visitor classes are defined after most of nsHTMLInputElement code.
* See bug 586298
*/
nsIRadioVisitor*
NS_GetRadioUpdateValueMissingVisitor(PRBool aNotify)
{
return new nsRadioUpdateValueMissingVisitor(aNotify);
}
NS_IMETHODIMP_(PRBool)
nsHTMLInputElement::IsSingleLineTextControl() const
{
@ -3725,3 +3867,10 @@ nsHTMLInputElement::InitializeKeyboardEventListeners()
state->InitializeKeyboardEventListeners();
}
}
NS_IMETHODIMP_(void)
nsHTMLInputElement::OnValueChanged(PRBool aNotify)
{
UpdateAllValidityStates(aNotify);
}

Просмотреть файл

@ -49,7 +49,7 @@
#include "nsTextEditorState.h"
#include "nsCOMPtr.h"
#include "nsConstraintValidation.h"
#include "nsIConstraintValidation.h"
//
// Accessors for mBitField
@ -82,7 +82,7 @@ class nsHTMLInputElement : public nsGenericHTMLFormElement,
public nsIPhonetic,
public nsIDOMNSEditableElement,
public nsIFileControlElement,
public nsConstraintValidation
public nsIConstraintValidation
{
public:
nsHTMLInputElement(already_AddRefed<nsINodeInfo> aNodeInfo,
@ -171,6 +171,7 @@ public:
NS_IMETHOD_(void) UpdatePlaceholderText(PRBool aNotify);
NS_IMETHOD_(void) SetPlaceholderClass(PRBool aVisible, PRBool aNotify);
NS_IMETHOD_(void) InitializeKeyboardEventListeners();
NS_IMETHOD_(void) OnValueChanged(PRBool aNotify);
// nsIFileControlElement
virtual void GetDisplayFileName(nsAString& aFileName);
@ -180,7 +181,7 @@ public:
void SetCheckedChangedInternal(PRBool aCheckedChanged);
PRBool GetCheckedChanged();
void AddedToRadioGroup(PRBool aNotify = PR_TRUE);
void WillRemoveFromRadioGroup();
void WillRemoveFromRadioGroup(PRBool aNotify);
/**
* Get the radio group container for this button (form or document)
* @return the radio group container (or null if no form or document)
@ -210,14 +211,19 @@ public:
virtual nsXPCClassInfo* GetClassInfo();
// nsConstraintValidation
// nsIConstraintValidation
PRBool IsTooLong();
PRBool IsValueMissing();
PRBool HasTypeMismatch();
PRBool HasPatternMismatch();
PRBool IsBarredFromConstraintValidation();
void UpdateTooLongValidityState();
void UpdateValueMissingValidityState();
void UpdateTypeMismatchValidityState();
void UpdatePatternMismatchValidityState();
void UpdateAllValidityStates(PRBool aNotify);
PRBool IsBarredFromConstraintValidation() const;
nsresult GetValidationMessage(nsAString& aValidationMessage,
ValidationMessageType aType);
ValidityStateType aType);
protected:
// Pull IsSingleLineTextControl into our scope, otherwise it'd be hidden
@ -373,7 +379,7 @@ protected:
* Actually set checked and notify the frame of the change.
* @param aValue the value of checked to set
*/
nsresult SetCheckedInternal(PRBool aValue, PRBool aNotify);
void SetCheckedInternal(PRBool aValue, PRBool aNotify);
/**
* Syntax sugar to make it easier to check for checked

Просмотреть файл

@ -40,11 +40,13 @@
#include "nsFormSubmission.h"
#include "nsDOMSettableTokenList.h"
#include "nsStubMutationObserver.h"
#include "nsIConstraintValidation.h"
class nsHTMLOutputElement : public nsGenericHTMLFormElement,
public nsIDOMHTMLOutputElement,
public nsStubMutationObserver
public nsStubMutationObserver,
public nsIConstraintValidation
{
public:
nsHTMLOutputElement(already_AddRefed<nsINodeInfo> aNodeInfo);
@ -79,6 +81,9 @@ public:
// has to be used to update the defaultValue attribute.
void DescendantsChanged();
// nsIConstraintValidation
PRBool IsBarredFromConstraintValidation() const { return PR_TRUE; }
// nsIMutationObserver
NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED
NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
@ -125,9 +130,10 @@ NS_IMPL_RELEASE_INHERITED(nsHTMLOutputElement, nsGenericElement)
DOMCI_NODE_DATA(HTMLOutputElement, nsHTMLOutputElement)
NS_INTERFACE_TABLE_HEAD(nsHTMLOutputElement)
NS_HTML_CONTENT_INTERFACE_TABLE2(nsHTMLOutputElement,
NS_HTML_CONTENT_INTERFACE_TABLE3(nsHTMLOutputElement,
nsIDOMHTMLOutputElement,
nsIMutationObserver)
nsIMutationObserver,
nsIConstraintValidation)
NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLOutputElement,
nsGenericHTMLFormElement)
NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLOutputElement)
@ -137,6 +143,9 @@ NS_IMPL_ELEMENT_CLONE(nsHTMLOutputElement)
NS_IMPL_STRING_ATTR(nsHTMLOutputElement, Name, name)
// nsIConstraintValidation
NS_IMPL_NSICONSTRAINTVALIDATION(nsHTMLOutputElement)
NS_IMETHODIMP
nsHTMLOutputElement::Reset()
{

Просмотреть файл

@ -181,9 +181,10 @@ DOMCI_NODE_DATA(HTMLSelectElement, nsHTMLSelectElement)
// QueryInterface implementation for nsHTMLSelectElement
NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsHTMLSelectElement)
NS_HTML_CONTENT_INTERFACE_TABLE2(nsHTMLSelectElement,
NS_HTML_CONTENT_INTERFACE_TABLE3(nsHTMLSelectElement,
nsIDOMHTMLSelectElement,
nsISelectElement)
nsISelectElement,
nsIConstraintValidation)
NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLSelectElement,
nsGenericHTMLFormElement)
NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLSelectElement)
@ -194,8 +195,22 @@ NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLSelectElement)
NS_IMPL_ELEMENT_CLONE(nsHTMLSelectElement)
// nsConstraintValidation
NS_IMPL_NSCONSTRAINTVALIDATION(nsHTMLSelectElement)
// nsIConstraintValidation
NS_IMPL_NSICONSTRAINTVALIDATION_EXCEPT_SETCUSTOMVALIDITY(nsHTMLSelectElement)
NS_IMETHODIMP
nsHTMLSelectElement::SetCustomValidity(const nsAString& aError)
{
nsIConstraintValidation::SetCustomValidity(aError);
nsIDocument* doc = GetCurrentDoc();
if (doc) {
doc->ContentStatesChanged(this, nsnull, NS_EVENT_STATE_INVALID |
NS_EVENT_STATE_VALID);
}
return NS_OK;
}
NS_IMETHODIMP
nsHTMLSelectElement::GetForm(nsIDOMHTMLFormElement** aForm)
@ -1455,7 +1470,13 @@ nsHTMLSelectElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
PRInt32
nsHTMLSelectElement::IntrinsicState() const
{
return NS_EVENT_STATE_OPTIONAL | nsGenericHTMLFormElement::IntrinsicState();
PRInt32 state = nsGenericHTMLFormElement::IntrinsicState();
if (IsCandidateForConstraintValidation()) {
state |= IsValid() ? NS_EVENT_STATE_VALID : NS_EVENT_STATE_INVALID;
}
return state | NS_EVENT_STATE_OPTIONAL;
}
// nsIFormControl

Просмотреть файл

@ -52,7 +52,7 @@
#include "nsISelectControlFrame.h"
#include "nsContentUtils.h"
#include "nsIHTMLCollection.h"
#include "nsConstraintValidation.h"
#include "nsIConstraintValidation.h"
// PresState
#include "nsXPCOM.h"
@ -238,7 +238,7 @@ private:
class nsHTMLSelectElement : public nsGenericHTMLFormElement,
public nsIDOMHTMLSelectElement,
public nsISelectElement,
public nsConstraintValidation
public nsIConstraintValidation
{
public:
nsHTMLSelectElement(already_AddRefed<nsINodeInfo> aNodeInfo,

Просмотреть файл

@ -77,7 +77,7 @@
#include "mozAutoDocUpdate.h"
#include "nsISupportsPrimitives.h"
#include "nsContentCreatorFunctions.h"
#include "nsConstraintValidation.h"
#include "nsIConstraintValidation.h"
#include "nsTextEditorState.h"
@ -91,7 +91,7 @@ class nsHTMLTextAreaElement : public nsGenericHTMLFormElement,
public nsITextControlElement,
public nsIDOMNSEditableElement,
public nsStubMutationObserver,
public nsConstraintValidation
public nsIConstraintValidation
{
public:
nsHTMLTextAreaElement(already_AddRefed<nsINodeInfo> aNodeInfo,
@ -155,6 +155,7 @@ public:
NS_IMETHOD_(void) UpdatePlaceholderText(PRBool aNotify);
NS_IMETHOD_(void) SetPlaceholderClass(PRBool aVisible, PRBool aNotify);
NS_IMETHOD_(void) InitializeKeyboardEventListeners();
NS_IMETHOD_(void) OnValueChanged(PRBool aNotify);
// nsIContent
virtual PRBool ParseAttribute(PRInt32 aNamespaceID,
@ -200,12 +201,14 @@ public:
virtual nsXPCClassInfo* GetClassInfo();
// nsConstraintValidation
// nsIConstraintValidation
PRBool IsTooLong();
PRBool IsValueMissing();
PRBool IsBarredFromConstraintValidation();
PRBool IsValueMissing() const;
void UpdateTooLongValidityState();
void UpdateValueMissingValidityState();
PRBool IsBarredFromConstraintValidation() const;
nsresult GetValidationMessage(nsAString& aValidationMessage,
ValidationMessageType aType);
ValidityStateType aType);
protected:
using nsGenericHTMLFormElement::IsSingleLineTextControl; // get rid of the compiler warning
@ -233,7 +236,7 @@ protected:
* value. If this is true, linebreaks will not be inserted even if
* wrap=hard.
*/
void GetValueInternal(nsAString& aValue, PRBool aIgnoreWrap);
void GetValueInternal(nsAString& aValue, PRBool aIgnoreWrap) const;
nsresult SetValueInternal(const nsAString& aValue,
PRBool aUserInput);
@ -297,12 +300,13 @@ DOMCI_NODE_DATA(HTMLTextAreaElement, nsHTMLTextAreaElement)
// QueryInterface implementation for nsHTMLTextAreaElement
NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsHTMLTextAreaElement)
NS_HTML_CONTENT_INTERFACE_TABLE5(nsHTMLTextAreaElement,
NS_HTML_CONTENT_INTERFACE_TABLE6(nsHTMLTextAreaElement,
nsIDOMHTMLTextAreaElement,
nsIDOMNSHTMLTextAreaElement,
nsITextControlElement,
nsIDOMNSEditableElement,
nsIMutationObserver)
nsIMutationObserver,
nsIConstraintValidation)
NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLTextAreaElement,
nsGenericHTMLFormElement)
NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLTextAreaElement)
@ -313,8 +317,8 @@ NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLTextAreaElement)
NS_IMPL_ELEMENT_CLONE(nsHTMLTextAreaElement)
// nsConstraintValidation
NS_IMPL_NSCONSTRAINTVALIDATION(nsHTMLTextAreaElement)
// nsIConstraintValidation
NS_IMPL_NSICONSTRAINTVALIDATION_EXCEPT_SETCUSTOMVALIDITY(nsHTMLTextAreaElement)
NS_IMETHODIMP
@ -439,7 +443,7 @@ nsHTMLTextAreaElement::GetValue(nsAString& aValue)
}
void
nsHTMLTextAreaElement::GetValueInternal(nsAString& aValue, PRBool aIgnoreWrap)
nsHTMLTextAreaElement::GetValueInternal(nsAString& aValue, PRBool aIgnoreWrap) const
{
mState->GetValue(aValue, aIgnoreWrap);
}
@ -841,17 +845,15 @@ nsresult
nsHTMLTextAreaElement::Reset()
{
nsresult rv;
// If the frame is there, we have to set the value so that it will show up.
nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_FALSE);
if (formControlFrame) {
// To get the initial spellchecking, reset value to
// empty string before setting the default value.
SetValue(EmptyString());
nsAutoString resetVal;
GetDefaultValue(resetVal);
rv = SetValue(resetVal);
NS_ENSURE_SUCCESS(rv, rv);
}
// To get the initial spellchecking, reset value to
// empty string before setting the default value.
SetValue(EmptyString());
nsAutoString resetVal;
GetDefaultValue(resetVal);
rv = SetValue(resetVal);
NS_ENSURE_SUCCESS(rv, rv);
SetValueChanged(PR_FALSE);
return NS_OK;
}
@ -965,6 +967,10 @@ nsHTMLTextAreaElement::IntrinsicState() const
state |= NS_EVENT_STATE_OPTIONAL;
}
if (IsCandidateForConstraintValidation()) {
state |= IsValid() ? NS_EVENT_STATE_VALID : NS_EVENT_STATE_INVALID;
}
return state;
}
@ -1033,18 +1039,33 @@ nsresult
nsHTMLTextAreaElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString* aValue, PRBool aNotify)
{
if (aNotify && aNameSpaceID == kNameSpaceID_None &&
aName == nsGkAtoms::readonly) {
UpdateEditableState();
PRInt32 states = 0;
nsIDocument* document = GetCurrentDoc();
if (document) {
mozAutoDocUpdate upd(document, UPDATE_CONTENT_STATE, PR_TRUE);
document->ContentStatesChanged(this, nsnull,
NS_EVENT_STATE_MOZ_READONLY |
NS_EVENT_STATE_MOZ_READWRITE);
if (aNameSpaceID == kNameSpaceID_None) {
if (aName == nsGkAtoms::required || aName == nsGkAtoms::disabled ||
aName == nsGkAtoms::readonly) {
UpdateValueMissingValidityState();
states |= NS_EVENT_STATE_VALID | NS_EVENT_STATE_INVALID;
} else if (aName == nsGkAtoms::maxlength) {
UpdateTooLongValidityState();
states |= NS_EVENT_STATE_VALID | NS_EVENT_STATE_INVALID;
}
if (aNotify) {
nsIDocument* doc = GetCurrentDoc();
MOZ_AUTO_DOC_UPDATE(doc, UPDATE_CONTENT_STATE, PR_TRUE);
if (aName == nsGkAtoms::readonly) {
UpdateEditableState();
states |= NS_EVENT_STATE_MOZ_READONLY | NS_EVENT_STATE_MOZ_READWRITE;
}
if (doc && states) {
doc->ContentStatesChanged(this, nsnull, states);
}
}
}
return nsGenericHTMLFormElement::AfterSetAttr(aNameSpaceID, aName, aValue,
aNotify);
}
@ -1070,7 +1091,21 @@ nsHTMLTextAreaElement::IsMutable() const
!HasAttr(kNameSpaceID_None, nsGkAtoms::disabled));
}
// nsConstraintValidation
// nsIConstraintValidation
NS_IMETHODIMP
nsHTMLTextAreaElement::SetCustomValidity(const nsAString& aError)
{
nsIConstraintValidation::SetCustomValidity(aError);
nsIDocument* doc = GetCurrentDoc();
if (doc) {
doc->ContentStatesChanged(this, nsnull, NS_EVENT_STATE_INVALID |
NS_EVENT_STATE_VALID);
}
return NS_OK;
}
PRBool
nsHTMLTextAreaElement::IsTooLong()
@ -1085,38 +1120,49 @@ nsHTMLTextAreaElement::IsTooLong()
GetMaxLength(&maxLength);
GetTextLength(&textLength);
return (maxLength >= 0) && (textLength > maxLength);
return maxLength >= 0 && textLength > maxLength;
}
PRBool
nsHTMLTextAreaElement::IsValueMissing()
nsHTMLTextAreaElement::IsValueMissing() const
{
if (!HasAttr(kNameSpaceID_None, nsGkAtoms::required) || !IsMutable()) {
return PR_FALSE;
}
nsAutoString value;
nsresult rv = GetValue(value);
NS_ENSURE_SUCCESS(rv, PR_FALSE);
GetValueInternal(value, PR_TRUE);
return value.IsEmpty();
}
void
nsHTMLTextAreaElement::UpdateTooLongValidityState()
{
SetValidityState(VALIDITY_STATE_TOO_LONG, IsTooLong());
}
void
nsHTMLTextAreaElement::UpdateValueMissingValidityState()
{
SetValidityState(VALIDITY_STATE_VALUE_MISSING, IsValueMissing());
}
PRBool
nsHTMLTextAreaElement::IsBarredFromConstraintValidation()
nsHTMLTextAreaElement::IsBarredFromConstraintValidation() const
{
return HasAttr(kNameSpaceID_None, nsGkAtoms::readonly);
}
nsresult
nsHTMLTextAreaElement::GetValidationMessage(nsAString& aValidationMessage,
ValidationMessageType aType)
ValidityStateType aType)
{
nsresult rv = NS_OK;
switch (aType)
{
case VALIDATION_MESSAGE_TOO_LONG:
case VALIDITY_STATE_TOO_LONG:
{
nsXPIDLString message;
PRInt32 maxLength = -1;
@ -1137,7 +1183,7 @@ nsHTMLTextAreaElement::GetValidationMessage(nsAString& aValidationMessage,
aValidationMessage = message;
}
break;
case VALIDATION_MESSAGE_VALUE_MISSING:
case VALIDITY_STATE_VALUE_MISSING:
{
nsXPIDLString message;
rv = nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES,
@ -1147,7 +1193,7 @@ nsHTMLTextAreaElement::GetValidationMessage(nsAString& aValidationMessage,
}
break;
default:
rv = nsConstraintValidation::GetValidationMessage(aValidationMessage, aType);
rv = nsIConstraintValidation::GetValidationMessage(aValidationMessage, aType);
}
return rv;
@ -1251,3 +1297,20 @@ nsHTMLTextAreaElement::InitializeKeyboardEventListeners()
{
mState->InitializeKeyboardEventListeners();
}
NS_IMETHODIMP_(void)
nsHTMLTextAreaElement::OnValueChanged(PRBool aNotify)
{
// Update the validity state
UpdateTooLongValidityState();
UpdateValueMissingValidityState();
if (aNotify) {
nsIDocument* doc = GetCurrentDoc();
if (doc) {
doc->ContentStatesChanged(this, nsnull, NS_EVENT_STATE_VALID |
NS_EVENT_STATE_INVALID);
}
}
}

Просмотреть файл

@ -35,13 +35,21 @@
*
* ***** END LICENSE BLOCK ***** */
#include "nsConstraintValidation.h"
#include "nsIConstraintValidation.h"
#include "nsAString.h"
#include "nsGenericHTMLElement.h"
#include "nsHTMLFormElement.h"
#include "nsDOMValidityState.h"
nsConstraintValidation::~nsConstraintValidation()
nsIConstraintValidation::nsIConstraintValidation()
: mValidityBitField(0)
, mValidity(nsnull)
{
}
nsIConstraintValidation::~nsIConstraintValidation()
{
if (mValidity) {
mValidity->Disconnect();
@ -49,7 +57,7 @@ nsConstraintValidation::~nsConstraintValidation()
}
nsresult
nsConstraintValidation::GetValidity(nsIDOMValidityState** aValidity)
nsIConstraintValidation::GetValidity(nsIDOMValidityState** aValidity)
{
if (!mValidity) {
mValidity = new nsDOMValidityState(this);
@ -61,30 +69,21 @@ nsConstraintValidation::GetValidity(nsIDOMValidityState** aValidity)
}
nsresult
nsConstraintValidation::GetWillValidate(PRBool* aWillValidate,
nsGenericHTMLFormElement* aElement)
{
*aWillValidate = IsCandidateForConstraintValidation(aElement);
return NS_OK;
}
nsresult
nsConstraintValidation::GetValidationMessage(nsAString & aValidationMessage,
nsGenericHTMLFormElement* aElement)
nsIConstraintValidation::GetValidationMessage(nsAString& aValidationMessage)
{
aValidationMessage.Truncate();
if (IsCandidateForConstraintValidation(aElement) && !IsValid()) {
if (!mCustomValidity.IsEmpty()) {
if (IsCandidateForConstraintValidation() && !IsValid()) {
if (GetValidityState(VALIDITY_STATE_CUSTOM_ERROR)) {
aValidationMessage.Assign(mCustomValidity);
} else if (IsTooLong()) {
GetValidationMessage(aValidationMessage, VALIDATION_MESSAGE_TOO_LONG);
} else if (IsValueMissing()) {
GetValidationMessage(aValidationMessage, VALIDATION_MESSAGE_VALUE_MISSING);
} else if (HasTypeMismatch()) {
GetValidationMessage(aValidationMessage, VALIDATION_MESSAGE_TYPE_MISMATCH);
} else if (HasPatternMismatch()) {
GetValidationMessage(aValidationMessage, VALIDATION_MESSAGE_PATTERN_MISMATCH);
} else if (GetValidityState(VALIDITY_STATE_TOO_LONG)) {
GetValidationMessage(aValidationMessage, VALIDITY_STATE_TOO_LONG);
} else if (GetValidityState(VALIDITY_STATE_VALUE_MISSING)) {
GetValidationMessage(aValidationMessage, VALIDITY_STATE_VALUE_MISSING);
} else if (GetValidityState(VALIDITY_STATE_TYPE_MISMATCH)) {
GetValidationMessage(aValidationMessage, VALIDITY_STATE_TYPE_MISMATCH);
} else if (GetValidityState(VALIDITY_STATE_PATTERN_MISMATCH)) {
GetValidationMessage(aValidationMessage, VALIDITY_STATE_PATTERN_MISMATCH);
} else {
// TODO: The other messages have not been written
// because related constraint validation are not implemented yet.
@ -99,45 +98,32 @@ nsConstraintValidation::GetValidationMessage(nsAString & aValidationMessage,
}
nsresult
nsConstraintValidation::CheckValidity(PRBool* aValidity,
nsGenericHTMLFormElement* aElement)
nsIConstraintValidation::CheckValidity(PRBool* aValidity)
{
if (!IsCandidateForConstraintValidation(aElement) || IsValid()) {
if (!IsCandidateForConstraintValidation() || IsValid()) {
*aValidity = PR_TRUE;
return NS_OK;
}
*aValidity = PR_FALSE;
return nsContentUtils::DispatchTrustedEvent(aElement->GetOwnerDoc(),
static_cast<nsIContent*>(aElement),
nsCOMPtr<nsIContent> content = do_QueryInterface(this);
NS_ASSERTION(content, "This class should be inherited by HTML elements only!");
return nsContentUtils::DispatchTrustedEvent(content->GetOwnerDoc(), content,
NS_LITERAL_STRING("invalid"),
PR_FALSE, PR_TRUE);
}
nsresult
nsConstraintValidation::SetCustomValidity(const nsAString & aError)
void
nsIConstraintValidation::SetCustomValidity(const nsAString& aError)
{
mCustomValidity.Assign(aError);
return NS_OK;
SetValidityState(VALIDITY_STATE_CUSTOM_ERROR, !mCustomValidity.IsEmpty());
}
PRBool
nsConstraintValidation::HasCustomError() const
{
return !mCustomValidity.IsEmpty();
}
PRBool
nsConstraintValidation::IsValid()
{
return !(IsValueMissing() || HasTypeMismatch() || HasPatternMismatch() ||
IsTooLong() || HasRangeUnderflow() || HasRangeOverflow() ||
HasStepMismatch() || HasCustomError());
}
PRBool
nsConstraintValidation::IsCandidateForConstraintValidation(nsGenericHTMLFormElement* aElement)
nsIConstraintValidation::IsCandidateForConstraintValidation() const
{
/**
* An element is never candidate for constraint validation if:
@ -147,13 +133,17 @@ nsConstraintValidation::IsCandidateForConstraintValidation(nsGenericHTMLFormElem
* |IsBarredFromConstraintValidation| function.
*/
// At the moment, every elements which can be candidate for constraint
// validation can be disabled. However, using |CanBeDisabled| is future-proof.
if (aElement->CanBeDisabled() &&
aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::disabled)) {
return PR_FALSE;
}
nsCOMPtr<nsIContent> content =
do_QueryInterface(const_cast<nsIConstraintValidation*>(this));
NS_ASSERTION(content, "This class should be inherited by HTML elements only!");
return !IsBarredFromConstraintValidation();
// For the moment, all elements that are not barred from constraint validation
// accept the disabled attribute and elements that are always barred from
// constraint validation do not accept it (objects, fieldset, output).
// If one of these elements change and become not always barred from
// constraint validation or another element appear with constraint validation
// support and can't be disabled, this code will have to be changed.
return !content->HasAttr(kNameSpaceID_None, nsGkAtoms::disabled) &&
!IsBarredFromConstraintValidation();
}

Просмотреть файл

@ -0,0 +1,188 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Mozilla Foundation
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Mounir Lamouri <mounir.lamouri@mozilla.com> (original author)
*
* 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 ***** */
#ifndef nsIConstraintValidition_h___
#define nsIConstraintValidition_h___
#include "nsISupports.h"
#include "nsAutoPtr.h"
#include "nsString.h"
class nsDOMValidityState;
class nsIDOMValidityState;
class nsGenericHTMLFormElement;
#define NS_ICONSTRAINTVALIDATION_IID \
{ 0xca3824dc, 0x4f5c, 0x4878, \
{ 0xa6, 0x8a, 0x95, 0x54, 0x5f, 0xfa, 0x4b, 0xf9 } }
/**
* This interface is for form elements implementing the validity constraint API.
* See: http://dev.w3.org/html5/spec/forms.html#the-constraint-validation-api
*
* This interface has to be implemented by all elements implementing the API
* and only them.
*/
class nsIConstraintValidation : public nsISupports
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ICONSTRAINTVALIDATION_IID);
friend class nsDOMValidityState;
virtual ~nsIConstraintValidation();
PRBool IsValid() const { return mValidityBitField == 0; }
PRBool IsCandidateForConstraintValidation() const;
protected:
enum ValidityStateType
{
VALIDITY_STATE_VALUE_MISSING = 0x01, // 0b00000001
VALIDITY_STATE_TYPE_MISMATCH = 0x02, // 0b00000010
VALIDITY_STATE_PATTERN_MISMATCH = 0x04, // 0b00000100
VALIDITY_STATE_TOO_LONG = 0x08, // 0b00001000
VALIDITY_STATE_RANGE_UNDERFLOW = 0x10, // 0b00010000
VALIDITY_STATE_RANGE_OVERFLOW = 0x20, // 0b00100000
VALIDITY_STATE_STEP_MISMATCH = 0x40, // 0b01000000
VALIDITY_STATE_CUSTOM_ERROR = 0x80 // 0b10000000
};
// You can't instantiate an object from that class.
nsIConstraintValidation();
nsresult GetValidity(nsIDOMValidityState** aValidity);
nsresult GetValidationMessage(nsAString& aValidationMessage);
nsresult CheckValidity(PRBool* aValidity);
void SetCustomValidity(const nsAString& aError);
bool GetValidityState(ValidityStateType mState) const {
return mValidityBitField & mState;
}
void SetValidityState(ValidityStateType mState, PRBool mValue) {
if (mValue) {
mValidityBitField |= mState;
} else {
mValidityBitField &= ~mState;
}
}
virtual PRBool IsBarredFromConstraintValidation() const { return PR_FALSE; }
virtual nsresult GetValidationMessage(nsAString& aValidationMessage,
ValidityStateType aType) {
return NS_OK;
}
private:
/**
* A bitfield representing the current validity state of the element.
* Each bit represent an error. All bits to zero means the element is valid.
*/
PRInt8 mValidityBitField;
/**
* A pointer to the ValidityState object.
*/
nsRefPtr<nsDOMValidityState> mValidity;
/**
* The string representing the custom error.
*/
nsString mCustomValidity;
};
/**
* Use these macro for class inheriting from nsIConstraintValidation to forward
* functions to nsIConstraintValidation.
*/
#define NS_FORWARD_NSICONSTRAINTVALIDATION_EXCEPT_SETCUSTOMVALIDITY \
NS_IMETHOD GetValidity(nsIDOMValidityState** aValidity) { \
return nsIConstraintValidation::GetValidity(aValidity); \
} \
NS_IMETHOD GetWillValidate(PRBool* aWillValidate) { \
*aWillValidate = IsCandidateForConstraintValidation(); \
return NS_OK; \
} \
NS_IMETHOD GetValidationMessage(nsAString& aValidationMessage) { \
return nsIConstraintValidation::GetValidationMessage(aValidationMessage); \
} \
NS_IMETHOD CheckValidity(PRBool* aValidity) { \
return nsIConstraintValidation::CheckValidity(aValidity); \
}
#define NS_FORWARD_NSICONSTRAINTVALIDATION \
NS_FORWARD_NSICONSTRAINTVALIDATION_EXCEPT_SETCUSTOMVALIDITY \
NS_IMETHOD SetCustomValidity(const nsAString& aError) { \
nsIConstraintValidation::SetCustomValidity(aError); \
return NS_OK; \
}
/* Use these macro when class declares functions from nsIConstraintValidation */
#define NS_IMPL_NSICONSTRAINTVALIDATION_EXCEPT_SETCUSTOMVALIDITY(_from) \
NS_IMETHODIMP _from::GetValidity(nsIDOMValidityState** aValidity) { \
return nsIConstraintValidation::GetValidity(aValidity); \
} \
NS_IMETHODIMP _from::GetWillValidate(PRBool* aWillValidate) { \
*aWillValidate = IsCandidateForConstraintValidation(); \
return NS_OK; \
} \
NS_IMETHODIMP _from::GetValidationMessage(nsAString& aValidationMessage) { \
return nsIConstraintValidation::GetValidationMessage(aValidationMessage); \
} \
NS_IMETHODIMP _from::CheckValidity(PRBool* aValidity) { \
return nsIConstraintValidation::CheckValidity(aValidity); \
}
#define NS_IMPL_NSICONSTRAINTVALIDATION(_from) \
NS_IMPL_NSICONSTRAINTVALIDATION_EXCEPT_SETCUSTOMVALIDITY(_from) \
NS_IMETHODIMP _from::SetCustomValidity(const nsAString& aError) { \
nsIConstraintValidation::SetCustomValidity(aError); \
return NS_OK; \
}
NS_DEFINE_STATIC_IID_ACCESSOR(nsIConstraintValidation,
NS_ICONSTRAINTVALIDATION_IID)
#endif // nsIConstraintValidation_h___

Просмотреть файл

@ -842,6 +842,8 @@ nsTextInputListener::EditAction()
// Fire input event
mFrame->FireOnInput();
mTxtCtrlElement->OnValueChanged(PR_TRUE);
return NS_OK;
}
@ -1782,6 +1784,8 @@ nsTextEditorState::SetValue(const nsAString& aValue, PRBool aUserInput)
// If we've reached the point where the root node has been created, we
// can assume that it's safe to notify.
ValueWasChanged(!!mRootNode);
mTextCtrlElement->OnValueChanged(!!mRootNode);
}
void

Просмотреть файл

@ -202,6 +202,9 @@ _TEST_FILES = \
test_bug566160.html \
test_bug582412-1.html \
test_bug582412-2.html \
test_bug558788-1.html \
test_bug558788-2.html \
test_bug561634.html \
$(NULL)
libs:: $(_TEST_FILES)

Просмотреть файл

@ -8,6 +8,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=344615
<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"/>
<style>
input { background-color: rgb(0,0,0) !important; }
input:valid { background-color: rgb(0,255,0) !important; }
input:invalid { background-color: rgb(255,0,0) !important; }
</style>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=344615">Mozilla Bug 344615</a>
@ -40,6 +45,8 @@ function checkValidURL(element)
ok(!gInvalid, "The invalid event should not have been thrown");
is(element.validationMessage, '',
"Validation message should be the empty string");
is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
"rgb(0, 255, 0)", ":valid pseudo-class should apply");
}
function checkInvalidURL(element)
@ -52,6 +59,8 @@ function checkInvalidURL(element)
ok(gInvalid, "The invalid event should have been thrown");
is(element.validationMessage, "The entered URL is not valid.",
"Validation message should be related to invalid URL");
is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
"rgb(255, 0, 0)", ":invalid pseudo-class should apply");
}
var url = document.getElementById('i');

Просмотреть файл

@ -8,6 +8,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=345512
<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"/>
<style>
input { background-color: rgb(0,0,0) !important; }
input:valid { background-color: rgb(0,255,0) !important; }
input:invalid { background-color: rgb(255,0,0) !important; }
</style>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=345512">Mozilla Bug 345512</a>
@ -56,7 +61,7 @@ function checkPatternAttribute(element)
"pattern content attribute value should be 'bar'");
}
function completeValidityCheck(element, alwaysValid)
function completeValidityCheck(element, alwaysValid, isBarred)
{
if (element.type == 'file') {
// Need privileges to set a filename with .value.
@ -75,7 +80,7 @@ function completeValidityCheck(element, alwaysValid)
element.value = "foo";
}
checkValidPattern(element, true);
checkValidPattern(element, true, isBarred);
// Check when pattern does not match.
@ -93,11 +98,11 @@ function completeValidityCheck(element, alwaysValid)
if (!alwaysValid) {
checkInvalidPattern(element, true);
} else {
checkValidPattern(element, true);
checkValidPattern(element, true, isBarred);
}
}
function checkValidPattern(element, completeCheck)
function checkValidPattern(element, completeCheck, isBarred)
{
if (completeCheck) {
gInvalid = false;
@ -109,6 +114,11 @@ function checkValidPattern(element, completeCheck)
ok(!gInvalid, "Invalid event shouldn't have been thrown");
is(element.validationMessage, '',
"Validation message should be the empty string");
if (element.type != 'radio' && element.type != 'checkbox') {
is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
isBarred ? "rgb(0, 0, 0)" : "rgb(0, 255, 0)",
"The pseudo-class is not correctly applied");
}
} else {
ok(!element.validity.patternMismatch,
"Element should not suffer from pattern mismatch");
@ -132,6 +142,11 @@ function checkInvalidPattern(element, completeCheck)
ok(element.validity.patternMismatch,
"Element should suffer from pattern mismatch");
}
if (element.type != 'radio' && element.type != 'checkbox') {
is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
"rgb(255, 0, 0)", ":invalid pseudo-class should apply");
}
}
function checkPatternValidity(element)
@ -277,8 +292,8 @@ checkPatternAttribute(input);
// |validTypes| are the types which accept @pattern
// and |invalidTypes| are the ones which do not accept it.
var validTypes = Array('text', 'password', 'search', 'telephone', 'email', 'url');
var invalidTypes = Array('hidden', 'checkbox', 'radio', 'file', 'submit',
'image', 'reset', 'button');
var barredTypes = Array('hidden', 'reset', 'button');
var invalidTypes = Array('checkbox', 'radio', 'file', 'submit', 'image');
// TODO: 'datetime', 'date', 'month', 'week', 'time', 'datetime-local',
// 'number', 'range', ande 'color' do not accept the @pattern too but are
// not implemented yet.
@ -289,6 +304,11 @@ for each (type in validTypes) {
checkPatternValidity(input);
}
for each (type in barredTypes) {
input.type = type;
completeValidityCheck(input, true, true);
}
for each (type in invalidTypes) {
input.type = type;
completeValidityCheck(input, true);

Просмотреть файл

@ -8,6 +8,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=345624
<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"/>
<style>
input, textarea, fieldset, button, select, keygen, output { background-color: rgb(0,0,0) !important; }
:valid { background-color: rgb(0,255,0) !important; }
:invalid { background-color: rgb(255,0,0) !important; }
</style>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=345624">Mozilla Bug 345624</a>
@ -19,6 +24,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=345624
<select id='s' oninvalid="invalidEventHandler(event);"></select>
<textarea id='t' oninvalid="invalidEventHandler(event);"></textarea>
<keygen id='k'></keygen>
<output id='o'></output>
</div>
<pre id="test">
<script type="application/javascript">
@ -80,10 +86,42 @@ function checkConstraintValidationAPIDefaultValues(element)
ok(element.checkValidity(), "The element should be valid by default");
}
function checkDefaultPseudoClass()
{
is(window.getComputedStyle(document.getElementById('f'), null)
.getPropertyValue('background-color'), "rgb(0, 0, 0)",
"Nor :valid and :invalid should apply");
is(window.getComputedStyle(document.getElementById('o'), null)
.getPropertyValue('background-color'), "rgb(0, 0, 0)",
"Nor :valid and :invalid should apply");
todo_is(window.getComputedStyle(document.getElementById('k'), null)
.getPropertyValue('background-color'), "rgb(0, 0, 0)",
"Nor :valid and :invalid should apply");
is(window.getComputedStyle(document.getElementById('s'), null)
.getPropertyValue('background-color'), "rgb(0, 255, 0)",
":valid pseudo-class should apply");
is(window.getComputedStyle(document.getElementById('i'), null)
.getPropertyValue('background-color'), "rgb(0, 255, 0)",
":valid pseudo-class should apply");
is(window.getComputedStyle(document.getElementById('t'), null)
.getPropertyValue('background-color'), "rgb(0, 255, 0)",
":valid pseudo-class should apply");
is(window.getComputedStyle(document.getElementById('b'), null)
.getPropertyValue('background-color'), "rgb(0, 255, 0)",
":valid pseudo-class should apply");
}
function checkSpecificWillValidate()
{
// fieldset, keygen (TODO) and select elements
// fieldset, output, keygen (TODO) and select elements
ok(!document.getElementById('f').willValidate, "Fielset element should be barred from constraint validation");
ok(!document.getElementById('o').willValidate, "Output element should be barred from constraint validation");
todo(!document.getElementById('k').willValidate, "Keygen element should be barred from constraint validation");
ok(document.getElementById('s').willValidate, "Select element should not be barred from constraint validation");
@ -91,31 +129,51 @@ function checkSpecificWillValidate()
i = document.getElementById('i');
i.type = "hidden";
ok(!i.willValidate, "Hidden state input should be barred from constraint validation");
is(window.getComputedStyle(i, null).getPropertyValue('background-color'),
"rgb(0, 0, 0)", "Nor :valid and :invalid should apply");
i.type = "reset";
ok(!i.willValidate, "Reset button state input should be barred from constraint validation");
is(window.getComputedStyle(i, null).getPropertyValue('background-color'),
"rgb(0, 0, 0)", "Nor :valid and :invalid should apply");
i.type = "button";
ok(!i.willValidate, "Button state input should be barred from constraint validation");
is(window.getComputedStyle(i, null).getPropertyValue('background-color'),
"rgb(0, 0, 0)", "Nor :valid and :invalid should apply");
i.type = "";
i.readOnly = 'true';
ok(!i.willValidate, "Readonly input should be barred from constraint validation");
is(window.getComputedStyle(i, null).getPropertyValue('background-color'),
"rgb(0, 0, 0)", "Nor :valid and :invalid should apply");
i.removeAttribute('readOnly');
ok(i.willValidate, "Default input element should not be barred from constraint validation");
is(window.getComputedStyle(i, null).getPropertyValue('background-color'),
"rgb(0, 255, 0)", ":valid pseudo-class should apply");
// button element
b = document.getElementById('b');
b.type = "reset";
ok(!b.willValidate, "Reset state button should be barred from constraint validation");
is(window.getComputedStyle(b, null).getPropertyValue('background-color'),
"rgb(0, 0, 0)", "Nor :valid and :invalid should apply");
b.type = "button";
ok(!b.willValidate, "Button state button should be barred from constraint validation");
is(window.getComputedStyle(b, null).getPropertyValue('background-color'),
"rgb(0, 0, 0)", "Nor :valid and :invalid should apply");
b.type = "";
ok(b.willValidate, "Default button element should not be barred from constraint validation");
is(window.getComputedStyle(b, null).getPropertyValue('background-color'),
"rgb(0, 255, 0)", ":valid pseudo-class should apply");
// textarea element
t = document.getElementById('t');
t.readOnly = true;
ok(!t.willValidate, "Readonly textarea should be barred from constraint validation");
is(window.getComputedStyle(t, null).getPropertyValue('background-color'),
"rgb(0, 0, 0)", "Nor :valid and :invalid should apply");
t.removeAttribute('readOnly');
ok(t.willValidate, "Default textarea element should not be barred from constraint validation");
is(window.getComputedStyle(t, null).getPropertyValue('background-color'),
"rgb(0, 255, 0)", ":valid pseudo-class should apply");
// TODO: output elements are always barred from constraint validation.
// TODO: PROGRESS
@ -124,26 +182,44 @@ function checkSpecificWillValidate()
function checkCommonWillValidate(element)
{
// Not checking the default value because it has been check previously
// Not checking the default value because it has been checked previously.
element.disabled = true;
ok(!element.willValidate, "Disabled element should be barred from constraint validation");
is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
"rgb(0, 0, 0)", "Nor :valid and :invalid should apply");
element.removeAttribute('disabled');
// TODO: If an element has a datalist element ancestor, it is barred from constraint validation.
}
function checkCustomError(element)
function checkCustomError(element, isBarred)
{
element.setCustomValidity("message");
is(element.validationMessage, "message", "When the element has a custom validity message, validation message should return it");
if (!isBarred) {
is(element.validationMessage, "message",
"When the element has a custom validity message, validation message should return it");
} else {
is(element.validationMessage, "",
"An element barred from constraint validation can't have a validation message");
}
ok(element.validity.customError, "The element should suffer from a custom error");
ok(!element.validity.valid, "The element should not be valid with a custom error");
is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
isBarred ? "rgb(0, 0, 0)" : "rgb(255, 0, 0)",
":invalid pseudo-classs should apply");
element.setCustomValidity("");
is(element.validationMessage, "", "The element should not have a validation message when reseted");
ok(!element.validity.customError, "The element should not suffer anymore from a custom error");
ok(element.validity.valid, "The element should now be valid");
is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
isBarred ? "rgb(0, 0, 0)" : "rgb(0, 255, 0)",
":valid pseudo-classs should apply");
}
function checkCheckValidity(element)
@ -190,21 +266,23 @@ function checkValidityStateObjectAliveWithoutElement(element)
ok(v.valid, "When the element is not alive, it should be valid");
}
/* TODO: add <output> element when it will be implemented */
checkConstraintValidationAPIExist(document.getElementById('f'));
checkConstraintValidationAPIExist(document.getElementById('i'));
checkConstraintValidationAPIExist(document.getElementById('b'));
checkConstraintValidationAPIExist(document.getElementById('s'));
checkConstraintValidationAPIExist(document.getElementById('t'));
checkConstraintValidationAPIExist(document.getElementById('k'));
checkConstraintValidationAPIExist(document.getElementById('o'));
/* TODO: add <output> element when it will be implemented */
checkConstraintValidationAPIDefaultValues(document.getElementById('f'));
checkConstraintValidationAPIDefaultValues(document.getElementById('i'));
checkConstraintValidationAPIDefaultValues(document.getElementById('b'));
checkConstraintValidationAPIDefaultValues(document.getElementById('s'));
checkConstraintValidationAPIDefaultValues(document.getElementById('t'));
checkConstraintValidationAPIDefaultValues(document.getElementById('k'));
checkConstraintValidationAPIDefaultValues(document.getElementById('o'));
checkDefaultPseudoClass();
checkSpecificWillValidate();
@ -215,12 +293,13 @@ checkCommonWillValidate(document.getElementById('b'));
checkCommonWillValidate(document.getElementById('s'));
checkCommonWillValidate(document.getElementById('t'));
// Not checking fieldset, output and keygen
// because they are always barred from constraint validation.
checkCustomError(document.getElementById('i'));
checkCustomError(document.getElementById('b'));
checkCustomError(document.getElementById('s'));
checkCustomError(document.getElementById('t'));
/* TODO: add "keygen" element */
checkCustomError(document.getElementById('i'), false);
checkCustomError(document.getElementById('b'), false);
checkCustomError(document.getElementById('s'), false);
checkCustomError(document.getElementById('t'), false);
checkCustomError(document.getElementById('f'), true);
checkCustomError(document.getElementById('o'), true);
// Not checking fieldset, output and keygen
// because they are always barred from constraint validation.
@ -229,12 +308,13 @@ checkCheckValidity(document.getElementById('b'));
checkCheckValidity(document.getElementById('s'));
checkCheckValidity(document.getElementById('t'));
/* TODO: add "output" and "keygen" elements */
/* TODO: add "keygen" element */
checkValidityStateObjectAliveWithoutElement("fieldset");
checkValidityStateObjectAliveWithoutElement("input");
checkValidityStateObjectAliveWithoutElement("button");
checkValidityStateObjectAliveWithoutElement("select");
checkValidityStateObjectAliveWithoutElement("textarea");
checkValidityStateObjectAliveWithoutElement("output");
</script>
</pre>

Просмотреть файл

@ -8,6 +8,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=345624
<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"/>
<style>
input, textarea { background-color: rgb(0,0,0) !important; }
:-moz-any(input,textarea):valid { background-color: rgb(0,255,0) !important; }
:-moz-any(input,textarea):invalid { background-color: rgb(255,0,0) !important; }
</style>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=345624">Mozilla Bug 345624</a>
@ -31,20 +36,28 @@ function checkTooLongValidity(element)
element.value = "foo";
ok(!element.validity.tooLong,
"Element should not be too long when maxlength is not set");
is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
"rgb(0, 255, 0)", ":valid pseudo-class should apply");
element.maxLength = 3;
ok(!element.validity.tooLong,
"Element should not be to long when maxlength = value length");
is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
"rgb(0, 255, 0)", ":valid pseudo-class should apply");
element.maxLength = 5;
ok(!element.validity.tooLong,
"Element should not be too long when maxlength > value length");
is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
"rgb(0, 255, 0)", ":valid pseudo-class should apply");
ok(element.validity.valid, "Element should be valid");
element.maxLength = 2;
ok(element.validity.tooLong,
"Element should be too long when maxlength < value length");
is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
"rgb(255, 0, 0)", ":invalid pseudo-class should apply");
ok(!element.validity.valid,
"Element should not be valid when it is too long");
@ -54,6 +67,8 @@ function checkTooLongValidity(element)
"The validation message text is not correct");
ok(!element.checkValidity(), "The element should not be valid");
element.setCustomValidity("custom message");
is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
"rgb(255, 0, 0)", ":invalid pseudo-class should apply");
is(element.validationMessage, "custom message",
"Custom message should be shown instead of too long one");
}

Просмотреть файл

@ -8,15 +8,17 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=345822
<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"/>
<style>
input, textarea { background-color: rgb(0,0,0) !important; }
:valid { background-color: rgb(0,255,0) !important; }
:invalid { background-color: rgb(255,0,0) !important; }
</style>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=345822">Mozilla Bug 345822</a>
<p id="display"></p>
<div id="content" style="display: none">
<div id="content">
<form>
<input name="input" id='i'>
<input name="input" id='r' type='radio'>
<textarea name="textarea" id='t'></textarea>
</form>
</div>
<pre id="test">
@ -49,7 +51,7 @@ function checkRequiredAttribute(element)
"Element required attribute should be disabled");
}
function checkNotSufferingFromBeingMissing(element)
function checkNotSufferingFromBeingMissing(element, doNotApply)
{
ok(!element.validity.valueMissing,
"Element should not suffer from value missing");
@ -57,6 +59,12 @@ function checkNotSufferingFromBeingMissing(element)
ok(element.checkValidity(), "Element should be valid");
is(element.validationMessage, "",
"Validation message should be the empty string");
if (element.type != 'radio' && element.type != 'checkbox') {
is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
doNotApply ? "rgb(0, 0, 0)" : "rgb(0, 255, 0)",
"The pseudo-class is not correctly applied");
}
}
function checkSufferingFromBeingMissing(element)
@ -89,10 +97,18 @@ function checkSufferingFromBeingMissing(element)
"This field is mandatory, you have to fill it.",
"Validation message is wrong");
}
if (element.type != 'radio' && element.type != 'checkbox') {
is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
"rgb(255, 0, 0)", ":invalid pseudo-class should apply");
}
}
function checkTextareaRequiredValidity(element)
function checkTextareaRequiredValidity()
{
var element = document.createElement('textarea');
document.forms[0].appendChild(element);
element.value = '';
element.required = false;
checkNotSufferingFromBeingMissing(element);
@ -101,7 +117,7 @@ function checkTextareaRequiredValidity(element)
checkSufferingFromBeingMissing(element);
element.readOnly = true;
checkNotSufferingFromBeingMissing(element);
checkNotSufferingFromBeingMissing(element, true);
element.readOnly = false;
checkSufferingFromBeingMissing(element);
@ -114,22 +130,34 @@ function checkTextareaRequiredValidity(element)
element.required = false;
checkNotSufferingFromBeingMissing(element);
document.forms[0].removeChild(element);
}
function checkInputRequiredNotApply(element)
function checkInputRequiredNotApply(type, isBarred)
{
var element = document.createElement('input');
element.type = type;
document.forms[0].appendChild(element);
element.value = '';
element.required = false;
checkNotSufferingFromBeingMissing(element);
checkNotSufferingFromBeingMissing(element, isBarred);
element.required = true;
checkNotSufferingFromBeingMissing(element);
checkNotSufferingFromBeingMissing(element, isBarred);
element.required = false;
document.forms[0].removeChild(element);
}
function checkInputRequiredValidity(element)
function checkInputRequiredValidity(type)
{
var element = document.createElement('input');
element.type = type;
document.forms[0].appendChild(element);
element.value = '';
element.required = false;
checkNotSufferingFromBeingMissing(element);
@ -138,7 +166,7 @@ function checkInputRequiredValidity(element)
checkSufferingFromBeingMissing(element);
element.readOnly = true;
checkNotSufferingFromBeingMissing(element);
checkNotSufferingFromBeingMissing(element, true);
element.readOnly = false;
checkSufferingFromBeingMissing(element);
@ -155,12 +183,16 @@ function checkInputRequiredValidity(element)
element.value = '';
checkSufferingFromBeingMissing(element);
element.required = false;
document.forms[0].removeChild(element);
checkNotSufferingFromBeingMissing(element);
}
function checkInputRequiredValidityForCheckbox(element)
function checkInputRequiredValidityForCheckbox()
{
var element = document.createElement('input');
element.type = 'checkbox';
document.forms[0].appendChild(element);
element.checked = false;
element.required = false;
checkNotSufferingFromBeingMissing(element);
@ -176,10 +208,17 @@ function checkInputRequiredValidityForCheckbox(element)
element.required = false;
checkNotSufferingFromBeingMissing(element);
document.forms[0].removeChild(element);
}
function checkInputRequiredValidityForRadio(element)
function checkInputRequiredValidityForRadio()
{
var element = document.createElement('input');
element.type = 'radio';
element.name = 'test'
document.forms[0].appendChild(element);
element.checked = false;
element.required = false;
checkNotSufferingFromBeingMissing(element);
@ -193,28 +232,28 @@ function checkInputRequiredValidityForRadio(element)
element.checked = false;
checkSufferingFromBeingMissing(element);
element.required = false;
checkNotSufferingFromBeingMissing(element);
// A required radio button should not suffer from value missing if another
// radio button from the same group is checked.
var element2 = document.createElement('input');//document.getElementById('r');
document.forms[0].appendChild(element2);
element2.name = 'input';
var element2 = document.createElement('input');
element2.type = 'radio';
element2.checked = false;
element2.required = false;
element.checked = false;
element.required = true;
checkSufferingFromBeingMissing(element);
element2.name = 'test';
element2.checked = true;
element2.required = false;
document.forms[0].appendChild(element2);
// Adding a checked radio should make required radio in the group not
// suffering from being missing.
checkNotSufferingFromBeingMissing(element);
element.checked = false;
element2.checked = false;
checkSufferingFromBeingMissing(element);
// The other radio button should not be disabled.
// A disabled checked radio button in the radio group
// is enough to not suffer from value missing.
element2.checked = true;
element2.disabled = true;
checkNotSufferingFromBeingMissing(element);
@ -227,10 +266,23 @@ function checkInputRequiredValidityForRadio(element)
element2.required = true;
checkNotSufferingFromBeingMissing(element);
checkSufferingFromBeingMissing(element2);
element.checked = true;
checkNotSufferingFromBeingMissing(element2);
// The checked radio is not in the group anymore, element2 should be invalid.
document.forms[0].removeChild(element);
checkSufferingFromBeingMissing(element2);
document.forms[0].removeChild(element2);
}
function checkInputRequiredValidityForFile(element)
function checkInputRequiredValidityForFile()
{
var element = document.createElement('input');
element.type = 'file'
document.forms[0].appendChild(element);
function createFileWithData(fileName, fileData) {
var dirSvc = Components.classes["@mozilla.org/file/directory_service;1"]
.getService(Components.interfaces.nsIProperties);
@ -269,52 +321,42 @@ function checkInputRequiredValidityForFile(element)
checkNotSufferingFromBeingMissing(element);
file.remove(false);
document.forms[0].removeChild(element);
}
var textarea = document.getElementById('t');
var input = document.getElementById('i');
checkRequiredAttribute(textarea);
checkTextareaRequiredValidity(textarea);
checkRequiredAttribute(document.createElement('textarea'));
checkTextareaRequiredValidity();
// Every input element should have the required attribute.
checkRequiredAttribute(input);
checkRequiredAttribute(document.createElement('input'));
// The required attribute behavior depend of the input type.
// First of all, checks for the types which do not use the required attribute.
// The require attribute behavior depend of the input type.
// First of all, checks for types that make the element barred from
// constraint validation.
var typeBarredFromConstraintValidation = ["hidden", "button", "reset"];
for each (type in typeRequireNotApply) {
checkInputRequiredNotApply(type, true);
}
// Then, checks for the types which do not use the required attribute.
// TODO: check 'color' and 'range' when they will be implemented.
input.type = 'hidden';
checkInputRequiredNotApply(input);
input.type = 'submit';
checkInputRequiredNotApply(input);
input.type = 'button';
checkInputRequiredNotApply(input);
input.type = 'reset';
checkInputRequiredNotApply(input);
input.type = 'image';
checkInputRequiredNotApply(input);
var typeRequireNotApply = ["submit", "image"];
for each (type in typeRequireNotApply) {
checkInputRequiredNotApply(type, false);
}
// Now, checking for all types which accept the required attribute.
// TODO: check 'datetime', 'date', 'month', 'week', 'time', 'datetime-local'
// and 'number' when they will be implemented.
input.type = 'text';
checkInputRequiredValidity(input);
input.type = 'password';
checkInputRequiredValidity(input);
input.type = 'checkbox';
checkInputRequiredValidityForCheckbox(input);
input.type = 'radio';
checkInputRequiredValidityForRadio(input);
input.type = 'file';
checkInputRequiredValidityForFile(input);
input.type = 'search';
checkInputRequiredValidity(input);
input.type = 'tel';
checkInputRequiredValidity(input);
input.type = 'email';
checkInputRequiredValidity(input);
input.type = 'url';
checkInputRequiredValidity(input);
var typeRequireApply = ["text", "password", "search", "tel", "email", "url"];
for each (type in typeRequireApply) {
checkInputRequiredValidity(type);
}
checkInputRequiredValidityForCheckbox();
checkInputRequiredValidityForRadio();
checkInputRequiredValidityForFile();
</script>
</pre>

Просмотреть файл

@ -8,6 +8,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=555559
<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"/>
<style>
input { background-color: rgb(0,0,0) !important; }
input:valid { background-color: rgb(0,255,0) !important; }
input:invalid { background-color: rgb(255,0,0) !important; }
</style>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=555559">Mozilla Bug 555559</a>
@ -42,6 +47,8 @@ function checkValidEmailAddress(element)
ok(!gInvalid, "The invalid event should not have been thrown");
is(element.validationMessage, '',
"Validation message should be the empty string");
is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
"rgb(0, 255, 0)", ":valid pseudo-class should apply");
}
function checkInvalidEmailAddress(element)
@ -54,6 +61,8 @@ function checkInvalidEmailAddress(element)
ok(gInvalid, "The invalid event should have been thrown");
is(element.validationMessage, "The entered email address is not valid.",
"Validation message is not valid");
is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
"rgb(255, 0, 0)", ":invalid pseudo-class should apply");
}
var email = document.forms[0].elements[0];

Просмотреть файл

@ -0,0 +1,202 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=558788
-->
<head>
<title>Test for Bug 558788</title>
<script type="application/javascript" src="/MochiKit/packed.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<style>
input, textarea { background-color: rgb(0,0,0) !important; }
:-moz-any(input,textarea):valid { background-color: rgb(0,255,0) !important; }
:-moz-any(input,textarea):invalid { background-color: rgb(255,0,0) !important; }
</style>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=558788">Mozilla Bug 558788</a>
<p id="display"></p>
<div id="content">
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 558788 **/
/**
* This test checks the behavior of :valid and :invalid pseudo-classes
* when the user is typing/interacting with the element.
* Only <input> and <textarea> elements can have there validity changed by an
* user input.
*/
var gContent = document.getElementById('content');
function checkValidApplies(elmt)
{
is(window.getComputedStyle(elmt, null).getPropertyValue('background-color'),
"rgb(0, 255, 0)", ":valid pseudo-class should apply");
}
function checkInvalidApplies(elmt)
{
is(window.getComputedStyle(elmt, null).getPropertyValue('background-color'),
"rgb(255, 0, 0)", ":invalid pseudo-class should apply");
}
function checkMissing(elementName)
{
var element = document.createElement(elementName);
element.required = true;
gContent.appendChild(element);
checkInvalidApplies(element);
element.focus();
synthesizeKey("a", {});
checkValidApplies(element);
synthesizeKey("VK_BACK_SPACE", {});
checkInvalidApplies(element);
gContent.removeChild(element);
}
function checkTooLong(elementName)
{
var element = document.createElement(elementName);
element.value = "foo";
element.maxLength = 2;
gContent.appendChild(element);
checkInvalidApplies(element);
element.focus();
synthesizeKey("VK_BACK_SPACE", {});
checkValidApplies(element);
gContent.removeChild(element);
}
function checkTextAreaMissing()
{
checkMissing('textarea');
}
function checkTextAreaTooLong()
{
checkTooLong('textarea');
}
function checkTextArea()
{
checkTextAreaMissing();
checkTextAreaTooLong();
}
function checkInputMissing()
{
checkMissing('input');
}
function checkInputTooLong()
{
checkTooLong('input');
}
function checkInputEmail()
{
var element = document.createElement('input');
element.type = 'email';
gContent.appendChild(element);
checkValidApplies(element);
element.focus();
synthesizeKey("a", {});
checkInvalidApplies(element);
sendString("@b.c", element);
checkValidApplies(element);
synthesizeKey("VK_BACK_SPACE", {});
for (var i=0; i<4; ++i) {
checkInvalidApplies(element);
synthesizeKey("VK_BACK_SPACE", {});
}
checkValidApplies(element);
gContent.removeChild(element);
}
function checkInputURL()
{
var element = document.createElement('input');
element.type = 'url';
gContent.appendChild(element);
checkValidApplies(element);
element.focus();
synthesizeKey("h", {});
checkInvalidApplies(element);
sendString("ttp://mozilla.org", element);
checkValidApplies(element);
for (var i=0; i<13; ++i) {
synthesizeKey("VK_BACK_SPACE", {});
checkValidApplies(element);
}
synthesizeKey("VK_BACK_SPACE", {});
for (var i=0; i<4; ++i) {
checkInvalidApplies(element);
synthesizeKey("VK_BACK_SPACE", {});
}
checkValidApplies(element);
gContent.removeChild(element);
}
function checkInputPattern()
{
var element = document.createElement('input');
element.pattern = "[0-9]*"
gContent.appendChild(element);
checkValidApplies(element);
element.focus();
synthesizeKey("0", {});
checkValidApplies(element);
synthesizeKey("a", {});
checkInvalidApplies(element);
synthesizeKey("VK_BACK_SPACE", {});
checkValidApplies(element);
synthesizeKey("VK_BACK_SPACE", {});
checkValidApplies(element);
gContent.removeChild(element);
}
function checkInput()
{
checkInputMissing();
checkInputTooLong();
checkInputEmail();
checkInputURL();
checkInputPattern();
}
checkTextArea();
checkInput();
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -0,0 +1,145 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=558788
-->
<head>
<title>Test for Bug 558788</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=558788">Mozilla Bug 558788</a>
<p id="display"></p>
<div id="content" style="display:none;">
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 558788 **/
var validElementsDescription = [
/* element type value required pattern maxlength */
/* <input> */
[ "input", null, null, null, null, null ],
/* <input required value='foo'> */
[ "input", null, "foo", true, null, null ],
/* <input type='email'> */
[ "input", "email", null, null, null, null ],
/* <input type='email' value='foo@mozilla.org'> */
[ "input", "email", "foo@mozilla.org", null, null, null ],
/* <input type='url'> */
[ "input", "url", null, null, null, null ],
/* <input type='url' value='http://mozilla.org'> */
[ "input", "url", "http://mozilla.org", null, null, null ],
/* <input pattern='\\d\\d'> */
[ "input", null, null, null, "\\d\\d", null ],
/* <input pattern='\\d\\d' value='42'> */
[ "input", null, "42", null, "\\d\\d", null ],
/* <input maxlength='3'> */
[ "input", null, null, null, null, "3" ],
/* <input maxlength='3'> */
[ "input", null, "foo", null, null, "3" ],
/* <textarea></textarea> */
[ "textarea", null, null, null, null, null ],
/* <textarea required>foo</textarea> */
[ "textarea", null, "foo", true, null, null ],
];
var invalidElementsDescription = [
/* element type value required pattern maxlength valid-value */
/* <input required> */
[ "input", null, null, true, null, null, "foo" ],
/* <input type='email' value='foo'> */
[ "input", "email", "foo", null, null, null, "foo@mozilla.org" ],
/* <input type='url' value='foo'> */
[ "input", "url", "foo", null, null, null, "http://mozilla.org" ],
/* <input pattern='\\d\\d' value='foo'> */
[ "input", null, "foo", null, "\\d\\d", null, "42" ],
/* <input maxlength='3' value='foo'> */
[ "input", null, "foobar", null, null, "3", "foo" ],
/* <textarea required></textarea> */
[ "textarea", null, null, true, null, null, "foo" ],
];
var validElements = [];
var invalidElements = [];
function appendElements(aElementsDesc, aElements)
{
var content = document.getElementById('content');
var length = aElementsDesc.length;
for (var i=0; i<length; ++i) {
var e = document.createElement(aElementsDesc[i][0]);
if (aElementsDesc[i][1]) {
e.type = aElementsDesc[i][1];
}
if (aElementsDesc[i][2]) {
e.value = aElementsDesc[i][2];
}
if (aElementsDesc[i][3]) {
e.required = true;
}
if (aElementsDesc[i][4]) {
e.pattern = aElementsDesc[i][4];
}
if (aElementsDesc[i][5]) {
e.maxLength = aElementsDesc[i][5];
}
content.appendChild(e);
// Adding the element to the appropriate list.
aElements.push(e);
}
}
function compareArrayWithSelector(aElements, aSelector)
{
var aSelectorElements = document.querySelectorAll(aSelector);
is(aSelectorElements.length, aElements.length,
aSelector + " selector should return the correct number of elements");
if (aSelectorElements.length != aElements.length) {
return;
}
var length = aElements.length;
for (var i=0; i<length; ++i) {
is(aSelectorElements[i], aElements[i],
aSelector + " should return the correct elements");
}
}
function makeInvalidElementsValid(aInvalidElements,
aInvalidElementsDesc,
aValidElements)
{
var length = aInvalidElementsDesc.length;
for (var i=0; i<length; ++i) {
var e = aInvalidElements.shift();
e.value = aInvalidElementsDesc[i][6];
aValidElements.push(e);
}
}
appendElements(validElementsDescription, validElements);
appendElements(invalidElementsDescription, invalidElements);
compareArrayWithSelector(validElements, ":valid");
compareArrayWithSelector(invalidElements, ":invalid");
makeInvalidElementsValid(invalidElements, invalidElementsDescription,
validElements);
compareArrayWithSelector(validElements, ":valid");
compareArrayWithSelector(invalidElements, ":invalid");
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -0,0 +1,144 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=561634
-->
<head>
<title>Test for Bug 561634</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=561634">Mozilla Bug 561634</a>
<p id="display"></p>
<!--<div id="content" style="display: none">-->
<div id="content">
<form>
</form>
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 561634 **/
function checkEmptyForm()
{
ok(document.forms[0].checkValidity(), "An empty form is valid");
}
function checkInvalidNonSubmittable()
{
var f = document.forms[0];
var o = document.createElement('output');
var fs = document.createElement('fieldset');
f.appendChild(o);
f.appendChild(fs);
o.setCustomValidity("foo");
fs.setCustomValidity("foo");
ok(f.checkValidity(),
"A form with invalid non-submittable elements is valid");
f.removeChild(o);
f.removeChild(fs);
}
function checkBarredFromConstraintValidation()
{
var f = document.forms[0];
var i = document.createElement('input');
i.type = 'hidden';
f.appendChild(i);
i.setCustomValidity("foo");
ok(f.checkValidity(),
"A form with invalid submittable element barred from constraint validation is valid");
f.removeChild(i);
}
function checkValid()
{
var f = document.forms[0];
var i = document.createElement('input');
f.appendChild(i);
ok(f.checkValidity(), "A form with valid elements is valid");
f.removeChild(i);
}
function checkInvalid()
{
var f = document.forms[0];
var i = document.createElement('input');
f.appendChild(i);
i.setCustomValidity("foo");
ok(!f.checkValidity(), "A form with invalid elements is invalid");
var i2 = document.createElement('input');
f.appendChild(i2);
ok(!f.checkValidity(),
"A form with at least one invalid element is invalid");
// Check event is fired
i.addEventListener("invalid", function (e) {
ok(true, "invalid event should have been fired on invalid elements");
SimpleTest.finish();
}, false);
f.removeChild(i2);
f.removeChild(i);
}
function checkInvalidEvent()
{
var f = document.forms[0];
var i = document.createElement('input');
f.appendChild(i);
var i2 = document.createElement('input');
f.appendChild(i2);
i.setCustomValidity("foo");
var invalidEventForInvalidElement = false;
var invalidEventForValidElement = false;
i.addEventListener("invalid", function (e) {
invalidEventForInvalidElement = true;
ok(e.cancelable, "invalid event should be cancelable");
ok(!e.bubbles, "invalid event should not bubble");
}, false);
i2.addEventListener("invalid", function (e) {
invalidEventForValidElement = true;
}, false);
f.checkValidity();
SimpleTest.executeSoon(function () {
ok(invalidEventForInvalidElement,
"invalid event should be fired on invalid elements");
ok(!invalidEventForValidElement,
"invalid event should not be fired on valid elements");
});
f.removeChild(i2);
f.removeChild(i);
}
checkEmptyForm();
checkInvalidNonSubmittable();
checkBarredFromConstraintValidation();
checkValid();
checkInvalid();
checkInvalidEvent();
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -8,6 +8,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=561640
<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"/>
<style>
input, textarea { background-color: rgb(0,0,0) !important; }
:-moz-any(input,textarea):valid { background-color: rgb(0,255,0) !important; }
:-moz-any(input,textarea):invalid { background-color: rgb(255,0,0) !important; }
</style>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=561640">Mozilla Bug 561640</a>
@ -25,11 +30,15 @@ var content = document.getElementById('content');
function checkValid(elmt)
{
ok(!elmt.validity.tooLong, "element should not be too long");
is(window.getComputedStyle(elmt, null).getPropertyValue('background-color'),
"rgb(0, 255, 0)", ":valid pseudo-class should apply");
}
function checkInvalid(elmt)
{
ok(elmt.validity.tooLong, "element should be too long");
is(window.getComputedStyle(elmt, null).getPropertyValue('background-color'),
"rgb(255, 0, 0)", ":invalid pseudo-class should apply");
}
for each (var elmtName in elements) {

Просмотреть файл

@ -329,6 +329,7 @@ void nsBuiltinDecoder::MetadataLoaded()
// Only inform the element of FirstFrameLoaded if not doing a load() in order
// to fulfill a seek, otherwise we'll get multiple loadedfirstframe events.
MonitorAutoEnter mon(mMonitor);
PRBool resourceIsLoaded = !mResourceLoaded && mStream &&
mStream->IsDataCachedToEndOfStream(mDecoderPosition);
if (mElement && notifyElement) {
@ -339,7 +340,6 @@ void nsBuiltinDecoder::MetadataLoaded()
// before reaching here, so only change the
// state if we're still set to the original
// loading state.
MonitorAutoEnter mon(mMonitor);
if (mPlayState == PLAY_STATE_LOADING) {
if (mRequestedSeekTime >= 0.0) {
ChangeState(PLAY_STATE_SEEKING);

Просмотреть файл

@ -133,6 +133,8 @@ nsWebMReader::~nsWebMReader()
mVideoPackets.Reset();
mAudioPackets.Reset();
vpx_codec_destroy(&mVP8);
vorbis_block_clear(&mVorbisBlock);
vorbis_dsp_clear(&mVorbisDsp);
vorbis_info_clear(&mVorbisInfo);
@ -143,7 +145,7 @@ nsWebMReader::~nsWebMReader()
nsresult nsWebMReader::Init()
{
if(vpx_codec_dec_init(&mVP8, &vpx_codec_vp8_dx_algo, NULL, 0)) {
if (vpx_codec_dec_init(&mVP8, &vpx_codec_vp8_dx_algo, NULL, 0)) {
return NS_ERROR_FAILURE;
}

Просмотреть файл

@ -48,6 +48,7 @@
*/
interface nsIDOMDOMSettableTokenList;
interface nsIDOMValidityState;
[scriptable, uuid(0f7f15a9-ea72-4feb-b2b5-2fcbc9c10ab8)]
interface nsIDOMHTMLOutputElement : nsIDOMHTMLElement
@ -60,16 +61,11 @@ interface nsIDOMHTMLOutputElement : nsIDOMHTMLElement
attribute DOMString defaultValue;
attribute DOMString value;
/**
* The next attributes depend on the constraint validation API.
* Keeping them commented until the constraint validation API is implemented.
* See bug bug 345624.
*/
//readonly attribute boolean willValidate;
//readonly attribute ValidityState validity;
//readonly attribute DOMString validationMessage;
//boolean checkValidity();
//void setCustomValidity(in DOMString error);
readonly attribute boolean willValidate;
readonly attribute nsIDOMValidityState validity;
readonly attribute DOMString validationMessage;
boolean checkValidity();
void setCustomValidity(in DOMString error);
/**
* The labels IDL attribute will be added with bug 556743.

Просмотреть файл

@ -41,9 +41,10 @@
interface nsIDOMFormData;
[scriptable, uuid(a5735b98-7a5f-4242-8c9a-3805f3f61b76)]
[scriptable, uuid(55bdaf9b-eacb-49d6-b4b1-a27e61ed54fc)]
interface nsIDOMNSHTMLFormElement : nsISupports
{
attribute DOMString encoding;
nsIDOMFormData getFormData();
boolean checkValidity();
};

Просмотреть файл

@ -86,6 +86,8 @@
#include "nsSerializationHelper.h"
#include "nsIFrame.h"
#include "nsIView.h"
#include "nsIEventListenerManager.h"
#include "nsGeolocation.h"
#ifdef MOZ_WIDGET_QT
#include <QX11EmbedWidget>
@ -509,6 +511,11 @@ TabChild::~TabChild()
if (mCx) {
DestroyCx();
}
nsIEventListenerManager* elm = mTabChildGlobal->GetListenerManager(PR_FALSE);
if (elm) {
elm->Disconnect();
}
mTabChildGlobal->mTabChild = nsnull;
}
@ -983,6 +990,7 @@ TabChild::AllocPGeolocationRequest(const IPC::URI&)
bool
TabChild::DeallocPGeolocationRequest(PGeolocationRequestChild* actor)
{
static_cast<nsGeolocationRequest*>(actor)->Release();
return true;
}

Просмотреть файл

@ -304,7 +304,7 @@ private:
bool InitTabChildGlobal();
nsCOMPtr<nsIWebNavigation> mWebNav;
TabChildGlobal* mTabChildGlobal;
nsRefPtr<TabChildGlobal> mTabChildGlobal;
PRUint32 mChromeFlags;
DISALLOW_EVIL_CONSTRUCTORS(TabChild);

Просмотреть файл

@ -1019,10 +1019,13 @@ nsGeolocation::RegisterRequestWithPrompt(nsGeolocationRequest* request)
// the one and only TabChild.
TabChild* child = GetTabChildFrom(window->GetDocShell());
PGeolocationRequestChild* a =
child->SendPGeolocationRequestConstructor(request, IPC::URI(mURI));
child->SendPGeolocationRequestConstructor(request, IPC::URI(mURI));
// Retain a reference so the object isn't deleted without IPDL's knowledge.
// Corresponding release occurs in DeallocPGeolocationRequest.
request->AddRef();
(void) a->Sendprompt();
unused << request->Sendprompt();
return;
}
#endif

Просмотреть файл

@ -139,6 +139,7 @@ extern nsIParserService *sParserService;
nsEditor::nsEditor()
: mModCount(0)
, mFlags(0)
, mPresShellWeak(nsnull)
, mUpdateCount(0)
, mSpellcheckCheckboxState(eTriUnset)

Просмотреть файл

@ -140,7 +140,7 @@ nsSelectionState::IsCollapsed()
nsCOMPtr<nsIDOMRange> range;
mArray[0].GetRange(address_of(range));
NS_ENSURE_TRUE(range, PR_FALSE);
PRBool bIsCollapsed;
PRBool bIsCollapsed = PR_FALSE;
range->GetCollapsed(&bIsCollapsed);
return bIsCollapsed;
}
@ -161,10 +161,11 @@ nsSelectionState::IsEqual(nsSelectionState *aSelState)
NS_ENSURE_TRUE(myRange && itsRange, PR_FALSE);
PRInt16 compResult;
myRange->CompareBoundaryPoints(nsIDOMRange::START_TO_START, itsRange, &compResult);
if (compResult) return PR_FALSE;
myRange->CompareBoundaryPoints(nsIDOMRange::END_TO_END, itsRange, &compResult);
if (compResult) return PR_FALSE;
nsresult rv;
rv = myRange->CompareBoundaryPoints(nsIDOMRange::START_TO_START, itsRange, &compResult);
if (NS_FAILED(rv) || compResult) return PR_FALSE;
rv = myRange->CompareBoundaryPoints(nsIDOMRange::END_TO_END, itsRange, &compResult);
if (NS_FAILED(rv) || compResult) return PR_FALSE;
}
// if we got here, they are equal
return PR_TRUE;

Просмотреть файл

@ -0,0 +1,18 @@
<html>
<head>
<style>
@font-face {
font-family: t;
src: url(580719-bad_head_table.ttf);
}
p.t {
font-size: 40px;
font-family: t;
}
</style>
</head>
<body>
<p class="t">Lorem ipsum</p>
</body>
</html>

Двоичные данные
gfx/tests/crashtests/580719-bad_head_table.ttf Normal file

Двоичный файл не отображается.

Просмотреть файл

@ -79,3 +79,4 @@ load balinese-letter-spacing.html
load 580100-1.html
load 580212-1.html
skip-if(gtk2Widget) load 580233-1.html
load 580719-1.html

Просмотреть файл

@ -199,10 +199,13 @@ CPPSRCS += \
$(NULL)
endif
ifneq (,$(filter x86 x86_64,$(CPU_ARCH)))
ifeq (86,$(findstring 86,$(OS_TEST)))
ifdef __GNUC__
gfxAlphaRecovery.$(OBJ_SUFFIX): MODULE_OPTIMIZE_FLAGS += -msse2
endif
ifdef SOLARIS_SUNPRO_CXX
gfxAlphaRecovery.$(OBJ_SUFFIX): OS_CXXFLAGS += -xarch=sse2 -xO4
endif
endif
SHARED_LIBRARY_LIBS += \

Просмотреть файл

@ -205,7 +205,7 @@ gfxAlphaRecovery::RecoverAlphaSSE2(gfxImageSurface* blackSurf,
unsigned char* blackData = blackSurf->Data();
unsigned char* whiteData = whiteSurf->Data();
if (NS_PTR_TO_UINT32(blackData) & 0xf != NS_PTR_TO_UINT32(whiteData) & 0xf ||
if ((NS_PTR_TO_UINT32(blackData) & 0xf) != (NS_PTR_TO_UINT32(whiteData) & 0xf) ||
(blackSurf->Stride() - whiteSurf->Stride()) & 0xf) {
// Cannot keep these in alignment.
return PR_FALSE;
@ -230,9 +230,9 @@ gfxAlphaRecovery::RecoverAlphaSSE2(gfxImageSurface* blackSurf,
// at a time loop.
for (; j < size.width - 8; j += 8) {
__m128i black1 = _mm_load_si128((__m128i*)blackData);
__m128i white1 = _mm_load_si128((__m128i*)whiteData);
__m128i white1 = _mm_load_si128((__m128i*)whiteData);
__m128i black2 = _mm_load_si128((__m128i*)(blackData + 16));
__m128i white2 = _mm_load_si128((__m128i*)(whiteData + 16));
__m128i white2 = _mm_load_si128((__m128i*)(whiteData + 16));
// Execute the same instructions as described in RecoverPixel, only
// using an SSE2 packed saturated subtract.
@ -260,7 +260,7 @@ gfxAlphaRecovery::RecoverAlphaSSE2(gfxImageSurface* blackSurf,
}
for (; j < size.width - 4; j += 4) {
__m128i black = _mm_load_si128((__m128i*)blackData);
__m128i white = _mm_load_si128((__m128i*)whiteData);
__m128i white = _mm_load_si128((__m128i*)whiteData);
white = _mm_subs_epu8(white, black);
white = _mm_subs_epu8(greenMask, white);

Просмотреть файл

@ -54,15 +54,16 @@ gfxAlphaBoxBlur::~gfxAlphaBoxBlur()
gfxContext*
gfxAlphaBoxBlur::Init(const gfxRect& aRect,
const gfxIntSize& aSpreadRadius,
const gfxIntSize& aBlurRadius,
const gfxRect* aDirtyRect,
const gfxRect* aSkipRect)
{
mSpreadRadius = aSpreadRadius;
mBlurRadius = aBlurRadius;
gfxRect rect(aRect);
rect.Outset(aBlurRadius.height, aBlurRadius.width,
aBlurRadius.height, aBlurRadius.width);
rect.Outset(aBlurRadius + aSpreadRadius);
rect.RoundOut();
if (rect.IsEmpty())
@ -74,8 +75,7 @@ gfxAlphaBoxBlur::Init(const gfxRect& aRect,
mHasDirtyRect = PR_TRUE;
mDirtyRect = *aDirtyRect;
gfxRect requiredBlurArea = mDirtyRect.Intersect(rect);
requiredBlurArea.Outset(aBlurRadius.height, aBlurRadius.width,
aBlurRadius.height, aBlurRadius.width);
requiredBlurArea.Outset(aBlurRadius + aSpreadRadius);
rect = requiredBlurArea.Intersect(rect);
} else {
mHasDirtyRect = PR_FALSE;
@ -83,14 +83,13 @@ gfxAlphaBoxBlur::Init(const gfxRect& aRect,
if (aSkipRect) {
// If we get passed a skip rect, we can lower the amount of
// blurring we need to do. We convert it to nsIntRect to avoid
// blurring/spreading we need to do. We convert it to nsIntRect to avoid
// expensive int<->float conversions if we were to use gfxRect instead.
gfxRect skipRect = *aSkipRect;
skipRect.RoundIn();
skipRect.Inset(aBlurRadius + aSpreadRadius);
mSkipRect = gfxThebesUtils::GfxRectToIntRect(skipRect);
nsIntRect shadowIntRect = gfxThebesUtils::GfxRectToIntRect(rect);
mSkipRect.Deflate(aBlurRadius.width, aBlurRadius.height);
mSkipRect.IntersectRect(mSkipRect, shadowIntRect);
if (mSkipRect == shadowIntRect)
return nsnull;
@ -140,6 +139,7 @@ gfxAlphaBoxBlur::PremultiplyAlpha(gfxFloat alpha)
* @param aWidth The number of columns in the buffers.
* @param aRows The number of rows in the buffers.
* @param aSkipRect An area to skip blurring in.
* XXX shouldn't we pass stride in separately here?
*/
static void
BoxBlurHorizontal(unsigned char* aInput,
@ -152,7 +152,7 @@ BoxBlurHorizontal(unsigned char* aInput,
{
PRInt32 boxSize = aLeftLobe + aRightLobe + 1;
PRBool skipRectCoversWholeRow = 0 >= aSkipRect.x &&
aWidth - 1 <= aSkipRect.XMost();
aWidth <= aSkipRect.XMost();
for (PRInt32 y = 0; y < aRows; y++) {
// Check whether the skip rect intersects this row. If the skip
@ -206,6 +206,7 @@ BoxBlurHorizontal(unsigned char* aInput,
/**
* Identical to BoxBlurHorizontal, except it blurs top and bottom instead of
* left and right.
* XXX shouldn't we pass stride in separately here?
*/
static void
BoxBlurVertical(unsigned char* aInput,
@ -218,7 +219,7 @@ BoxBlurVertical(unsigned char* aInput,
{
PRInt32 boxSize = aTopLobe + aBottomLobe + 1;
PRBool skipRectCoversWholeColumn = 0 >= aSkipRect.y &&
aRows - 1 <= aSkipRect.YMost();
aRows <= aSkipRect.YMost();
for (PRInt32 x = 0; x < aWidth; x++) {
PRBool inSkipRectX = x >= aSkipRect.x &&
@ -304,6 +305,99 @@ static void ComputeLobes(PRInt32 aRadius, PRInt32 aLobes[3][2])
aLobes[2][1] = final;
}
static void
SpreadHorizontal(unsigned char* aInput,
unsigned char* aOutput,
PRInt32 aRadius,
PRInt32 aWidth,
PRInt32 aRows,
PRInt32 aStride,
const nsIntRect& aSkipRect)
{
if (aRadius == 0) {
memcpy(aOutput, aInput, aStride*aRows);
return;
}
PRBool skipRectCoversWholeRow = 0 >= aSkipRect.x &&
aWidth <= aSkipRect.XMost();
for (PRInt32 y = 0; y < aRows; y++) {
// Check whether the skip rect intersects this row. If the skip
// rect covers the whole surface in this row, we can avoid
// this row entirely (and any others along the skip rect).
PRBool inSkipRectY = y >= aSkipRect.y &&
y < aSkipRect.YMost();
if (inSkipRectY && skipRectCoversWholeRow) {
y = aSkipRect.YMost() - 1;
continue;
}
for (PRInt32 x = 0; x < aWidth; x++) {
// Check whether we are within the skip rect. If so, go
// to the next point outside the skip rect.
if (inSkipRectY && x >= aSkipRect.x &&
x < aSkipRect.XMost()) {
x = aSkipRect.XMost();
if (x >= aWidth)
break;
}
PRInt32 sMin = PR_MAX(x - aRadius, 0);
PRInt32 sMax = PR_MIN(x + aRadius, aWidth - 1);
PRInt32 v = 0;
for (PRInt32 s = sMin; s <= sMax; ++s) {
v = PR_MAX(v, aInput[aStride * y + s]);
}
aOutput[aStride * y + x] = v;
}
}
}
static void
SpreadVertical(unsigned char* aInput,
unsigned char* aOutput,
PRInt32 aRadius,
PRInt32 aWidth,
PRInt32 aRows,
PRInt32 aStride,
const nsIntRect& aSkipRect)
{
if (aRadius == 0) {
memcpy(aOutput, aInput, aStride*aRows);
return;
}
PRBool skipRectCoversWholeColumn = 0 >= aSkipRect.y &&
aRows <= aSkipRect.YMost();
for (PRInt32 x = 0; x < aWidth; x++) {
PRBool inSkipRectX = x >= aSkipRect.x &&
x < aSkipRect.XMost();
if (inSkipRectX && skipRectCoversWholeColumn) {
x = aSkipRect.XMost() - 1;
continue;
}
for (PRInt32 y = 0; y < aRows; y++) {
// Check whether we are within the skip rect. If so, go
// to the next point outside the skip rect.
if (inSkipRectX && y >= aSkipRect.y &&
y < aSkipRect.YMost()) {
y = aSkipRect.YMost();
if (y >= aRows)
break;
}
PRInt32 sMin = PR_MAX(y - aRadius, 0);
PRInt32 sMax = PR_MIN(y + aRadius, aRows - 1);
PRInt32 v = 0;
for (PRInt32 s = sMin; s <= sMax; ++s) {
v = PR_MAX(v, aInput[aStride * s + x]);
}
aOutput[aStride * y + x] = v;
}
}
}
void
gfxAlphaBoxBlur::Paint(gfxContext* aDestinationCtx, const gfxPoint& offset)
{
@ -312,8 +406,8 @@ gfxAlphaBoxBlur::Paint(gfxContext* aDestinationCtx, const gfxPoint& offset)
unsigned char* boxData = mImageSurface->Data();
// no need to do all this if not blurring
if (mBlurRadius.width != 0 || mBlurRadius.height != 0) {
// no need to do all this if not blurring or spreading
if (mBlurRadius != gfxIntSize(0,0) || mSpreadRadius != gfxIntSize(0,0)) {
nsTArray<unsigned char> tempAlphaDataBuf;
PRSize szB = mImageSurface->GetDataSize();
if (!tempAlphaDataBuf.SetLength(szB))
@ -323,11 +417,16 @@ gfxAlphaBoxBlur::Paint(gfxContext* aDestinationCtx, const gfxPoint& offset)
// .SetLength above doesn't initialise the new elements since
// they are unsigned chars and so have no default constructor.
// So we have to initialise them by hand.
// https://bugzilla.mozilla.org/show_bug.cgi?id=582668#c10
memset(tmpData, 0, szB);
PRInt32 stride = mImageSurface->Stride();
PRInt32 rows = mImageSurface->Height();
PRInt32 width = mImageSurface->Width();
if (mSpreadRadius.width > 0 || mSpreadRadius.height > 0) {
SpreadHorizontal(boxData, tmpData, mSpreadRadius.width, width, rows, stride, mSkipRect);
SpreadVertical(tmpData, boxData, mSpreadRadius.height, width, rows, stride, mSkipRect);
}
if (mBlurRadius.width > 0) {
PRInt32 lobes[3][2];
@ -335,6 +434,8 @@ gfxAlphaBoxBlur::Paint(gfxContext* aDestinationCtx, const gfxPoint& offset)
BoxBlurHorizontal(boxData, tmpData, lobes[0][0], lobes[0][1], stride, rows, mSkipRect);
BoxBlurHorizontal(tmpData, boxData, lobes[1][0], lobes[1][1], stride, rows, mSkipRect);
BoxBlurHorizontal(boxData, tmpData, lobes[2][0], lobes[2][1], stride, rows, mSkipRect);
} else {
memcpy(tmpData, boxData, stride*rows);
}
if (mBlurRadius.height > 0) {
@ -343,20 +444,22 @@ gfxAlphaBoxBlur::Paint(gfxContext* aDestinationCtx, const gfxPoint& offset)
BoxBlurVertical(tmpData, boxData, lobes[0][0], lobes[0][1], stride, rows, mSkipRect);
BoxBlurVertical(boxData, tmpData, lobes[1][0], lobes[1][1], stride, rows, mSkipRect);
BoxBlurVertical(tmpData, boxData, lobes[2][0], lobes[2][1], stride, rows, mSkipRect);
} else {
memcpy(boxData, tmpData, stride*rows);
}
}
// Avoid a semi-expensive clip operation if we can, otherwise
// clip to the dirty rect
if (mHasDirtyRect) {
aDestinationCtx->Save();
aDestinationCtx->NewPath();
aDestinationCtx->Rectangle(mDirtyRect);
aDestinationCtx->Clip();
aDestinationCtx->Mask(mImageSurface, offset);
aDestinationCtx->Restore();
aDestinationCtx->Save();
aDestinationCtx->NewPath();
aDestinationCtx->Rectangle(mDirtyRect);
aDestinationCtx->Clip();
aDestinationCtx->Mask(mImageSurface, offset);
aDestinationCtx->Restore();
} else {
aDestinationCtx->Mask(mImageSurface, offset);
aDestinationCtx->Mask(mImageSurface, offset);
}
}

Просмотреть файл

@ -46,10 +46,13 @@
/**
* Implementation of a box blur approximation of a Gaussian blur.
*
* Creates an 8-bit alpha channel context for callers to draw in, blurs the
* contents of that context and applies it as an alpha mask on a
* different existing context.
*
* Creates an 8-bit alpha channel context for callers to draw in,
* spreads the contents of that context, blurs the contents, and applies
* it as an alpha mask on a different existing context.
*
* A spread N makes each output pixel the maximum value of all source
* pixels within a square of side length 2N+1 centered on the output pixel.
*
* A temporary surface is created in the Init function. The caller then draws
* any desired content onto the context acquired through GetContext, and lastly
* calls Paint to apply the blurred content as an alpha mask.
@ -75,6 +78,7 @@ public:
* pass NULL here.
*/
gfxContext* Init(const gfxRect& aRect,
const gfxIntSize& aSpreadRadius,
const gfxIntSize& aBlurRadius,
const gfxRect* aDirtyRect,
const gfxRect* aSkipRect);
@ -95,8 +99,8 @@ public:
void PremultiplyAlpha(gfxFloat alpha);
/**
* Does the actual blurring and mask applying. Users of this object
* must have drawn whatever they want to be blurred onto the internal
* Does the actual blurring/spreading and mask applying. Users of this
* object must have drawn whatever they want to be blurred onto the internal
* gfxContext returned by GetContext before calling this.
*
* @param aDestinationCtx The graphics context on which to apply the
@ -111,6 +115,10 @@ public:
static gfxIntSize CalculateBlurRadius(const gfxPoint& aStandardDeviation);
protected:
/**
* The spread radius, in pixels.
*/
gfxIntSize mSpreadRadius;
/**
* The blur radius, in pixels.
*/

Просмотреть файл

@ -484,8 +484,11 @@ gfxGDIFont::GetHintedGlyphWidth(gfxContext *aCtx, PRUint16 aGID)
return width;
}
DCFromContext dc(aCtx);
AutoSelectFont fs(dc, GetHFONT());
int devWidth;
if (GetCharWidthI(DCFromContext(aCtx), aGID, 1, NULL, &devWidth)) {
if (GetCharWidthI(dc, aGID, 1, NULL, &devWidth)) {
// ensure width is positive, 16.16 fixed-point value
width = (devWidth & 0x7fff) << 16;
mGlyphWidths.Put(aGID, width);

Просмотреть файл

@ -98,9 +98,12 @@ gfxImageSurface::gfxImageSurface(const gfxIntSize& size, gfxImageFormat format)
// if we have a zero-sized surface, just leave mData nsnull
if (mSize.height * mStride > 0) {
mData = (unsigned char *) calloc(mSize.height, mStride);
// Use the fallible allocator here
mData = (unsigned char *) moz_malloc(mSize.height * mStride);
if (!mData)
return;
memset(mData, 0, mSize.height * mStride);
}
mOwnsData = PR_TRUE;

Просмотреть файл

@ -54,6 +54,7 @@ gfxQuartzNativeDrawing::gfxQuartzNativeDrawing(gfxContext* ctx,
const gfxRect& nativeRect)
: mContext(ctx), mNativeRect(nativeRect)
{
mNativeRect.RoundOut();
}
CGContextRef
@ -73,45 +74,50 @@ gfxQuartzNativeDrawing::BeginNativeDrawing()
if (surf->GetType() == gfxASurface::SurfaceTypeQuartz &&
(surf->GetContentType() == gfxASurface::CONTENT_COLOR ||
(surf->GetContentType() == gfxASurface::CONTENT_COLOR_ALPHA))) {
mQuartzSurface = static_cast<gfxQuartzSurface*>(static_cast<gfxASurface*>(surf.get()));
mQuartzSurface = static_cast<gfxQuartzSurface*>(surf.get());
mSurfaceContext = mContext;
// grab the CGContextRef
mCGContext = cairo_quartz_get_cg_context_with_clip(mSurfaceContext->GetCairo());
if (!mCGContext)
return nsnull;
gfxMatrix m = mContext->CurrentMatrix();
CGContextTranslateCTM(mCGContext, deviceOffset.x, deviceOffset.y);
// I -think- that this context will always have an identity
// transform (since we don't maintain a transform on it in
// cairo-land, and instead push/pop as needed)
gfxFloat x0 = m.x0;
gfxFloat y0 = m.y0;
// We round x0/y0 if we don't have a scale, because otherwise things get
// rendered badly
// XXX how should we be rounding x0/y0?
if (!m.HasNonTranslationOrFlip()) {
x0 = floor(x0 + 0.5);
y0 = floor(y0 + 0.5);
}
CGContextConcatCTM(mCGContext, CGAffineTransformMake(m.xx, m.yx,
m.xy, m.yy,
x0, y0));
// bug 382049 - need to explicity set the composite operation to sourceOver
CGContextSetCompositeOperation(mCGContext, kPrivateCGCompositeSourceOver);
} else {
// XXXkinetik we could create and use a temp surface here and draw
// it back to the gfxContext in EndNativeDrawing like the Windows
// version of this class
NS_WARNING("unhandled surface type");
return nsnull;
mQuartzSurface = new gfxQuartzSurface(mNativeRect.size,
gfxASurface::ImageFormatARGB32);
if (mQuartzSurface->CairoStatus())
return nsnull;
mSurfaceContext = new gfxContext(mQuartzSurface);
// grab the CGContextRef
mCGContext = cairo_quartz_get_cg_context_with_clip(mSurfaceContext->GetCairo());
CGContextTranslateCTM(mCGContext, -mNativeRect.X(), -mNativeRect.Y());
}
// grab the CGContextRef
mCGContext = cairo_quartz_get_cg_context_with_clip(mContext->GetCairo());
if (!mCGContext)
return nsnull;
gfxMatrix m = mContext->CurrentMatrix();
CGContextTranslateCTM(mCGContext, deviceOffset.x, deviceOffset.y);
// I -think- that this context will always have an identity
// transform (since we don't maintain a transform on it in
// cairo-land, and instead push/pop as needed)
gfxFloat x0 = m.x0;
gfxFloat y0 = m.y0;
// We round x0/y0 if we don't have a scale, because otherwise things get
// rendered badly
// XXX how should we be rounding x0/y0?
if (!m.HasNonTranslationOrFlip()) {
x0 = floor(x0 + 0.5);
y0 = floor(y0 + 0.5);
}
CGContextConcatCTM(mCGContext, CGAffineTransformMake(m.xx, m.yx,
m.xy, m.yy,
x0, y0));
// bug 382049 - need to explicity set the composite operation to sourceOver
CGContextSetCompositeOperation(mCGContext, kPrivateCGCompositeSourceOver);
return mCGContext;
}
@ -120,7 +126,13 @@ gfxQuartzNativeDrawing::EndNativeDrawing()
{
NS_ASSERTION(mQuartzSurface, "EndNativeDrawing called without BeginNativeDrawing");
cairo_quartz_finish_cg_context_with_clip(mContext->GetCairo());
cairo_quartz_finish_cg_context_with_clip(mSurfaceContext->GetCairo());
mQuartzSurface->MarkDirty();
mQuartzSurface = nsnull;
if (mSurfaceContext != mContext) {
gfxContextMatrixAutoSaveRestore save(mContext);
// Copy back to destination
mContext->Translate(mNativeRect.TopLeft());
mContext->DrawSurface(mQuartzSurface, mNativeRect.size);
}
}

Просмотреть файл

@ -74,8 +74,12 @@ private:
gfxQuartzNativeDrawing(const gfxQuartzNativeDrawing&);
const gfxQuartzNativeDrawing& operator=(const gfxQuartzNativeDrawing&);
// Final destination context
nsRefPtr<gfxContext> mContext;
gfxRect mNativeRect; // not yet used, will be needed for offscreen buffers
// context that draws to mQuartzSurface; can be different from mContext
// if mContext is not drawing to Quartz
nsRefPtr<gfxContext> mSurfaceContext;
gfxRect mNativeRect;
// saved state
nsRefPtr<gfxQuartzSurface> mQuartzSurface;

Просмотреть файл

@ -137,6 +137,10 @@ struct THEBES_API gfxRect {
Inset(sides[0], sides[1], sides[2], sides[3]);
}
void Inset(const gfxIntSize& size) {
Inset(size.height, size.width, size.height, size.width);
}
void Outset(gfxFloat k) {
pos.x -= k;
pos.y -= k;
@ -155,6 +159,10 @@ struct THEBES_API gfxRect {
Outset(sides[0], sides[1], sides[2], sides[3]);
}
void Outset(const gfxIntSize& size) {
Outset(size.height, size.width, size.height, size.width);
}
// Round the rectangle edges to integer coordinates, such that the rounded
// rectangle has the same set of pixel centers as the original rectangle.
// Edges at offset 0.5 round up.

Просмотреть файл

@ -50,7 +50,7 @@ public:
enum {
FLAG_TAKE_DC = (1 << 0),
FLAG_FOR_PRINTING = (1 << 1),
FLAG_IS_TRANSPARENT = (1 << 2),
FLAG_IS_TRANSPARENT = (1 << 2)
};
gfxWindowsSurface(HWND wnd, PRUint32 flags = 0);

Просмотреть файл

@ -77,13 +77,11 @@ MOZ_SYNC_BUILD_FILES = @MOZ_SYNC_BUILD_FILES@
MOZ_DEBUG = @MOZ_DEBUG@
MOZ_DEBUG_SYMBOLS = @MOZ_DEBUG_SYMBOLS@
MOZ_PROFILE_MODULES = @MOZ_PROFILE_MODULES@
MOZ_DEBUG_ENABLE_DEFS = @MOZ_DEBUG_ENABLE_DEFS@
MOZ_DEBUG_DISABLE_DEFS = @MOZ_DEBUG_DISABLE_DEFS@
MOZ_DEBUG_FLAGS = @MOZ_DEBUG_FLAGS@
MOZ_DEBUG_LDFLAGS=@MOZ_DEBUG_LDFLAGS@
MOZ_EXTENSIONS = @MOZ_EXTENSIONS@
MOZ_IMG_DECODERS= @MOZ_IMG_DECODERS@
MOZ_IMG_ENCODERS= @MOZ_IMG_ENCODERS@
MOZ_JSDEBUGGER = @MOZ_JSDEBUGGER@
MOZ_LEAKY = @MOZ_LEAKY@

Просмотреть файл

@ -891,6 +891,7 @@ wx/xrc/xmlres.h
X11/cursorfont.h
X11/extensions/Print.h
X11/extensions/shape.h
X11/extensions/scrnsaver.h
X11/extensions/XIElib.h
X11/extensions/XShm.h
X11/extensions/Xrender.h

Просмотреть файл

@ -49,7 +49,7 @@ skip script regress-335700.js # bug xxx - reftest hang, BigO
skip-if(!xulRuntime.shell) script regress-336409-1.js # no results reported.
skip-if(!xulRuntime.shell&&xulRuntime.XPCOMABI.match(/x86_64/)) script regress-336409-2.js # fails on 64 bit systems for some reason
skip-if(!xulRuntime.shell) script regress-336410-1.js # slow
skip-if(!xulRuntime.shell&&xulRuntime.XPCOMABI.match(/x86_64/)) script regress-336410-2.js # fails on 64 bit systems for some reason
skip-if(!xulRuntime.shell&&(xulRuntime.XPCOMABI.match(/x86_64/)||xulRuntime.OS=="WINNT")) script regress-336410-2.js # fails in browser on 64 bit systems or Windows.
script regress-338804-01.js
script regress-338804-02.js
script regress-338804-03.js

Просмотреть файл

@ -72,6 +72,10 @@ ifdef WINCE
WIN32_EXE_LDFLAGS += -ENTRY:mainWCRTStartup
LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/xre/
endif
ifeq ($(OS_TEST),x86_64)
# set stack to 2MB on x64 build. See bug 582910
WIN32_EXE_LDFLAGS += -STACK:2097152
endif
endif
include $(topsrcdir)/config/config.mk

Просмотреть файл

@ -1176,31 +1176,61 @@ nsCSSRendering::PaintBoxShadowOuter(nsPresContext* aPresContext,
const nsRect& aFrameArea,
const nsRect& aDirtyRect)
{
nsCSSShadowArray* shadows = aForFrame->GetEffectiveBoxShadows();
const nsStyleBorder* styleBorder = aForFrame->GetStyleBorder();
nsCSSShadowArray* shadows = styleBorder->mBoxShadow;
if (!shadows)
return;
const nsStyleBorder* styleBorder = aForFrame->GetStyleBorder();
PRIntn sidesToSkip = aForFrame->GetSkipSides();
// Get any border radius, since box-shadow must also have rounded corners if the frame does
nscoord twipsRadii[8];
PRBool hasBorderRadius = GetBorderRadiusTwips(styleBorder->mBorderRadius,
aFrameArea.width, twipsRadii);
nscoord twipsPerPixel = aPresContext->DevPixelsToAppUnits(1);
PRBool hasBorderRadius;
PRBool nativeTheme; // mutually exclusive with hasBorderRadius
gfxCornerSizes borderRadii;
ComputePixelRadii(twipsRadii, aFrameArea, sidesToSkip,
twipsPerPixel, &borderRadii);
gfxRect frameGfxRect = RectToGfxRect(aFrameArea, twipsPerPixel);
// Get any border radius, since box-shadow must also have rounded corners if the frame does
const nsStyleDisplay* styleDisplay = aForFrame->GetStyleDisplay();
nsITheme::Transparency transparency;
if (aForFrame->IsThemed(styleDisplay, &transparency)) {
// We don't respect border-radius for native-themed widgets
hasBorderRadius = PR_FALSE;
// For opaque (rectangular) theme widgets we can take the generic
// border-box path with border-radius disabled.
nativeTheme = transparency != nsITheme::eOpaque;
} else {
nativeTheme = PR_FALSE;
nscoord twipsRadii[8];
hasBorderRadius =
GetBorderRadiusTwips(styleBorder->mBorderRadius,
aFrameArea.width, twipsRadii);
if (hasBorderRadius) {
PRIntn sidesToSkip = aForFrame->GetSkipSides();
ComputePixelRadii(twipsRadii, aFrameArea, sidesToSkip, twipsPerPixel,
&borderRadii);
}
}
nsRect frameRect =
nativeTheme ? aForFrame->GetOverflowRectRelativeToSelf() + aFrameArea.TopLeft() : aFrameArea;
gfxRect frameGfxRect = RectToGfxRect(frameRect, twipsPerPixel);
frameGfxRect.Round();
// We don't show anything that intersects with the frame we're blurring on. So tell the
// blurrer not to do unnecessary work there.
gfxRect skipGfxRect = frameGfxRect;
if (hasBorderRadius) {
skipGfxRect.Inset(PR_MAX(borderRadii[C_TL].height, borderRadii[C_TR].height), 0,
PR_MAX(borderRadii[C_BL].height, borderRadii[C_BR].height), 0);
PRBool useSkipGfxRect = PR_TRUE;
if (nativeTheme) {
// Optimize non-leaf native-themed frames by skipping computing pixels
// in the padding-box. We assume the padding-box is going to be painted
// opaquely for non-leaf frames.
// XXX this may not be a safe assumption; we should make this go away
// by optimizing box-shadow drawing more for the cases where we don't have a skip-rect.
useSkipGfxRect = !aForFrame->IsLeaf();
nsRect paddingRect =
aForFrame->GetPaddingRect() - aForFrame->GetPosition() + aFrameArea.TopLeft();
skipGfxRect = RectToGfxRect(paddingRect, twipsPerPixel);
} else if (hasBorderRadius) {
skipGfxRect.Inset(
PR_MAX(borderRadii[C_TL].height, borderRadii[C_TR].height), 0,
PR_MAX(borderRadii[C_BL].height, borderRadii[C_BR].height), 0);
}
for (PRUint32 i = shadows->Length(); i > 0; --i) {
@ -1208,9 +1238,15 @@ nsCSSRendering::PaintBoxShadowOuter(nsPresContext* aPresContext,
if (shadowItem->mInset)
continue;
nsRect shadowRect = aFrameArea;
nsRect shadowRect = frameRect;
shadowRect.MoveBy(shadowItem->mXOffset, shadowItem->mYOffset);
shadowRect.Inflate(shadowItem->mSpread, shadowItem->mSpread);
nscoord pixelSpreadRadius;
if (nativeTheme) {
pixelSpreadRadius = shadowItem->mSpread;
} else {
shadowRect.Inflate(shadowItem->mSpread, shadowItem->mSpread);
pixelSpreadRadius = 0;
}
// shadowRect won't include the blur, so make an extra rect here that includes the blur
// for use in the even-odd rule below.
@ -1227,8 +1263,15 @@ nsCSSRendering::PaintBoxShadowOuter(nsPresContext* aPresContext,
nsRefPtr<gfxContext> shadowContext;
nsContextBoxBlur blurringArea;
shadowContext = blurringArea.Init(shadowRect, blurRadius, twipsPerPixel, renderContext,
aDirtyRect, &skipGfxRect);
// When getting the widget shape from the native theme, we're going
// to draw the widget into the shadow surface to create a mask.
// We need to ensure that there actually *is* a shadow surface
// and that we're not going to draw directly into renderContext.
shadowContext =
blurringArea.Init(shadowRect, pixelSpreadRadius,
blurRadius, twipsPerPixel, renderContext, aDirtyRect,
useSkipGfxRect ? &skipGfxRect : nsnull,
nativeTheme ? nsContextBoxBlur::FORCE_MASK : 0);
if (!shadowContext)
continue;
@ -1242,55 +1285,72 @@ nsCSSRendering::PaintBoxShadowOuter(nsPresContext* aPresContext,
renderContext->Save();
renderContext->SetColor(gfxRGBA(shadowColor));
// Clip out the area of the actual frame so the shadow is not shown within
// the frame
renderContext->NewPath();
renderContext->Rectangle(shadowGfxRectPlusBlur);
if (hasBorderRadius)
renderContext->RoundedRectangle(frameGfxRect, borderRadii);
else
renderContext->Rectangle(frameGfxRect);
renderContext->SetFillRule(gfxContext::FILL_RULE_EVEN_ODD);
renderContext->Clip();
// Draw the shape of the frame so it can be blurred. Recall how nsContextBoxBlur
// doesn't make any temporary surfaces if blur is 0 and it just returns the original
// surface? If we have no blur, we're painting this fill on the actual content surface
// (renderContext == shadowContext) which is why we set up the color and clip
// before doing this.
shadowContext->NewPath();
if (hasBorderRadius) {
gfxCornerSizes clipRectRadii;
gfxFloat spreadDistance = -shadowItem->mSpread / twipsPerPixel;
gfxFloat borderSizes[4] = {0, 0, 0, 0};
if (nativeTheme) {
// We don't clip the border-box from the shadow, nor any other box.
// We assume that the native theme is going to paint over the shadow.
// We only give the spread radius to corners with a radius on them, otherwise we'll
// give a rounded shadow corner to a frame corner with 0 border radius, should
// the author use non-uniform border radii sizes (-moz-border-radius-topleft etc)
// (bug 514670)
if (borderRadii[C_TL].width > 0 || borderRadii[C_BL].width > 0) {
borderSizes[NS_SIDE_LEFT] = spreadDistance;
}
if (borderRadii[C_TL].height > 0 || borderRadii[C_TR].height > 0) {
borderSizes[NS_SIDE_TOP] = spreadDistance;
}
if (borderRadii[C_TR].width > 0 || borderRadii[C_BR].width > 0) {
borderSizes[NS_SIDE_RIGHT] = spreadDistance;
}
if (borderRadii[C_BL].height > 0 || borderRadii[C_BR].height > 0) {
borderSizes[NS_SIDE_BOTTOM] = spreadDistance;
}
nsCSSBorderRenderer::ComputeInnerRadii(borderRadii, borderSizes,
&clipRectRadii);
shadowContext->RoundedRectangle(shadowGfxRect, clipRectRadii);
// Draw the widget shape
gfxContextMatrixAutoSaveRestore save(shadowContext);
nsIDeviceContext* devCtx = aPresContext->DeviceContext();
nsCOMPtr<nsIRenderingContext> wrapperCtx;
devCtx->CreateRenderingContextInstance(*getter_AddRefs(wrapperCtx));
wrapperCtx->Init(devCtx, shadowContext);
wrapperCtx->Translate(shadowItem->mXOffset, shadowItem->mYOffset);
aPresContext->GetTheme()->DrawWidgetBackground(wrapperCtx, aForFrame,
styleDisplay->mAppearance, aFrameArea, frameRect);
} else {
shadowContext->Rectangle(shadowGfxRect);
// Clip out the area of the actual frame so the shadow is not shown within
// the frame
renderContext->NewPath();
renderContext->Rectangle(shadowGfxRectPlusBlur);
if (hasBorderRadius) {
renderContext->RoundedRectangle(frameGfxRect, borderRadii);
} else {
renderContext->Rectangle(frameGfxRect);
}
renderContext->SetFillRule(gfxContext::FILL_RULE_EVEN_ODD);
renderContext->Clip();
shadowContext->NewPath();
if (hasBorderRadius) {
gfxCornerSizes clipRectRadii;
gfxFloat spreadDistance = -shadowItem->mSpread / twipsPerPixel;
gfxFloat borderSizes[4] = { 0, 0, 0, 0 };
// We only give the spread radius to corners with a radius on them, otherwise we'll
// give a rounded shadow corner to a frame corner with 0 border radius, should
// the author use non-uniform border radii sizes (-moz-border-radius-topleft etc)
// (bug 514670)
if (borderRadii[C_TL].width > 0 || borderRadii[C_BL].width > 0) {
borderSizes[NS_SIDE_LEFT] = spreadDistance;
}
if (borderRadii[C_TL].height > 0 || borderRadii[C_TR].height > 0) {
borderSizes[NS_SIDE_TOP] = spreadDistance;
}
if (borderRadii[C_TR].width > 0 || borderRadii[C_BR].width > 0) {
borderSizes[NS_SIDE_RIGHT] = spreadDistance;
}
if (borderRadii[C_BL].height > 0 || borderRadii[C_BR].height > 0) {
borderSizes[NS_SIDE_BOTTOM] = spreadDistance;
}
nsCSSBorderRenderer::ComputeInnerRadii(borderRadii, borderSizes,
&clipRectRadii);
shadowContext->RoundedRectangle(shadowGfxRect, clipRectRadii);
} else {
shadowContext->Rectangle(shadowGfxRect);
}
shadowContext->Fill();
}
shadowContext->Fill();
blurringArea.DoPaint();
renderContext->Restore();
@ -1304,10 +1364,18 @@ nsCSSRendering::PaintBoxShadowInner(nsPresContext* aPresContext,
const nsRect& aFrameArea,
const nsRect& aDirtyRect)
{
nsCSSShadowArray* shadows = aForFrame->GetEffectiveBoxShadows();
const nsStyleBorder* styleBorder = aForFrame->GetStyleBorder();
nsCSSShadowArray* shadows = styleBorder->mBoxShadow;
if (!shadows)
return;
const nsStyleBorder* styleBorder = aForFrame->GetStyleBorder();
if (aForFrame->IsThemed() && aForFrame->GetContent() &&
!nsContentUtils::IsChromeDoc(aForFrame->GetContent()->GetCurrentDoc())) {
// There's no way of getting hold of a shape corresponding to a
// "padding-box" for native-themed widgets, so just don't draw
// inner box-shadows for them. But we allow chrome to paint inner
// box shadows since chrome can be aware of the platform theme.
return;
}
// Get any border radius, since box-shadow must also have rounded corners if the frame does
nscoord twipsRadii[8];
@ -1398,7 +1466,7 @@ nsCSSRendering::PaintBoxShadowInner(nsPresContext* aPresContext,
nsRefPtr<gfxContext> shadowContext;
nsContextBoxBlur blurringArea;
shadowContext = blurringArea.Init(shadowPaintRect, blurRadius, twipsPerPixel, renderContext,
shadowContext = blurringArea.Init(shadowPaintRect, 0, blurRadius, twipsPerPixel, renderContext,
aDirtyRect, &skipGfxRect);
if (!shadowContext)
continue;
@ -3827,16 +3895,19 @@ ImageRenderer::Draw(nsPresContext* aPresContext,
}
#define MAX_BLUR_RADIUS 300
#define MAX_SPREAD_RADIUS 50
// -----
// nsContextBoxBlur
// -----
gfxContext*
nsContextBoxBlur::Init(const nsRect& aRect, nscoord aBlurRadius,
nsContextBoxBlur::Init(const nsRect& aRect, nscoord aSpreadRadius,
nscoord aBlurRadius,
PRInt32 aAppUnitsPerDevPixel,
gfxContext* aDestinationCtx,
const nsRect& aDirtyRect,
const gfxRect* aSkipRect)
const gfxRect* aSkipRect,
PRUint32 aFlags)
{
if (aRect.IsEmpty()) {
mContext = nsnull;
@ -3845,10 +3916,12 @@ nsContextBoxBlur::Init(const nsRect& aRect, nscoord aBlurRadius,
PRInt32 blurRadius = static_cast<PRInt32>(aBlurRadius / aAppUnitsPerDevPixel);
blurRadius = PR_MIN(blurRadius, MAX_BLUR_RADIUS);
PRInt32 spreadRadius = static_cast<PRInt32>(aSpreadRadius / aAppUnitsPerDevPixel);
spreadRadius = PR_MIN(spreadRadius, MAX_BLUR_RADIUS);
mDestinationCtx = aDestinationCtx;
// If not blurring, draw directly onto the destination device
if (blurRadius <= 0) {
if (blurRadius <= 0 && spreadRadius <= 0 && !(aFlags & FORCE_MASK)) {
mContext = aDestinationCtx;
return mContext;
}
@ -3860,7 +3933,8 @@ nsContextBoxBlur::Init(const nsRect& aRect, nscoord aBlurRadius,
dirtyRect.RoundOut();
// Create the temporary surface for blurring
mContext = blur.Init(rect, gfxIntSize(blurRadius, blurRadius),
mContext = blur.Init(rect, gfxIntSize(spreadRadius, spreadRadius),
gfxIntSize(blurRadius, blurRadius),
&dirtyRect, aSkipRect);
return mContext;
}

Просмотреть файл

@ -391,6 +391,9 @@ protected:
*/
class nsContextBoxBlur {
public:
enum {
FORCE_MASK = 0x01
};
/**
* Prepares a gfxContext to draw on. Do not call this twice; if you want
* to get the gfxContext again use GetContext().
@ -421,6 +424,10 @@ public:
*
* @param aSkipRect An area in device pixels (NOT app units!) to avoid
* blurring over, to prevent unnecessary work.
*
* @param aFlags FORCE_MASK to ensure that the content drawn to the
* returned gfxContext is used as a mask, and not
* drawn directly to aDestinationCtx.
*
* @return A blank 8-bit alpha-channel-only graphics context to
* draw on, or null on error. Must not be freed. The
@ -435,10 +442,19 @@ public:
* should prepare the destination context as if you were going to draw
* directly on it instead of any temporary surface created in this class.
*/
gfxContext* Init(const nsRect& aRect, nscoord aBlurRadius,
gfxContext* Init(const nsRect& aRect, nscoord aSpreadRadius,
nscoord aBlurRadius,
PRInt32 aAppUnitsPerDevPixel, gfxContext* aDestinationCtx,
const nsRect& aDirtyRect, const gfxRect* aSkipRect);
const nsRect& aDirtyRect, const gfxRect* aSkipRect,
PRUint32 aFlags = 0);
/**
* Does the actual blurring/spreading. Users of this object *must*
* have called Init() first, then have drawn whatever they want to be
* blurred onto the internal gfxContext before calling this.
*/
void DoEffects();
/**
* Does the actual blurring and mask applying. Users of this object *must*
* have called Init() first, then have drawn whatever they want to be

Просмотреть файл

@ -626,8 +626,9 @@ RegisterThemeWidgetGeometry(nsIFrame* aFrame)
borderBox.ToNearestPixels(presContext->AppUnitsPerDevPixel()));
}
nsDisplayBackground::nsDisplayBackground(nsIFrame* aFrame)
: nsDisplayItem(aFrame)
nsDisplayBackground::nsDisplayBackground(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame)
: nsDisplayItem(aBuilder, aFrame)
{
MOZ_COUNT_CTOR(nsDisplayBackground);
const nsStyleDisplay* disp = mFrame->GetStyleDisplay();
@ -807,7 +808,7 @@ nsDisplayBackground::IsFixedAndCoveringViewport(nsDisplayListBuilder* aBuilder)
void
nsDisplayBackground::Paint(nsDisplayListBuilder* aBuilder,
nsIRenderingContext* aCtx) {
nsPoint offset = aBuilder->ToReferenceFrame(mFrame);
nsPoint offset = ToReferenceFrame();
PRUint32 flags = aBuilder->GetBackgroundPaintFlags();
nsDisplayItem* nextItem = GetAbove();
if (nextItem && nextItem->GetUnderlyingFrame() == mFrame &&
@ -822,22 +823,28 @@ nsDisplayBackground::Paint(nsDisplayListBuilder* aBuilder,
nsRect
nsDisplayBackground::GetBounds(nsDisplayListBuilder* aBuilder) {
if (mIsThemed)
return mFrame->GetOverflowRect() + aBuilder->ToReferenceFrame(mFrame);
if (mIsThemed) {
nsRect r(nsPoint(0,0), mFrame->GetSize());
nsPresContext* presContext = mFrame->PresContext();
presContext->GetTheme()->
GetWidgetOverflow(presContext->DeviceContext(), mFrame,
mFrame->GetStyleDisplay()->mAppearance, &r);
return r + ToReferenceFrame();
}
return nsRect(aBuilder->ToReferenceFrame(mFrame), mFrame->GetSize());
return nsRect(ToReferenceFrame(), mFrame->GetSize());
}
nsRect
nsDisplayOutline::GetBounds(nsDisplayListBuilder* aBuilder) {
return mFrame->GetOverflowRect() + aBuilder->ToReferenceFrame(mFrame);
return mFrame->GetOverflowRect() + ToReferenceFrame();
}
void
nsDisplayOutline::Paint(nsDisplayListBuilder* aBuilder,
nsIRenderingContext* aCtx) {
// TODO join outlines together
nsPoint offset = aBuilder->ToReferenceFrame(mFrame);
nsPoint offset = ToReferenceFrame();
nsCSSRendering::PaintOutline(mFrame->PresContext(), *aCtx, mFrame,
mVisibleRect,
nsRect(offset, mFrame->GetSize()),
@ -851,7 +858,7 @@ nsDisplayOutline::ComputeVisibility(nsDisplayListBuilder* aBuilder,
return PR_FALSE;
const nsStyleOutline* outline = mFrame->GetStyleOutline();
nsRect borderBox(aBuilder->ToReferenceFrame(mFrame), mFrame->GetSize());
nsRect borderBox(ToReferenceFrame(), mFrame->GetSize());
if (borderBox.Contains(aVisibleRegion->GetBounds()) &&
!nsLayoutUtils::HasNonZeroCorner(outline->mOutlineRadius)) {
if (outline->mOutlineOffset >= 0) {
@ -869,7 +876,7 @@ nsDisplayCaret::Paint(nsDisplayListBuilder* aBuilder,
nsIRenderingContext* aCtx) {
// Note: Because we exist, we know that the caret is visible, so we don't
// need to check for the caret's visibility.
mCaret->PaintCaret(aBuilder, aCtx, mFrame, aBuilder->ToReferenceFrame(mFrame));
mCaret->PaintCaret(aBuilder, aCtx, mFrame, ToReferenceFrame());
}
PRBool
@ -879,7 +886,7 @@ nsDisplayBorder::ComputeVisibility(nsDisplayListBuilder* aBuilder,
return PR_FALSE;
nsRect paddingRect = mFrame->GetPaddingRect() - mFrame->GetPosition() +
aBuilder->ToReferenceFrame(mFrame);
ToReferenceFrame();
const nsStyleBorder *styleBorder;
if (paddingRect.Contains(aVisibleRegion->GetBounds()) &&
!(styleBorder = mFrame->GetStyleBorder())->IsBorderImageLoaded() &&
@ -899,7 +906,7 @@ nsDisplayBorder::ComputeVisibility(nsDisplayListBuilder* aBuilder,
void
nsDisplayBorder::Paint(nsDisplayListBuilder* aBuilder,
nsIRenderingContext* aCtx) {
nsPoint offset = aBuilder->ToReferenceFrame(mFrame);
nsPoint offset = ToReferenceFrame();
nsCSSRendering::PaintBorder(mFrame->PresContext(), *aCtx, mFrame,
mVisibleRect,
nsRect(offset, mFrame->GetSize()),
@ -941,7 +948,7 @@ ComputeDisjointRectangles(const nsRegion& aRegion,
void
nsDisplayBoxShadowOuter::Paint(nsDisplayListBuilder* aBuilder,
nsIRenderingContext* aCtx) {
nsPoint offset = aBuilder->ToReferenceFrame(mFrame);
nsPoint offset = ToReferenceFrame();
nsRect borderRect = nsRect(offset, mFrame->GetSize());
nsPresContext* presContext = mFrame->PresContext();
nsAutoTArray<nsRect,10> rects;
@ -958,7 +965,7 @@ nsDisplayBoxShadowOuter::Paint(nsDisplayListBuilder* aBuilder,
nsRect
nsDisplayBoxShadowOuter::GetBounds(nsDisplayListBuilder* aBuilder) {
return mFrame->GetOverflowRect() + aBuilder->ToReferenceFrame(mFrame);
return mFrame->GetOverflowRect() + ToReferenceFrame();
}
PRBool
@ -970,7 +977,7 @@ nsDisplayBoxShadowOuter::ComputeVisibility(nsDisplayListBuilder* aBuilder,
// Store the actual visible region
mVisibleRegion.And(*aVisibleRegion, mVisibleRect);
nsPoint origin = aBuilder->ToReferenceFrame(mFrame);
nsPoint origin = ToReferenceFrame();
nsRect visibleBounds = aVisibleRegion->GetBounds();
nsRect frameRect(origin, mFrame->GetSize());
if (!frameRect.Contains(visibleBounds))
@ -992,7 +999,7 @@ nsDisplayBoxShadowOuter::ComputeVisibility(nsDisplayListBuilder* aBuilder,
void
nsDisplayBoxShadowInner::Paint(nsDisplayListBuilder* aBuilder,
nsIRenderingContext* aCtx) {
nsPoint offset = aBuilder->ToReferenceFrame(mFrame);
nsPoint offset = ToReferenceFrame();
nsRect borderRect = nsRect(offset, mFrame->GetSize());
nsPresContext* presContext = mFrame->PresContext();
nsAutoTArray<nsRect,10> rects;
@ -1018,13 +1025,15 @@ nsDisplayBoxShadowInner::ComputeVisibility(nsDisplayListBuilder* aBuilder,
return PR_TRUE;
}
nsDisplayWrapList::nsDisplayWrapList(nsIFrame* aFrame, nsDisplayList* aList)
: nsDisplayItem(aFrame) {
nsDisplayWrapList::nsDisplayWrapList(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame, nsDisplayList* aList)
: nsDisplayItem(aBuilder, aFrame) {
mList.AppendToTop(aList);
}
nsDisplayWrapList::nsDisplayWrapList(nsIFrame* aFrame, nsDisplayItem* aItem)
: nsDisplayItem(aFrame) {
nsDisplayWrapList::nsDisplayWrapList(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame, nsDisplayItem* aItem)
: nsDisplayItem(aBuilder, aFrame) {
mList.AppendToTop(aItem);
}
@ -1169,8 +1178,9 @@ nsresult nsDisplayWrapper::WrapListsInPlace(nsDisplayListBuilder* aBuilder,
return WrapEachDisplayItem(aBuilder, aLists.Outlines(), this);
}
nsDisplayOpacity::nsDisplayOpacity(nsIFrame* aFrame, nsDisplayList* aList)
: nsDisplayWrapList(aFrame, aList) {
nsDisplayOpacity::nsDisplayOpacity(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame, nsDisplayList* aList)
: nsDisplayWrapList(aBuilder, aFrame, aList) {
MOZ_COUNT_CTOR(nsDisplayOpacity);
}
@ -1236,8 +1246,9 @@ PRBool nsDisplayOpacity::TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem*
return PR_TRUE;
}
nsDisplayOwnLayer::nsDisplayOwnLayer(nsIFrame* aFrame, nsDisplayList* aList)
: nsDisplayWrapList(aFrame, aList) {
nsDisplayOwnLayer::nsDisplayOwnLayer(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame, nsDisplayList* aList)
: nsDisplayWrapList(aBuilder, aFrame, aList) {
MOZ_COUNT_CTOR(nsDisplayOwnLayer);
}
@ -1256,16 +1267,18 @@ nsDisplayOwnLayer::BuildLayer(nsDisplayListBuilder* aBuilder,
return layer.forget();
}
nsDisplayClip::nsDisplayClip(nsIFrame* aFrame, nsIFrame* aClippingFrame,
nsDisplayItem* aItem, const nsRect& aRect)
: nsDisplayWrapList(aFrame, aItem),
nsDisplayClip::nsDisplayClip(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame, nsIFrame* aClippingFrame,
nsDisplayItem* aItem, const nsRect& aRect)
: nsDisplayWrapList(aBuilder, aFrame, aItem),
mClippingFrame(aClippingFrame), mClip(aRect) {
MOZ_COUNT_CTOR(nsDisplayClip);
}
nsDisplayClip::nsDisplayClip(nsIFrame* aFrame, nsIFrame* aClippingFrame,
nsDisplayList* aList, const nsRect& aRect)
: nsDisplayWrapList(aFrame, aList),
nsDisplayClip::nsDisplayClip(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame, nsIFrame* aClippingFrame,
nsDisplayList* aList, const nsRect& aRect)
: nsDisplayWrapList(aBuilder, aFrame, aList),
mClippingFrame(aClippingFrame), mClip(aRect) {
MOZ_COUNT_CTOR(nsDisplayClip);
}
@ -1317,12 +1330,14 @@ PRBool nsDisplayClip::TryMerge(nsDisplayListBuilder* aBuilder,
nsDisplayWrapList* nsDisplayClip::WrapWithClone(nsDisplayListBuilder* aBuilder,
nsDisplayItem* aItem) {
return new (aBuilder)
nsDisplayClip(aItem->GetUnderlyingFrame(), mClippingFrame, aItem, mClip);
nsDisplayClip(aBuilder, aItem->GetUnderlyingFrame(), mClippingFrame, aItem, mClip);
}
nsDisplayZoom::nsDisplayZoom(nsIFrame* aFrame, nsDisplayList* aList,
nsDisplayZoom::nsDisplayZoom(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame, nsDisplayList* aList,
PRInt32 aAPD, PRInt32 aParentAPD)
: nsDisplayOwnLayer(aFrame, aList), mAPD(aAPD), mParentAPD(aParentAPD) {
: nsDisplayOwnLayer(aBuilder, aFrame, aList), mAPD(aAPD),
mParentAPD(aParentAPD) {
MOZ_COUNT_CTOR(nsDisplayZoom);
}
@ -1532,7 +1547,7 @@ already_AddRefed<Layer> nsDisplayTransform::BuildLayer(nsDisplayListBuilder *aBu
LayerManager *aManager)
{
gfxMatrix newTransformMatrix =
GetResultingTransformMatrix(mFrame, aBuilder->ToReferenceFrame(mFrame),
GetResultingTransformMatrix(mFrame, ToReferenceFrame(),
mFrame->PresContext()->AppUnitsPerDevPixel(),
nsnull);
if (newTransformMatrix.IsSingular())
@ -1568,7 +1583,7 @@ PRBool nsDisplayTransform::ComputeVisibility(nsDisplayListBuilder *aBuilder,
* untransform the visible rect, since we want everything that's painting to
* think that it's painting in its original rectangular coordinate space. */
nsRegion untransformedVisible =
UntransformRect(mVisibleRect, mFrame, aBuilder->ToReferenceFrame(mFrame));
UntransformRect(mVisibleRect, mFrame, ToReferenceFrame());
mStoredList.ComputeVisibility(aBuilder, &untransformedVisible);
return PR_TRUE;
@ -1593,7 +1608,7 @@ void nsDisplayTransform::HitTest(nsDisplayListBuilder *aBuilder,
*/
float factor = nsPresContext::AppUnitsPerCSSPixel();
gfxMatrix matrix =
GetResultingTransformMatrix(mFrame, aBuilder->ToReferenceFrame(mFrame),
GetResultingTransformMatrix(mFrame, ToReferenceFrame(),
factor, nsnull);
if (matrix.IsSingular())
return;
@ -1651,7 +1666,7 @@ void nsDisplayTransform::HitTest(nsDisplayListBuilder *aBuilder,
*/
nsRect nsDisplayTransform::GetBounds(nsDisplayListBuilder *aBuilder)
{
return mFrame->GetOverflowRect() + aBuilder->ToReferenceFrame(mFrame);
return mFrame->GetOverflowRect() + ToReferenceFrame();
}
/* The transform is opaque iff the transform consists solely of scales and
@ -1779,8 +1794,9 @@ nsRect nsDisplayTransform::UntransformRect(const nsRect &aUntransformedBounds,
}
#ifdef MOZ_SVG
nsDisplaySVGEffects::nsDisplaySVGEffects(nsIFrame* aFrame, nsDisplayList* aList)
: nsDisplayWrapList(aFrame, aList), mEffectsFrame(aFrame),
nsDisplaySVGEffects::nsDisplaySVGEffects(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame, nsDisplayList* aList)
: nsDisplayWrapList(aBuilder, aFrame, aList), mEffectsFrame(aFrame),
mBounds(aFrame->GetOverflowRectRelativeToSelf())
{
MOZ_COUNT_CTOR(nsDisplaySVGEffects);

Просмотреть файл

@ -436,7 +436,12 @@ public:
// This is never instantiated directly (it has pure virtual methods), so no
// need to count constructors and destructors.
nsDisplayItem(nsIFrame* aFrame) : mFrame(aFrame) {}
nsDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) :
mFrame(aFrame) {
if (aFrame) {
mToReferenceFrame = aBuilder->ToReferenceFrame(aFrame);
}
}
virtual ~nsDisplayItem() {}
void* operator new(size_t aSize,
@ -496,8 +501,7 @@ public:
* contains the area drawn by this display item
*/
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder) {
nsIFrame* f = GetUnderlyingFrame();
return nsRect(aBuilder->ToReferenceFrame(f), f->GetSize());
return nsRect(ToReferenceFrame(), GetUnderlyingFrame()->GetSize());
}
/**
* @return PR_TRUE if the item is definitely opaque --- i.e., paints
@ -635,6 +639,14 @@ public:
PRBool RecomputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion);
/**
* Returns the result of aBuilder->ToReferenceFrame(GetUnderlyingFrame())
*/
const nsPoint& ToReferenceFrame() {
NS_ASSERTION(mFrame, "No frame?");
return mToReferenceFrame;
}
protected:
friend class nsDisplayList;
@ -643,6 +655,8 @@ protected:
}
nsIFrame* mFrame;
// Result of ToReferenceFrame(mFrame), if mFrame is non-null
nsPoint mToReferenceFrame;
// This is the rectangle that needs to be painted.
// nsDisplayList::ComputeVisibility sets this to the visible region
// of the item by intersecting the current visible region with the bounds
@ -1054,8 +1068,9 @@ public:
typedef void (* PaintCallback)(nsIFrame* aFrame, nsIRenderingContext* aCtx,
const nsRect& aDirtyRect, nsPoint aFramePt);
nsDisplayGeneric(nsIFrame* aFrame, PaintCallback aPaint, const char* aName, Type aType)
: nsDisplayItem(aFrame), mPaint(aPaint)
nsDisplayGeneric(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
PaintCallback aPaint, const char* aName, Type aType)
: nsDisplayItem(aBuilder, aFrame), mPaint(aPaint)
#ifdef DEBUG
, mName(aName)
#endif
@ -1070,7 +1085,7 @@ public:
#endif
virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx) {
mPaint(mFrame, aCtx, mVisibleRect, aBuilder->ToReferenceFrame(mFrame));
mPaint(mFrame, aCtx, mVisibleRect, ToReferenceFrame());
}
NS_DISPLAY_DECL_NAME(mName, mType)
protected:
@ -1096,9 +1111,10 @@ protected:
*/
class nsDisplayReflowCount : public nsDisplayItem {
public:
nsDisplayReflowCount(nsIFrame* aFrame, const char* aFrameName,
nsDisplayReflowCount(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
const char* aFrameName,
PRUint32 aColor = 0)
: nsDisplayItem(aFrame),
: nsDisplayItem(aBuilder, aFrame),
mFrameName(aFrameName),
mColor(aColor)
{
@ -1111,7 +1127,7 @@ public:
#endif
virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx) {
nsPoint pt = aBuilder->ToReferenceFrame(mFrame);
nsPoint pt = ToReferenceFrame();
nsIRenderingContext::AutoPushTranslation translate(aCtx, pt.x, pt.y);
mFrame->PresContext()->PresShell()->PaintCount(mFrameName, aCtx,
mFrame->PresContext(),
@ -1128,8 +1144,8 @@ protected:
if (!aBuilder->IsBackgroundOnly() && !aBuilder->IsForEventDelivery() && \
PresContext()->PresShell()->IsPaintingFrameCounts()) { \
nsresult _rv = \
aLists.Outlines()->AppendNewToTop(new (aBuilder) \
nsDisplayReflowCount(this, _name)); \
aLists.Outlines()->AppendNewToTop( \
new (aBuilder) nsDisplayReflowCount(aBuilder, this, _name)); \
NS_ENSURE_SUCCESS(_rv, _rv); \
} \
PR_END_MACRO
@ -1139,9 +1155,8 @@ protected:
if (!aBuilder->IsBackgroundOnly() && !aBuilder->IsForEventDelivery() && \
PresContext()->PresShell()->IsPaintingFrameCounts()) { \
nsresult _rv = \
aLists.Outlines()->AppendNewToTop(new (aBuilder) \
nsDisplayReflowCount(this, _name, \
_color)); \
aLists.Outlines()->AppendNewToTop( \
new (aBuilder) nsDisplayReflowCount(aBuilder, this, _name, _color)); \
NS_ENSURE_SUCCESS(_rv, _rv); \
} \
PR_END_MACRO
@ -1167,8 +1182,9 @@ protected:
class nsDisplayCaret : public nsDisplayItem {
public:
nsDisplayCaret(nsIFrame* aCaretFrame, nsCaret *aCaret)
: nsDisplayItem(aCaretFrame), mCaret(aCaret) {
nsDisplayCaret(nsDisplayListBuilder* aBuilder, nsIFrame* aCaretFrame,
nsCaret *aCaret)
: nsDisplayItem(aBuilder, aCaretFrame), mCaret(aCaret) {
MOZ_COUNT_CTOR(nsDisplayCaret);
}
#ifdef NS_BUILD_REFCNT_LOGGING
@ -1179,7 +1195,7 @@ public:
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder) {
// The caret returns a rect in the coordinates of mFrame.
return mCaret->GetCaretRect() + aBuilder->ToReferenceFrame(mFrame);
return mCaret->GetCaretRect() + ToReferenceFrame();
}
virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx);
NS_DISPLAY_DECL_NAME("Caret", TYPE_CARET)
@ -1192,7 +1208,8 @@ protected:
*/
class nsDisplayBorder : public nsDisplayItem {
public:
nsDisplayBorder(nsIFrame* aFrame) : nsDisplayItem(aFrame) {
nsDisplayBorder(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) :
nsDisplayItem(aBuilder, aFrame) {
MOZ_COUNT_CTOR(nsDisplayBorder);
}
#ifdef NS_BUILD_REFCNT_LOGGING
@ -1220,8 +1237,9 @@ public:
*/
class nsDisplaySolidColor : public nsDisplayItem {
public:
nsDisplaySolidColor(nsIFrame* aFrame, const nsRect& aBounds, nscolor aColor)
: nsDisplayItem(aFrame), mBounds(aBounds), mColor(aColor) {
nsDisplaySolidColor(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
const nsRect& aBounds, nscolor aColor)
: nsDisplayItem(aBuilder, aFrame), mBounds(aBounds), mColor(aColor) {
MOZ_COUNT_CTOR(nsDisplaySolidColor);
}
#ifdef NS_BUILD_REFCNT_LOGGING
@ -1256,7 +1274,7 @@ private:
*/
class nsDisplayBackground : public nsDisplayItem {
public:
nsDisplayBackground(nsIFrame* aFrame);
nsDisplayBackground(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame);
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplayBackground() {
MOZ_COUNT_DTOR(nsDisplayBackground);
@ -1289,7 +1307,8 @@ protected:
*/
class nsDisplayBoxShadowOuter : public nsDisplayItem {
public:
nsDisplayBoxShadowOuter(nsIFrame* aFrame) : nsDisplayItem(aFrame) {
nsDisplayBoxShadowOuter(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
: nsDisplayItem(aBuilder, aFrame) {
MOZ_COUNT_CTOR(nsDisplayBoxShadowOuter);
}
#ifdef NS_BUILD_REFCNT_LOGGING
@ -1313,7 +1332,8 @@ private:
*/
class nsDisplayBoxShadowInner : public nsDisplayItem {
public:
nsDisplayBoxShadowInner(nsIFrame* aFrame) : nsDisplayItem(aFrame) {
nsDisplayBoxShadowInner(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
: nsDisplayItem(aBuilder, aFrame) {
MOZ_COUNT_CTOR(nsDisplayBoxShadowInner);
}
#ifdef NS_BUILD_REFCNT_LOGGING
@ -1336,7 +1356,8 @@ private:
*/
class nsDisplayOutline : public nsDisplayItem {
public:
nsDisplayOutline(nsIFrame* aFrame) : nsDisplayItem(aFrame) {
nsDisplayOutline(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) :
nsDisplayItem(aBuilder, aFrame) {
MOZ_COUNT_CTOR(nsDisplayOutline);
}
#ifdef NS_BUILD_REFCNT_LOGGING
@ -1357,7 +1378,8 @@ public:
*/
class nsDisplayEventReceiver : public nsDisplayItem {
public:
nsDisplayEventReceiver(nsIFrame* aFrame) : nsDisplayItem(aFrame) {
nsDisplayEventReceiver(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
: nsDisplayItem(aBuilder, aFrame) {
MOZ_COUNT_CTOR(nsDisplayEventReceiver);
}
#ifdef NS_BUILD_REFCNT_LOGGING
@ -1396,8 +1418,10 @@ public:
/**
* Takes all the items from aList and puts them in our list.
*/
nsDisplayWrapList(nsIFrame* aFrame, nsDisplayList* aList);
nsDisplayWrapList(nsIFrame* aFrame, nsDisplayItem* aItem);
nsDisplayWrapList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
nsDisplayList* aList);
nsDisplayWrapList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
nsDisplayItem* aItem);
virtual ~nsDisplayWrapList();
virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames);
@ -1477,7 +1501,8 @@ protected:
*/
class nsDisplayOpacity : public nsDisplayWrapList {
public:
nsDisplayOpacity(nsIFrame* aFrame, nsDisplayList* aList);
nsDisplayOpacity(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
nsDisplayList* aList);
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplayOpacity();
#endif
@ -1499,7 +1524,8 @@ public:
*/
class nsDisplayOwnLayer : public nsDisplayWrapList {
public:
nsDisplayOwnLayer(nsIFrame* aFrame, nsDisplayList* aList);
nsDisplayOwnLayer(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
nsDisplayList* aList);
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplayOwnLayer();
#endif
@ -1531,9 +1557,11 @@ public:
* frame for this content, e.g. the frame whose z-index we have.
* @param aClippingFrame the frame that is inducing the clipping.
*/
nsDisplayClip(nsIFrame* aFrame, nsIFrame* aClippingFrame,
nsDisplayClip(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
nsIFrame* aClippingFrame,
nsDisplayItem* aItem, const nsRect& aRect);
nsDisplayClip(nsIFrame* aFrame, nsIFrame* aClippingFrame,
nsDisplayClip(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
nsIFrame* aClippingFrame,
nsDisplayList* aList, const nsRect& aRect);
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplayClip();
@ -1576,7 +1604,8 @@ public:
* @param aParentAPD is the app units per dev pixel ratio of the parent
* document.
*/
nsDisplayZoom(nsIFrame* aFrame, nsDisplayList* aList,
nsDisplayZoom(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
nsDisplayList* aList,
PRInt32 aAPD, PRInt32 aParentAPD);
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplayZoom();
@ -1606,7 +1635,8 @@ private:
*/
class nsDisplaySVGEffects : public nsDisplayWrapList {
public:
nsDisplaySVGEffects(nsIFrame* aFrame, nsDisplayList* aList);
nsDisplaySVGEffects(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
nsDisplayList* aList);
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplaySVGEffects();
#endif
@ -1644,8 +1674,9 @@ public:
/* Constructor accepts a display list, empties it, and wraps it up. It also
* ferries the underlying frame to the nsDisplayItem constructor.
*/
nsDisplayTransform(nsIFrame *aFrame, nsDisplayList *aList) :
nsDisplayItem(aFrame), mStoredList(aFrame, aList)
nsDisplayTransform(nsDisplayListBuilder* aBuilder, nsIFrame *aFrame,
nsDisplayList *aList) :
nsDisplayItem(aBuilder, aFrame), mStoredList(aBuilder, aFrame, aList)
{
MOZ_COUNT_CTOR(nsDisplayTransform);
}

Просмотреть файл

@ -2408,6 +2408,12 @@ DocumentViewerImpl::FindContainerView()
parentDocShell->GetPresShell(getter_AddRefs(parentPresShell));
}
}
if (!parentPresShell && containerElement) {
nsCOMPtr<nsIDocument> parentDoc = containerElement->GetCurrentDoc();
if (parentDoc) {
parentPresShell = parentDoc->GetShell();
}
}
if (!containerElement) {
NS_WARNING("Subdocument container has no content");
} else if (!parentPresShell) {

Просмотреть файл

@ -1219,13 +1219,13 @@ nsLayoutUtils::PaintFrame(nsIRenderingContext* aRenderingContext, nsIFrame* aFra
const nsRegion& aDirtyRegion, nscolor aBackstop,
PRUint32 aFlags)
{
#ifdef DEBUG
if (aFlags & PAINT_WIDGET_LAYERS) {
nsIView* view = aFrame->GetView();
NS_ASSERTION(view && view->GetWidget() && GetDisplayRootFrame(aFrame) == aFrame,
"PAINT_WIDGET_LAYERS should only be used on a display root that has a widget");
if (!(view && view->GetWidget() && GetDisplayRootFrame(aFrame) == aFrame)) {
aFlags &= ~PAINT_WIDGET_LAYERS;
NS_ASSERTION(aRenderingContext, "need a rendering context");
}
}
#endif
nsPresContext* presContext = aFrame->PresContext();
nsIPresShell* presShell = presContext->PresShell();

Просмотреть файл

@ -5368,7 +5368,8 @@ PresShell::ClipListToRange(nsDisplayListBuilder *aBuilder,
// wrap the item in an nsDisplayClip so that it can be clipped to
// the selection. If the allocation fails, fall through and delete
// the item below.
itemToInsert = new (aBuilder)nsDisplayClip(frame, frame, i, textRect);
itemToInsert = new (aBuilder)
nsDisplayClip(aBuilder, frame, frame, i, textRect);
}
}
// Don't try to descend into subdocuments.
@ -5715,8 +5716,8 @@ PresShell::AddPrintPreviewBackgroundItem(nsDisplayListBuilder& aBuilder,
nsIFrame* aFrame,
const nsRect& aBounds)
{
return aList.AppendNewToBottom(
new (&aBuilder) nsDisplaySolidColor(aFrame, aBounds, NS_RGB(115, 115, 115)));
return aList.AppendNewToBottom(new (&aBuilder)
nsDisplaySolidColor(&aBuilder, aFrame, aBounds, NS_RGB(115, 115, 115)));
}
static PRBool
@ -5772,7 +5773,7 @@ nsresult PresShell::AddCanvasBackgroundColorItem(nsDisplayListBuilder& aBuilder,
}
return aList.AppendNewToBottom(
new (&aBuilder) nsDisplaySolidColor(aFrame, aBounds, bgcolor));
new (&aBuilder) nsDisplaySolidColor(&aBuilder, aFrame, aBounds, bgcolor));
}
void PresShell::UpdateCanvasBackground()

Просмотреть файл

@ -51,6 +51,9 @@
#include "nsGUIEvent.h"
#include "nsEventDispatcher.h"
#include "jsapi.h"
#include "nsContentUtils.h"
using mozilla::TimeStamp;
/*
* TODO:
@ -59,9 +62,30 @@
* that we flush when necessary.
*/
#define REFRESH_INTERVAL_MILLISECONDS 20
#define DEFAULT_FRAME_RATE 60
using mozilla::TimeStamp;
// Compute the interval to use for the refresh driver timer, in
// milliseconds
static PRInt32
GetRefreshTimerInterval()
{
PRInt32 rate = nsContentUtils::GetIntPref("layout.frame_rate", -1);
if (rate <= 0) {
// TODO: get the rate from the platform
rate = DEFAULT_FRAME_RATE;
}
NS_ASSERTION(rate > 0, "Must have positive rate here");
return NSToIntRound(1000.0/rate);
}
static PRInt32
GetRefreshTimerType()
{
PRBool precise =
nsContentUtils::GetBoolPref("layout.frame_rate.precise", PR_FALSE);
return precise ? nsITimer::TYPE_REPEATING_PRECISE
: nsITimer::TYPE_REPEATING_SLACK;
}
nsRefreshDriver::nsRefreshDriver(nsPresContext *aPresContext)
: mPresContext(aPresContext),
@ -128,8 +152,8 @@ nsRefreshDriver::EnsureTimerStarted()
return;
}
nsresult rv = mTimer->InitWithCallback(this, REFRESH_INTERVAL_MILLISECONDS,
nsITimer::TYPE_REPEATING_SLACK);
nsresult rv = mTimer->InitWithCallback(this, GetRefreshTimerInterval(),
GetRefreshTimerType());
if (NS_FAILED(rv)) {
mTimer = nsnull;
}

Просмотреть файл

@ -93,8 +93,9 @@ nsButtonFrameRenderer::isDisabled()
class nsDisplayButtonBoxShadowOuter : public nsDisplayItem {
public:
nsDisplayButtonBoxShadowOuter(nsButtonFrameRenderer* aRenderer)
: nsDisplayItem(aRenderer->GetFrame()), mBFR(aRenderer) {
nsDisplayButtonBoxShadowOuter(nsDisplayListBuilder* aBuilder,
nsButtonFrameRenderer* aRenderer)
: nsDisplayItem(aBuilder, aRenderer->GetFrame()), mBFR(aRenderer) {
MOZ_COUNT_CTOR(nsDisplayButtonBoxShadowOuter);
}
#ifdef NS_BUILD_REFCNT_LOGGING
@ -113,13 +114,13 @@ private:
nsRect
nsDisplayButtonBoxShadowOuter::GetBounds(nsDisplayListBuilder* aBuilder) {
return mFrame->GetOverflowRect() + aBuilder->ToReferenceFrame(mFrame);
return mFrame->GetOverflowRect() + ToReferenceFrame();
}
void
nsDisplayButtonBoxShadowOuter::Paint(nsDisplayListBuilder* aBuilder,
nsIRenderingContext* aCtx) {
nsRect frameRect = nsRect(aBuilder->ToReferenceFrame(mFrame), mFrame->GetSize());
nsRect frameRect = nsRect(ToReferenceFrame(), mFrame->GetSize());
nsRect buttonRect;
mBFR->GetButtonRect(frameRect, buttonRect);
@ -130,8 +131,9 @@ nsDisplayButtonBoxShadowOuter::Paint(nsDisplayListBuilder* aBuilder,
class nsDisplayButtonBorderBackground : public nsDisplayItem {
public:
nsDisplayButtonBorderBackground(nsButtonFrameRenderer* aRenderer)
: nsDisplayItem(aRenderer->GetFrame()), mBFR(aRenderer) {
nsDisplayButtonBorderBackground(nsDisplayListBuilder* aBuilder,
nsButtonFrameRenderer* aRenderer)
: nsDisplayItem(aBuilder, aRenderer->GetFrame()), mBFR(aRenderer) {
MOZ_COUNT_CTOR(nsDisplayButtonBorderBackground);
}
#ifdef NS_BUILD_REFCNT_LOGGING
@ -153,8 +155,9 @@ private:
class nsDisplayButtonForeground : public nsDisplayItem {
public:
nsDisplayButtonForeground(nsButtonFrameRenderer* aRenderer)
: nsDisplayItem(aRenderer->GetFrame()), mBFR(aRenderer) {
nsDisplayButtonForeground(nsDisplayListBuilder* aBuilder,
nsButtonFrameRenderer* aRenderer)
: nsDisplayItem(aBuilder, aRenderer->GetFrame()), mBFR(aRenderer) {
MOZ_COUNT_CTOR(nsDisplayButtonForeground);
}
#ifdef NS_BUILD_REFCNT_LOGGING
@ -175,7 +178,7 @@ void nsDisplayButtonBorderBackground::Paint(nsDisplayListBuilder* aBuilder,
{
NS_ASSERTION(mFrame, "No frame?");
nsPresContext* pc = mFrame->PresContext();
nsRect r = nsRect(aBuilder->ToReferenceFrame(mFrame), mFrame->GetSize());
nsRect r = nsRect(ToReferenceFrame(), mFrame->GetSize());
// draw the border and background inside the focus and outline borders
mBFR->PaintBorderAndBackground(pc, *aCtx, mVisibleRect, r,
@ -190,7 +193,7 @@ void nsDisplayButtonForeground::Paint(nsDisplayListBuilder* aBuilder,
if (!mFrame->IsThemed(disp) ||
!presContext->GetTheme()->ThemeDrawsFocusForWidget(presContext, mFrame, disp->mAppearance)) {
// draw the focus and outline borders
nsRect r = nsRect(aBuilder->ToReferenceFrame(mFrame), mFrame->GetSize());
nsRect r = nsRect(ToReferenceFrame(), mFrame->GetSize());
mBFR->PaintOutlineAndFocusBorders(presContext, *aCtx, mVisibleRect, r);
}
}
@ -202,16 +205,16 @@ nsButtonFrameRenderer::DisplayButton(nsDisplayListBuilder* aBuilder,
{
if (mFrame->GetStyleBorder()->mBoxShadow) {
nsresult rv = aBackground->AppendNewToTop(new (aBuilder)
nsDisplayButtonBoxShadowOuter(this));
nsDisplayButtonBoxShadowOuter(aBuilder, this));
NS_ENSURE_SUCCESS(rv, rv);
}
nsresult rv = aBackground->AppendNewToTop(new (aBuilder)
nsDisplayButtonBorderBackground(this));
nsDisplayButtonBorderBackground(aBuilder, this));
NS_ENSURE_SUCCESS(rv, rv);
return aForeground->AppendNewToTop(new (aBuilder)
nsDisplayButtonForeground(this));
nsDisplayButtonForeground(aBuilder, this));
}
void

Просмотреть файл

@ -1313,8 +1313,9 @@ nsComboboxControlFrame::UpdateRecentIndex(PRInt32 aIndex)
class nsDisplayComboboxFocus : public nsDisplayItem {
public:
nsDisplayComboboxFocus(nsComboboxControlFrame* aFrame)
: nsDisplayItem(aFrame) {
nsDisplayComboboxFocus(nsDisplayListBuilder* aBuilder,
nsComboboxControlFrame* aFrame)
: nsDisplayItem(aBuilder, aFrame) {
MOZ_COUNT_CTOR(nsDisplayComboboxFocus);
}
#ifdef NS_BUILD_REFCNT_LOGGING
@ -1332,7 +1333,7 @@ void nsDisplayComboboxFocus::Paint(nsDisplayListBuilder* aBuilder,
nsIRenderingContext* aCtx)
{
static_cast<nsComboboxControlFrame*>(mFrame)
->PaintFocus(*aCtx, aBuilder->ToReferenceFrame(mFrame));
->PaintFocus(*aCtx, ToReferenceFrame());
}
NS_IMETHODIMP
@ -1367,8 +1368,8 @@ nsComboboxControlFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
if ((!IsThemed(disp) ||
!presContext->GetTheme()->ThemeDrawsFocusForWidget(presContext, this, disp->mAppearance)) &&
mDisplayFrame && IsVisibleForPainting(aBuilder)) {
nsresult rv = aLists.Content()->AppendNewToTop(new (aBuilder)
nsDisplayComboboxFocus(this));
nsresult rv = aLists.Content()->AppendNewToTop(
new (aBuilder) nsDisplayComboboxFocus(aBuilder, this));
NS_ENSURE_SUCCESS(rv, rv);
}
}

Просмотреть файл

@ -176,8 +176,9 @@ nsFieldSetFrame::SetInitialChildList(nsIAtom* aListName,
class nsDisplayFieldSetBorderBackground : public nsDisplayItem {
public:
nsDisplayFieldSetBorderBackground(nsFieldSetFrame* aFrame)
: nsDisplayItem(aFrame) {
nsDisplayFieldSetBorderBackground(nsDisplayListBuilder* aBuilder,
nsFieldSetFrame* aFrame)
: nsDisplayItem(aBuilder, aFrame) {
MOZ_COUNT_CTOR(nsDisplayFieldSetBorderBackground);
}
#ifdef NS_BUILD_REFCNT_LOGGING
@ -207,7 +208,7 @@ nsDisplayFieldSetBorderBackground::Paint(nsDisplayListBuilder* aBuilder,
nsIRenderingContext* aCtx)
{
static_cast<nsFieldSetFrame*>(mFrame)->
PaintBorderBackground(*aCtx, aBuilder->ToReferenceFrame(mFrame),
PaintBorderBackground(*aCtx, ToReferenceFrame(),
mVisibleRect, aBuilder->GetBackgroundPaintFlags());
}
@ -222,14 +223,14 @@ nsFieldSetFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
if (IsVisibleForPainting(aBuilder)) {
if (GetStyleBorder()->mBoxShadow) {
nsresult rv = aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
nsDisplayBoxShadowOuter(this));
nsDisplayBoxShadowOuter(aBuilder, this));
NS_ENSURE_SUCCESS(rv, rv);
}
// don't bother checking to see if we really have a border or background.
// we usually will have a border.
nsresult rv = aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
nsDisplayFieldSetBorderBackground(this));
nsDisplayFieldSetBorderBackground(aBuilder, this));
NS_ENSURE_SUCCESS(rv, rv);
rv = DisplayOutlineUnconditional(aBuilder, aLists);

Просмотреть файл

@ -1007,7 +1007,7 @@ nsFileControlFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
// box-shadow
if (GetStyleBorder()->mBoxShadow) {
nsresult rv = aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
nsDisplayBoxShadowOuter(this));
nsDisplayBoxShadowOuter(aBuilder, this));
NS_ENSURE_SUCCESS(rv, rv);
}
@ -1031,14 +1031,12 @@ nsFileControlFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
// Disabled file controls don't pass mouse events to their children, so we
// put an invisible item in the display list above the children
// just to catch events
// REVIEW: I'm not sure why we do this, but that's what nsFileControlFrame::
// GetFrameForPoint was doing
if (mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::disabled) &&
IsVisibleForPainting(aBuilder)) {
nsDisplayItem* item = new (aBuilder) nsDisplayEventReceiver(this);
if (!item)
return NS_ERROR_OUT_OF_MEMORY;
aLists.Content()->AppendToTop(item);
rv = aLists.Content()->AppendNewToTop(
new (aBuilder) nsDisplayEventReceiver(aBuilder, this));
if (NS_FAILED(rv))
return rv;
}
return DisplaySelectionOverlay(aBuilder, aLists);

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше