зеркало из https://github.com/mozilla/pjs.git
Merge mozilla-central to tracemonkey
This commit is contained in:
Коммит
3367dc7943
|
@ -259,8 +259,7 @@ __try {
|
|||
return E_FAIL;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRenderingContext> rc;
|
||||
presShell->CreateRenderingContext(frame, getter_AddRefs(rc));
|
||||
nsCOMPtr<nsIRenderingContext> rc = presShell->GetReferenceRenderingContext();
|
||||
if (!rc) {
|
||||
return E_FAIL;
|
||||
}
|
||||
|
|
|
@ -512,6 +512,7 @@
|
|||
disabled="true"/>
|
||||
#endif
|
||||
<menu id="historyUndoMenu"
|
||||
class="recentlyClosedTabsMenu"
|
||||
label="&historyUndoMenu.label;"
|
||||
disabled="true">
|
||||
<menupopup id="historyUndoPopup"
|
||||
|
@ -521,6 +522,7 @@
|
|||
onpopupshowing="document.getElementById('history-menu')._placesView.populateUndoSubmenu();"/>
|
||||
</menu>
|
||||
<menu id="historyUndoWindowMenu"
|
||||
class="recentlyClosedWindowsMenu"
|
||||
label="&historyUndoWindowMenu.label;"
|
||||
disabled="true">
|
||||
<menupopup id="historyUndoWindowPopup"
|
||||
|
@ -557,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);"
|
||||
|
|
|
@ -576,13 +576,13 @@ HistoryMenu.prototype = {
|
|||
|
||||
toggleRecentlyClosedTabs: function HM_toggleRecentlyClosedTabs() {
|
||||
// enable/disable the Recently Closed Tabs sub menu
|
||||
var undoPopup = document.getElementById("historyUndoPopup");
|
||||
var undoMenu = this._rootElt.getElementsByClassName("recentlyClosedTabsMenu")[0];
|
||||
|
||||
// no restorable tabs, so disable menu
|
||||
if (this._ss.getClosedTabCount(window) == 0)
|
||||
undoPopup.parentNode.setAttribute("disabled", true);
|
||||
undoMenu.setAttribute("disabled", true);
|
||||
else
|
||||
undoPopup.parentNode.removeAttribute("disabled");
|
||||
undoMenu.removeAttribute("disabled");
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -603,7 +603,8 @@ HistoryMenu.prototype = {
|
|||
* Populate when the history menu is opened
|
||||
*/
|
||||
populateUndoSubmenu: function PHM_populateUndoSubmenu() {
|
||||
var undoPopup = document.getElementById("historyUndoPopup");
|
||||
var undoMenu = this._rootElt.getElementsByClassName("recentlyClosedTabsMenu")[0];
|
||||
var undoPopup = undoMenu.firstChild;
|
||||
|
||||
// remove existing menu items
|
||||
while (undoPopup.hasChildNodes())
|
||||
|
@ -611,12 +612,12 @@ HistoryMenu.prototype = {
|
|||
|
||||
// no restorable tabs, so make sure menu is disabled, and return
|
||||
if (this._ss.getClosedTabCount(window) == 0) {
|
||||
undoPopup.parentNode.setAttribute("disabled", true);
|
||||
undoMenu.setAttribute("disabled", true);
|
||||
return;
|
||||
}
|
||||
|
||||
// enable menu
|
||||
undoPopup.parentNode.removeAttribute("disabled");
|
||||
undoMenu.removeAttribute("disabled");
|
||||
|
||||
// populate menu
|
||||
var undoItems = eval("(" + this._ss.getClosedTabData(window) + ")");
|
||||
|
@ -661,20 +662,21 @@ HistoryMenu.prototype = {
|
|||
|
||||
toggleRecentlyClosedWindows: function PHM_toggleRecentlyClosedWindows() {
|
||||
// enable/disable the Recently Closed Windows sub menu
|
||||
let undoPopup = document.getElementById("historyUndoWindowPopup");
|
||||
var undoMenu = this._rootElt.getElementsByClassName("recentlyClosedWindowsMenu")[0];
|
||||
|
||||
// no restorable windows, so disable menu
|
||||
if (this._ss.getClosedWindowCount() == 0)
|
||||
undoPopup.parentNode.setAttribute("disabled", true);
|
||||
undoMenu.setAttribute("disabled", true);
|
||||
else
|
||||
undoPopup.parentNode.removeAttribute("disabled");
|
||||
undoMenu.removeAttribute("disabled");
|
||||
},
|
||||
|
||||
/**
|
||||
* Populate when the history menu is opened
|
||||
*/
|
||||
populateUndoWindowSubmenu: function PHM_populateUndoWindowSubmenu() {
|
||||
let undoPopup = document.getElementById("historyUndoWindowPopup");
|
||||
let undoMenu = this._rootElt.getElementsByClassName("recentlyClosedWindowsMenu")[0];
|
||||
let undoPopup = undoMenu.firstChild;
|
||||
let menuLabelString = gNavigatorBundle.getString("menuUndoCloseWindowLabel");
|
||||
let menuLabelStringSingleTab =
|
||||
gNavigatorBundle.getString("menuUndoCloseWindowSingleTabLabel");
|
||||
|
@ -685,12 +687,12 @@ HistoryMenu.prototype = {
|
|||
|
||||
// no restorable windows, so make sure menu is disabled, and return
|
||||
if (this._ss.getClosedWindowCount() == 0) {
|
||||
undoPopup.parentNode.setAttribute("disabled", true);
|
||||
undoMenu.setAttribute("disabled", true);
|
||||
return;
|
||||
}
|
||||
|
||||
// enable menu
|
||||
undoPopup.parentNode.removeAttribute("disabled");
|
||||
undoMenu.removeAttribute("disabled");
|
||||
|
||||
// populate menu
|
||||
let undoItems = JSON.parse(this._ss.getClosedWindowData());
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -2604,11 +2604,6 @@ function BrowserOnClick(event) {
|
|||
);
|
||||
}
|
||||
}
|
||||
else if (/^about:privatebrowsing/.test(errorDoc.documentURI)) {
|
||||
if (ot == errorDoc.getElementById("startPrivateBrowsing")) {
|
||||
gPrivateBrowsingUI.toggleMode();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -6643,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) {
|
||||
|
|
|
@ -521,7 +521,7 @@
|
|||
<hbox flex="1"
|
||||
class="split-menuitem">
|
||||
<menuitem id="appmenu_print"
|
||||
class="menuitem-iconic"
|
||||
class="menuitem-iconic split-menuitem-item"
|
||||
flex="1"
|
||||
label="&printCmd.label;"
|
||||
command="cmd_print"/>
|
||||
|
@ -579,52 +579,53 @@
|
|||
</vbox>
|
||||
<vbox id="appmenuSecondaryPane">
|
||||
<hbox class="split-menuitem">
|
||||
<menuitem id="appmenu_BookmarkItem"
|
||||
class="menuitem-iconic"
|
||||
<menuitem id="appmenu_bookmarks"
|
||||
class="menuitem-iconic split-menuitem-item"
|
||||
flex="1"
|
||||
label="&bookmarksMenu.label;"
|
||||
command="Browser:ShowAllBookmarks"/>
|
||||
<menu id="appmenuBookmarkMenu"
|
||||
<menu id="appmenu_bookmarksMenu"
|
||||
class="split-menuitem-menu">
|
||||
<menupopup id="appmenuBookmarkMenu_popup"
|
||||
<menupopup id="appmenu_bookmarksMenupopup"
|
||||
placespopup="true"
|
||||
context="placesContext"
|
||||
openInTabs="children"
|
||||
oncommand="BookmarksEventHandler.onCommand(event);"
|
||||
onclick="BookmarksEventHandler.onClick(event);"
|
||||
onpopupshowing="BookmarksMenuButton.onPopupShowing(event);
|
||||
if (!this.parentNode._placesView)new PlacesMenu(event, 'place:folder=BOOKMARKS_MENU');
|
||||
this.appendChild(document.getElementById('appmenuBookmarkMenu_unsorted_seperator'));
|
||||
this.appendChild(document.getElementById('appmenuBookmarkMenu_unsorted-menuitem'));"
|
||||
if (!this.parentNode._placesView)
|
||||
new PlacesMenu(event, 'place:folder=BOOKMARKS_MENU');
|
||||
this.appendChild(document.getElementById('appmenu_unsortedBookmarks_seperator'));
|
||||
this.appendChild(document.getElementById('appmenu_unsortedBookmarks'));"
|
||||
tooltip="bhTooltip"
|
||||
popupsinherittooltip="true">
|
||||
<menuseparator id="appmenuBookmarkMenu_unsorted_seperator"/>
|
||||
<menuitem id="appmenuBookmarkMenu_unsorted-menuitem"
|
||||
<menuseparator id="appmenu_unsortedBookmarks_seperator"/>
|
||||
<menuitem id="appmenu_unsortedBookmarks"
|
||||
label="&appMenuUnsorted.label;"
|
||||
oncommand="PlacesCommandHook.showPlacesOrganizer('UnfiledBookmarks');"
|
||||
class="menuitem-iconic"/>
|
||||
<menuitem id="appmenuBookmarkMenu_organize_bookmarks"
|
||||
<menuitem id="appmenu_organizeBookmarks"
|
||||
label="&organizeBookmarks.label;"
|
||||
key="manBookmarkKb"
|
||||
command="Browser:ShowAllBookmarks"
|
||||
context=""/>
|
||||
<menuseparator/>
|
||||
<menuitem id="appmenuBookmarkThisPage"
|
||||
<menuitem id="appmenu_bookmarkThisPage"
|
||||
class="menuitem-iconic"
|
||||
label="&bookmarkThisPageCmd.label;"
|
||||
command="Browser:AddBookmarkAs"
|
||||
key="addBookmarkAsKb"/>
|
||||
<menuitem id="subscribeToPageMenuitem"
|
||||
<menuitem id="appmenu_subscribeToPage"
|
||||
class="menuitem-iconic"
|
||||
label="&subscribeToPageMenuitem.label;"
|
||||
oncommand="return FeedHandler.subscribeToFeed(null, event);"
|
||||
onclick="checkForMiddleClick(this, event);"
|
||||
disabled="true"/>
|
||||
<menu id="subscribeToPageMenupopup"
|
||||
observes="singleFeedMenuitemState"/>
|
||||
<menu id="appmenu_subscribeToPageMenu"
|
||||
class="menu-iconic"
|
||||
label="&subscribeToPageMenupopup.label;"
|
||||
hidden="true">
|
||||
<menupopup id="subscribeToPageSubmenuMenupopup"
|
||||
observes="multipleFeedsMenuState">
|
||||
<menupopup id="appmenu_subscribeToPageMenupopup"
|
||||
onpopupshowing="return FeedHandler.buildFeedList(event.target);"
|
||||
oncommand="return FeedHandler.subscribeToFeed(null, event);"
|
||||
onclick="checkForMiddleClick(this, event);"/>
|
||||
|
@ -634,18 +635,19 @@
|
|||
</menu>
|
||||
</hbox>
|
||||
<hbox class="split-menuitem">
|
||||
<menuitem id="appmenu_HistoryItem"
|
||||
class="menuitem-iconic"
|
||||
<menuitem id="appmenu_history"
|
||||
class="menuitem-iconic split-menuitem-item"
|
||||
flex="1"
|
||||
label="&historyMenu.label;"
|
||||
command="Browser:ShowAllHistory"/>
|
||||
<menu id="appmenu_history"
|
||||
<menu id="appmenu_historyMenu"
|
||||
class="split-menuitem-menu">
|
||||
<menupopup id="appmenu_history_popup"
|
||||
<menupopup id="appmenu_historyMenupopup"
|
||||
placespopup="true"
|
||||
oncommand="this.parentNode._placesView._onCommand(event);"
|
||||
onclick="checkForMiddleClick(this, event);"
|
||||
onpopupshowing="if (!this.parentNode._placesView) new HistoryMenu(event);"
|
||||
onpopupshowing="if (!this.parentNode._placesView)
|
||||
new HistoryMenu(event);"
|
||||
tooltip="bhTooltip"
|
||||
popupsinherittooltip="true">
|
||||
<menuitem id="appmenu_showAllHistory"
|
||||
|
@ -658,17 +660,19 @@
|
|||
key="key_sanitize"
|
||||
command="Tools:Sanitize"/>
|
||||
<menuseparator class="hide-if-empty-places-result"/>
|
||||
<menu id="historyUndoMenu"
|
||||
<menu id="appmenu_recentlyClosedTabsMenu"
|
||||
class="recentlyClosedTabsMenu"
|
||||
label="&historyUndoMenu.label;"
|
||||
disabled="true">
|
||||
<menupopup id="historyUndoPopup"
|
||||
onpopupshowing="_placesView.populateUndoSubmenu();"/>
|
||||
<menupopup id="appmenu_recentlyClosedTabsMenupopup"
|
||||
onpopupshowing="document.getElementById('appmenu_historyMenu')._placesView.populateUndoSubmenu();"/>
|
||||
</menu>
|
||||
<menu id="historyUndoWindowMenu"
|
||||
<menu id="appmenu_recentlyClosedWindowsMenu"
|
||||
class="recentlyClosedWindowsMenu"
|
||||
label="&historyUndoWindowMenu.label;"
|
||||
disabled="true">
|
||||
<menupopup id="historyUndoPopup"
|
||||
onpopupshowing="_placesView.populateUndoWindowSubmenu();"/>
|
||||
<menupopup id="appmenu_recentlyClosedWindowsMenupopup"
|
||||
onpopupshowing="document.getElementById('appmenu_historyMenu')._placesView.populateUndoWindowSubmenu();"/>
|
||||
</menu>
|
||||
<menuseparator/>
|
||||
</menupopup>
|
||||
|
@ -691,7 +695,7 @@
|
|||
<menu class="split-menuitem-menu"
|
||||
label="&preferencesCmd.label;">
|
||||
<menupopup id="appmenu_customizeMenu"
|
||||
onpopupshowing="onViewToolbarsPopupShowing(event, (document.getElementById('appmenuToggleStatusbar')));">
|
||||
onpopupshowing="onViewToolbarsPopupShowing(event, document.getElementById('appmenu_toggleStatusbar'));">
|
||||
<menuitem id="appmenu_preferences"
|
||||
#ifdef XP_UNIX
|
||||
label="&preferencesCmdUnix.label;"
|
||||
|
@ -700,12 +704,12 @@
|
|||
#endif
|
||||
oncommand="openPreferences();"/>
|
||||
<menuseparator/>
|
||||
<menuitem id="appmenuToggleStatusbar"
|
||||
<menuitem id="appmenu_toggleStatusbar"
|
||||
type="checkbox"
|
||||
command="cmd_toggleTaskbar"
|
||||
observes="toggle_taskbar"/>
|
||||
<menuseparator/>
|
||||
<menuitem id="appmenuToggleTabs"
|
||||
<menuitem id="appmenu_toggleTabsOnTop"
|
||||
label="&viewTabsOnTop.label;"
|
||||
type="checkbox"
|
||||
command="cmd_ToggleTabsOnTop"/>
|
||||
|
@ -716,23 +720,23 @@
|
|||
</menu>
|
||||
</hbox>
|
||||
<hbox class="split-menuitem">
|
||||
<menuitem id="appmenu_helpItem"
|
||||
<menuitem id="appmenu_help"
|
||||
class="split-menuitem-item"
|
||||
flex="1"
|
||||
label="&helpMenu.label;"
|
||||
oncommand="openHelpLink('firefox-help')"/>
|
||||
<menu id="appmenu_about_menu"
|
||||
class="split-menuitem-menu">
|
||||
<menupopup>
|
||||
<menu class="split-menuitem-menu">
|
||||
<menupopup id="appmenu_helpMenupopup">
|
||||
<menuitem id="appmenu_openHelp"
|
||||
label="&helpMenu.label;"
|
||||
oncommand="openHelpLink('firefox-help')"
|
||||
onclick="checkForMiddleClick(this, event);"/>
|
||||
<menuitem id="appmenu_help_getting_started"
|
||||
<menuitem id="appmenu_gettingStarted"
|
||||
label="&appMenuGettingStarted.label;"
|
||||
oncommand="gBrowser.selectedTab = gBrowser.addTab('http://www.mozilla.com/firefox/central/');"
|
||||
oncommand="gBrowser.loadOneTab('http://www.mozilla.com/firefox/central/', {inBackground: false});"
|
||||
onclick="checkForMiddleClick(this, event);"/>
|
||||
<menuseparator/>
|
||||
<menuitem id="appmenu_help_about"
|
||||
<menuitem id="appmenu_about"
|
||||
label="&aboutProduct.label;"
|
||||
oncommand="openAboutDialog();"/>
|
||||
</menupopup>
|
||||
|
|
|
@ -146,6 +146,7 @@ _BROWSER_FILES = \
|
|||
browser_ctrlTab.js \
|
||||
browser_discovery.js \
|
||||
browser_drag.js \
|
||||
browser_duplicateIDs.js \
|
||||
browser_gestureSupport.js \
|
||||
browser_getshortcutoruri.js \
|
||||
browser_hide_removing.js \
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
function test() {
|
||||
var ids = {};
|
||||
Array.forEach(document.querySelectorAll("[id]"), function (node) {
|
||||
var id = node.id;
|
||||
ok(!(id in ids), id + " should be unique");
|
||||
ids[id] = null;
|
||||
});
|
||||
}
|
|
@ -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();
|
||||
|
|
|
@ -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>
|
|
@ -114,6 +114,10 @@
|
|||
if (moreInfoLink)
|
||||
moreInfoLink.setAttribute("href", moreInfoURL + "private-browsing");
|
||||
}, false);
|
||||
|
||||
function togglePrivateBrowsing() {
|
||||
mainWindow.gPrivateBrowsingUI.toggleMode();
|
||||
}
|
||||
]]></script>
|
||||
</head>
|
||||
|
||||
|
@ -145,9 +149,10 @@
|
|||
|
||||
<!-- Start Private Browsing -->
|
||||
<div id="startPrivateBrowsingDesc" class="showNormal">
|
||||
<button id="startPrivateBrowsing"
|
||||
<button xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
id="startPrivateBrowsing" label="&privatebrowsingpage.startPrivateBrowsing.label;"
|
||||
accesskey="&privatebrowsingpage.startPrivateBrowsing.accesskey;"
|
||||
>&privatebrowsingpage.startPrivateBrowsing.label;</button>
|
||||
oncommand="togglePrivateBrowsing();"/>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
|
|
|
@ -380,7 +380,6 @@
|
|||
@BINPATH@/components/nsPrompter.js
|
||||
#ifdef MOZ_SERVICES_SYNC
|
||||
@BINPATH@/components/SyncComponents.manifest
|
||||
@BINPATH@/components/FormNotifier.js
|
||||
@BINPATH@/components/Weave.js
|
||||
@BINPATH@/components/WeaveCrypto.manifest
|
||||
@BINPATH@/components/WeaveCrypto.js
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -170,12 +170,12 @@ be temporary, and you can try again later.</li>
|
|||
<!ENTITY securityOverride.getMeOutOfHereButton "Get me out of here!">
|
||||
<!ENTITY securityOverride.exceptionButtonLabel "Add Exception…">
|
||||
|
||||
<!-- LOCALIZATION NOTE (securityOverride.warningText) - Do not translate the
|
||||
contents of the <xul:button> tags. The only language content is the label= field,
|
||||
which uses strings already defined above. The button is included here (instead of
|
||||
netError.xhtml) because it exposes functionality specific to firefox. -->
|
||||
<!-- LOCALIZATION NOTE (securityOverride.warningContent) - Do not translate the
|
||||
contents of the <button> tags. It uses strings already defined above. The
|
||||
button is included here (instead of netError.xhtml) because it exposes
|
||||
functionality specific to firefox. -->
|
||||
|
||||
<!ENTITY securityOverride.warningText "
|
||||
<!ENTITY securityOverride.warningContent "
|
||||
<p>You should not add an exception if you are using an internet connection that you do not trust completely or if you are not used to seeing a warning for this server.</p>
|
||||
|
||||
<button id='getMeOutOfHereButton'>&securityOverride.getMeOutOfHereButton;</button>
|
||||
|
|
|
@ -251,23 +251,16 @@ statusbarpanel#statusbar-display {
|
|||
font-style: italic;
|
||||
}
|
||||
|
||||
#appmenu_BookmarkItem {
|
||||
#appmenu_bookmarks {
|
||||
list-style-image: url("chrome://browser/skin/places/bookmark.png");
|
||||
-moz-image-region: rect(0px 48px 16px 32px);
|
||||
}
|
||||
|
||||
#appmenu_BookmarkItem > .menu-iconic-left,
|
||||
#appmenu_addons > .menu-iconic-left {
|
||||
-moz-margin-end: -5px;
|
||||
-moz-margin-start: 5px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#appmenu_privateBrowsing {
|
||||
list-style-image: url("chrome://browser/skin/Privacy-16.png");
|
||||
}
|
||||
|
||||
#appmenuBookmarkMenu_unsorted-menuitem {
|
||||
#appmenu_unsortedBookmarks {
|
||||
list-style-image: url("chrome://browser/skin/places/unsortedBookmarks.png");
|
||||
}
|
||||
|
||||
|
@ -275,13 +268,13 @@ statusbarpanel#statusbar-display {
|
|||
list-style-image: url("chrome://mozapps/skin/extensions/extensionGeneric-16.png");
|
||||
}
|
||||
|
||||
#appmenu-button #subscribeToPageMenuitem:not([disabled]),
|
||||
#appmenu-button #subscribeToPageMenupopup:not([hidden]) {
|
||||
#appmenu_subscribeToPage:not([disabled]),
|
||||
#appmenu_subscribeToPageMenu {
|
||||
list-style-image: url("chrome://browser/skin/feeds/feed-icons-16.png");
|
||||
-moz-image-region: rect(0px 16px 16px 0px);
|
||||
}
|
||||
|
||||
#appmenuBookmarkThisPage {
|
||||
#appmenu_bookmarkThisPage {
|
||||
list-style-image: url("chrome://browser/skin/places/bookmark.png");
|
||||
-moz-image-region: rect(0 16px 16px 0);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
@ -294,6 +295,7 @@ class Automation(object):
|
|||
# Open database and create table
|
||||
permDB = sqlite3.connect(os.path.join(profileDir, "permissions.sqlite"))
|
||||
cursor = permDB.cursor();
|
||||
# SQL copied from nsPermissionManager.cpp
|
||||
cursor.execute("""CREATE TABLE moz_hosts (
|
||||
id INTEGER PRIMARY KEY,
|
||||
host TEXT,
|
||||
|
@ -654,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
|
||||
|
@ -709,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().
|
||||
|
|
16
client.mk
16
client.mk
|
@ -142,11 +142,12 @@ run_for_side_effects := \
|
|||
|
||||
include $(TOPSRCDIR)/.mozconfig.mk
|
||||
|
||||
ifndef MOZ_OBJDIR
|
||||
MOZ_OBJDIR = obj-$(CONFIG_GUESS)
|
||||
endif
|
||||
|
||||
ifdef MOZ_BUILD_PROJECTS
|
||||
|
||||
ifndef MOZ_OBJDIR
|
||||
$(error When MOZ_BUILD_PROJECTS is set, you must set MOZ_OBJDIR)
|
||||
endif
|
||||
ifdef MOZ_CURRENT_PROJECT
|
||||
OBJDIR = $(MOZ_OBJDIR)/$(MOZ_CURRENT_PROJECT)
|
||||
MOZ_MAKE = $(MAKE) $(MOZ_MAKE_FLAGS) -C $(OBJDIR)
|
||||
|
@ -158,13 +159,8 @@ endif
|
|||
|
||||
else # MOZ_BUILD_PROJECTS
|
||||
|
||||
ifdef MOZ_OBJDIR
|
||||
OBJDIR = $(MOZ_OBJDIR)
|
||||
MOZ_MAKE = $(MAKE) $(MOZ_MAKE_FLAGS) -C $(OBJDIR)
|
||||
else
|
||||
OBJDIR := $(TOPSRCDIR)
|
||||
MOZ_MAKE := $(MAKE) $(MOZ_MAKE_FLAGS)
|
||||
endif
|
||||
OBJDIR = $(MOZ_OBJDIR)
|
||||
MOZ_MAKE = $(MAKE) $(MOZ_MAKE_FLAGS) -C $(OBJDIR)
|
||||
|
||||
endif # MOZ_BUILD_PROJECTS
|
||||
|
||||
|
|
|
@ -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@
|
||||
|
|
|
@ -1,78 +0,0 @@
|
|||
#!/usr/bin/env perl
|
||||
#
|
||||
# cvsco-fast-update.pl cvs co ...
|
||||
#
|
||||
# This command parses a "cvs co ..." command and converts it to
|
||||
# fast-update.pl commands
|
||||
#
|
||||
use Getopt::Long;
|
||||
|
||||
my $filename = ".fast-update";
|
||||
my $start_time = time();
|
||||
|
||||
my $branch;
|
||||
my @modules;
|
||||
my @dirs;
|
||||
my $dirlocal = 0;
|
||||
|
||||
print "$0: (".join(')(',@ARGV).")\n";
|
||||
while (scalar(@ARGV)) {
|
||||
my $val = shift(@ARGV);
|
||||
if ( ($val eq '-A') || ($val eq 'co') || ($val eq 'cvs')
|
||||
|| ($val eq '-P') || ($val eq '-q')) {
|
||||
#print "ignore $val\n";
|
||||
next;
|
||||
}
|
||||
elsif (($val eq '-d') || ($val eq '-q') || ($val eq '-z')) {
|
||||
my $tmp = shift @ARGV;
|
||||
#print "ignore $val $tmp\n";
|
||||
next;
|
||||
}
|
||||
elsif ($val eq '-r') {
|
||||
$branch = shift @ARGV;
|
||||
#print "branch = $branch\n";
|
||||
next;
|
||||
}
|
||||
elsif ($val eq '-l') {
|
||||
$dirlocal = 1;
|
||||
#print "dirlocal = $dirlocal\n";
|
||||
next;
|
||||
}
|
||||
elsif ($val =~ /^-/) {
|
||||
print "*** unknown switch: $val\n";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
if ($val =~ /\//) {
|
||||
push @dirs, $val;
|
||||
#print "dir = $val\n";
|
||||
}
|
||||
else {
|
||||
push @modules, $val;
|
||||
#print "module = $val\n";
|
||||
}
|
||||
}
|
||||
|
||||
#print "dir = (".join(')(', @dirs)."), "
|
||||
# . "module = (".join(')(', @modules)."), "
|
||||
# . "branch = ($branch)\n";
|
||||
|
||||
if (!$branch) {
|
||||
$branch = 'HEAD';
|
||||
}
|
||||
|
||||
my $status = 0;
|
||||
foreach my $mod (@modules) {
|
||||
my $cmd = "config/fast-update.pl -r $branch -m $mod" . ($dirlocal ? " -l" : "");
|
||||
#print "system \"$cmd\"\n";
|
||||
$status |= system $cmd;
|
||||
}
|
||||
my $dirlist = join(' -d ', @dirs);
|
||||
my $cmd = "config/fast-update.pl -r $branch -d $dirlist -m all" . ($dirlocal ? " -l" : "");
|
||||
#print "system \"$cmd\"\n";
|
||||
$status |= system $cmd;
|
||||
|
||||
exit $status;
|
||||
|
||||
|
||||
|
|
@ -1,83 +0,0 @@
|
|||
#!/usr/bin/env perl
|
||||
#
|
||||
# ***** 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
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1999
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Stephen Lamm
|
||||
#
|
||||
# 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 *****
|
||||
|
||||
sub usage {
|
||||
warn "usage: cvsco.pl <checkout_command>\n"
|
||||
." <checkout_command> is the entire cvs co command\n"
|
||||
." (e.g. cvs -q -z3 co SeaMonkeyAll).\n";
|
||||
}
|
||||
|
||||
usage(), die "Error: Not enough arguments\n" if $#ARGV < 0;
|
||||
usage(), die "Error: Wrong cwd. Must chdir to mozilla/..\n"
|
||||
unless -r 'mozilla/config/cvsco.pl';
|
||||
|
||||
$co_command = join ' ', @ARGV;
|
||||
|
||||
$logfile = 'cvslog.txt';
|
||||
$old_logfile = 'cvslog-old.txt';
|
||||
|
||||
sub dblprint {
|
||||
print LOG @_;
|
||||
print STDERR @_;
|
||||
}
|
||||
|
||||
if (-r $logfile) {
|
||||
rename $logfile, $old_logfile;
|
||||
print "rename $logfile, $old_logfile\n";
|
||||
}
|
||||
|
||||
open LOG, ">$logfile";
|
||||
open CVSCO, "$co_command|";
|
||||
|
||||
dblprint "\ncheckout start: ".scalar(localtime)."\n";
|
||||
dblprint "$co_command | tee cvslog.txt\n";
|
||||
|
||||
while (<CVSCO>) {
|
||||
dblprint $_;
|
||||
push @conflicts, $_ if /^C /;
|
||||
}
|
||||
|
||||
if (@conflicts) {
|
||||
print "Error: cvs conflicts during checkout:\n";
|
||||
die join('', @conflicts);
|
||||
}
|
||||
|
||||
close(CVSCO) or die "cvs error.\n";
|
||||
dblprint 'checkout finish: '.scalar(localtime)."\n";
|
||||
|
|
@ -1,312 +0,0 @@
|
|||
#!/usr/bin/env perl
|
||||
#
|
||||
# fast-update.pl [-h hours] [-m module] [-r branch]
|
||||
#
|
||||
# This command, fast-update.pl, does a (fast) cvs update of the current
|
||||
# directory. It is fast because the cvs up command is only run on those
|
||||
# directories / sub-directories where changes have occurred since the
|
||||
# last fast-update.
|
||||
#
|
||||
# The last update time is stored in a ".fast-update" file in the current
|
||||
# directory. Thus one can choose to only fast-update a branch of the tree
|
||||
# and then fast-update the whole tree later.
|
||||
#
|
||||
# The first time this command is run in a directory the last cvs update
|
||||
# time is assumed to be the timestamp of the CVS/Entries file.
|
||||
#
|
||||
use Getopt::Long;
|
||||
|
||||
my $filename = ".fast-update";
|
||||
my $start_time = time();
|
||||
|
||||
my $branch;
|
||||
my $module="SeaMonkeyAll";
|
||||
my $maxdirs=5;
|
||||
my $rootdir = "";
|
||||
my $hours = 0;
|
||||
my @dirs = ();
|
||||
my $dirlocal = 0;
|
||||
|
||||
&GetOptions('d=s@' => \@dirs, 'h=s' => \$hours, 'm=s' => \$module, 'r=s' => \$branch, 'l' => \$dirlocal);
|
||||
|
||||
#print "dirs = (@dirs), hours = ($hours), module = ($module), branch = ($branch), dirlocal = ($dirlocal)\n";
|
||||
if (scalar(@dirs) > 0) {
|
||||
# put .fast-update in the first directory listed
|
||||
$filename = "$dirs[0]/$filename";
|
||||
$filename =~ s#mozilla/*##;
|
||||
}
|
||||
|
||||
if (!$hours) {
|
||||
$hours = get_hours_since_last_update();
|
||||
}
|
||||
if (!$hours) {
|
||||
$hours = 24;
|
||||
}
|
||||
|
||||
|
||||
# pull out the current directory
|
||||
# if there is no such file, this will all just fail, which is ok
|
||||
open REPOSITORY, "<CVS/Repository";
|
||||
$rootdir = <REPOSITORY>;
|
||||
$rootdir =~ tr/\r\n//d; # Remove newlines
|
||||
close REPOSITORY;
|
||||
|
||||
# try to guess the current branch by looking at all the
|
||||
# files in CVS/Entries
|
||||
if (!$branch) {
|
||||
my $foundbranch =0;
|
||||
|
||||
open ENTRIES, "<CVS/Entries";
|
||||
while (<ENTRIES>) {
|
||||
chop;
|
||||
@entry = split(/\//);
|
||||
my ($type, $file, $ver, $date, $unknown, $tag) = @entry;
|
||||
|
||||
# the tag usually starts with "T"
|
||||
$thisbranch = substr($tag, 1);
|
||||
|
||||
# look for more than one branch
|
||||
if ($type eq "") {
|
||||
|
||||
if ($foundbranch and ($lastbranch ne $thisbranch)) {
|
||||
die "Multiple branches in this directory, cannot determine branch\n";
|
||||
}
|
||||
$foundbranch = 1;
|
||||
$lastbranch = $thisbranch;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$branch = $lastbranch if ($foundbranch);
|
||||
|
||||
close ENTRIES;
|
||||
}
|
||||
|
||||
# check for a static Tag
|
||||
# (at least that is what I think this does)
|
||||
# (bonsai does not report changes when the Tag starts with 'N')
|
||||
# (I do not really understand all this)
|
||||
if ($branch) {
|
||||
open TAG, "<CVS/Tag";
|
||||
my $line = <TAG>;
|
||||
if ($line =~ /^N/) {
|
||||
print "static tag, ignore branch\n";
|
||||
$branch = '';
|
||||
}
|
||||
close TAG;
|
||||
}
|
||||
|
||||
|
||||
my $url = "http://bonsai.mozilla.org/cvsquery.cgi?module=${module}&branch=${branch}&branchtype=match&sortby=File&date=hours&hours=${hours}&cvsroot=%2Fcvsroot";
|
||||
|
||||
my $dir_string = "";
|
||||
if (scalar(@dirs) > 0) {
|
||||
$dir_string = join(' ', @dirs);
|
||||
my $esc_dir = escape($dir_string);
|
||||
$url .= "&dir=$esc_dir";
|
||||
}
|
||||
if ($dirlocal) {
|
||||
$url .= "&dirtype=local";
|
||||
}
|
||||
|
||||
print "Contacting bonsai for updates to ${module} ";
|
||||
print "on the ${branch} branch " if ($branch);
|
||||
print "in the last ${hours} hours ";
|
||||
print "within the $rootdir directory..\n" if ($rootdir);
|
||||
print "\n" unless ($rootdir);
|
||||
#print "url = $url\n";
|
||||
|
||||
# first try wget, then try lynx, then try curl
|
||||
|
||||
# this is my lame way of checking if a command succeeded AND getting
|
||||
# output from it. I'd love a better way. -alecf@netscape.com
|
||||
my $have_checkins = 0;
|
||||
open CHECKINS,"wget --quiet --output-document=- \"$url\"|" or
|
||||
die "Error opening wget: $!\n";
|
||||
|
||||
$header = <CHECKINS> and $have_checkins=1;
|
||||
|
||||
if (!$have_checkins) {
|
||||
|
||||
open CHECKINS, "lynx -source '$url'|" or die "Error opening lynx: $!\n";
|
||||
|
||||
$header = <CHECKINS> and $have_checkins = 1;
|
||||
}
|
||||
|
||||
if (!$have_checkins) {
|
||||
|
||||
open CHECKINS, "curl -s '$url'|" or die "Error opening curl $!\n";
|
||||
|
||||
$header = <CHECKINS> and $have_checkins = 1;
|
||||
}
|
||||
|
||||
$have_checkins || die "Couldn't get checkins\n";
|
||||
|
||||
open REALOUT, ">.fast-update.bonsai.html" || die "argh $!\n";
|
||||
print "Processing checkins...";
|
||||
while (<CHECKINS>) {
|
||||
print REALOUT $_;
|
||||
|
||||
if (/js_file_menu\((.*),\s*\'(.*)\'\s*,\s*(.*),\s*(.*),\s*(.*),\s*(.*)\)/) {
|
||||
my ($repos, $dir, $file, $rev, $branch, $event) =
|
||||
($1, $2, $3, $4, $5, $6);
|
||||
$dir =~ s/\/Attic$//;
|
||||
push @dirlist, $dir;
|
||||
}
|
||||
}
|
||||
|
||||
print "done.\n";
|
||||
close REALOUT;
|
||||
unlink '.fast-update.bonsai.html';
|
||||
|
||||
my $lastdir = "";
|
||||
my @uniquedirs;
|
||||
|
||||
foreach $dir (sort @dirlist) {
|
||||
next if ($lastdir eq $dir);
|
||||
|
||||
my $strippeddir = "";
|
||||
$lastdir = $dir;
|
||||
|
||||
# now strip out $rootdir
|
||||
if ($rootdir) {
|
||||
|
||||
# only deal with directories that start with $rootdir
|
||||
if (substr($dir, 0, (length $rootdir)) eq $rootdir) {
|
||||
|
||||
if ($dir eq $rootdir) {
|
||||
$strippeddir = ".";
|
||||
} else {
|
||||
$strippeddir = substr($dir,(length $rootdir) + 1 );
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
$strippeddir = $dir;
|
||||
}
|
||||
|
||||
if ($strippeddir) {
|
||||
push @uniquedirs, $strippeddir;
|
||||
}
|
||||
}
|
||||
|
||||
my $status = 0;
|
||||
if (scalar(@uniquedirs)) {
|
||||
print "Updating tree... (" . scalar(@uniquedirs) . " directories)\n";
|
||||
my $i=0;
|
||||
my $dirlist = "";
|
||||
foreach $dir (sort @uniquedirs) {
|
||||
if (!-d $dir) {
|
||||
cvs_up_parent($dir);
|
||||
}
|
||||
$dirlist .= "\"$dir\" ";
|
||||
$i++;
|
||||
if ($i == 5) {
|
||||
$status |= spawn("cvs -z3 -q -f up -l -d $dirlist\n");
|
||||
$dirlist = "";
|
||||
$i=0;
|
||||
}
|
||||
}
|
||||
if ($i) {
|
||||
$status |= spawn("cvs -z3 -q -f up -l -d $dirlist\n");
|
||||
}
|
||||
}
|
||||
else {
|
||||
print "No directories to update.\n";
|
||||
}
|
||||
|
||||
close CHECKINS;
|
||||
if ($status == 0) {
|
||||
set_last_update_time($filename, $start_time);
|
||||
print "successfully updated ";
|
||||
}
|
||||
else {
|
||||
print "error while updating ";
|
||||
}
|
||||
if ($module ne "all") {
|
||||
print "$module/";
|
||||
}
|
||||
if (scalar(@dirs) > 0) {
|
||||
print $dir_string;
|
||||
}
|
||||
print "\n";
|
||||
|
||||
exit $status;
|
||||
|
||||
sub cvs_up_parent {
|
||||
my ($dir) = @_;
|
||||
my $pdir = $dir;
|
||||
$pdir =~ s|/*[^/]*/*$||;
|
||||
#$pdir =~ s|/$||;
|
||||
#$pdir =~ s|[^/]*$||;
|
||||
#$pdir =~ s|/$||;
|
||||
if (!$pdir) {
|
||||
$pdir = '.';
|
||||
}
|
||||
if (!-d $pdir) {
|
||||
cvs_up_parent($pdir);
|
||||
}
|
||||
$status |= system "cvs -z3 -q -f up -d -l $pdir\n";
|
||||
}
|
||||
|
||||
sub get_hours_since_last_update {
|
||||
# get the last time this command was run
|
||||
my $last_time = get_last_update_time($filename);
|
||||
if (!defined($last_time)) {
|
||||
#
|
||||
# This must be the first use of fast-update.pl so use the timestamp
|
||||
# of a file that:
|
||||
# 1) is managed by cvs
|
||||
# 2) the user should not be tampering with
|
||||
# 3) that gets updated fairly frequently.
|
||||
#
|
||||
$last_time = (stat "CVS/Entries")[9];
|
||||
if (defined($last_time)) {
|
||||
$last_time -= 3600*24; # for safety go back a bit
|
||||
print "use fallback time of ".localtime($last_time)."\n";
|
||||
}
|
||||
}
|
||||
if(!defined($last_time)) {
|
||||
print "last_time not defined\n";
|
||||
}
|
||||
|
||||
# figure the hours (rounded up) since the last fast-update
|
||||
my $hours = int(($start_time - $last_time + 3600)/3600);
|
||||
print "last updated $hours hour(s) ago at ".localtime($last_time)."\n";
|
||||
return $hours;
|
||||
}
|
||||
|
||||
# returns time of last update if known
|
||||
sub get_last_update_time {
|
||||
my ($filename) = @_;
|
||||
if (!-r $filename) {
|
||||
return undef;
|
||||
}
|
||||
open FILE, "<$filename";
|
||||
my $line = <FILE>;
|
||||
if (!defined(line)) {
|
||||
return undef;
|
||||
}
|
||||
# print "line = $line";
|
||||
$line =~ /^(\d+):/;
|
||||
return $1;
|
||||
}
|
||||
|
||||
sub set_last_update_time {
|
||||
my ($filename, $time) = @_;
|
||||
my $time_str = localtime($time);
|
||||
open FILE, ">$filename";
|
||||
print FILE "$time: last fast-update.pl at ".localtime($time)."\n";
|
||||
}
|
||||
|
||||
# URL-encode data
|
||||
sub escape {
|
||||
my ($toencode) = @_;
|
||||
$toencode=~s/([^a-zA-Z0-9_.-])/uc sprintf("%%%02x",ord($1))/eg;
|
||||
return $toencode;
|
||||
}
|
||||
|
||||
sub spawn {
|
||||
my ($procname) = @_;
|
||||
return system "$procname";
|
||||
}
|
|
@ -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
|
||||
|
|
61
configure.in
61
configure.in
|
@ -1088,10 +1088,20 @@ case "$target" in
|
|||
dnl Use the specified value
|
||||
export MACOSX_DEPLOYMENT_TARGET=$_MACOSX_DEPLOYMENT_TARGET
|
||||
AC_DEFINE_UNQUOTED(__ENVIRONMENT_MAC_OS_X_VERION_MIN_REQUIRED__,$_MACOSX_DEPLOYMENT_TARGET)
|
||||
elif test -z "$MACOSX_DEPLOYMENT_TARGET" ; then
|
||||
else
|
||||
dnl No value specified on the command line or in the environment,
|
||||
dnl use architecture minimum.
|
||||
export MACOSX_DEPLOYMENT_TARGET=10.5
|
||||
case "${target_cpu}" in
|
||||
ppc*)
|
||||
export MACOSX_DEPLOYMENT_TARGET=10.5
|
||||
;;
|
||||
i*86)
|
||||
export MACOSX_DEPLOYMENT_TARGET=10.5
|
||||
;;
|
||||
x86_64)
|
||||
export MACOSX_DEPLOYMENT_TARGET=10.6
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
@ -3460,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 ========================================================
|
||||
|
@ -3524,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([],
|
||||
|
@ -4866,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
|
||||
|
@ -6299,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 ========================================================
|
||||
|
@ -6359,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 ========================================================
|
||||
|
@ -8716,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
|
||||
|
|
|
@ -390,6 +390,8 @@ GK_ATOM(form, "form")
|
|||
GK_ATOM(formaction, "formaction")
|
||||
GK_ATOM(format, "format")
|
||||
GK_ATOM(formatNumber, "format-number")
|
||||
GK_ATOM(formenctype, "formenctype")
|
||||
GK_ATOM(formmethod, "formmethod")
|
||||
GK_ATOM(formtarget, "formtarget")
|
||||
GK_ATOM(frame, "frame")
|
||||
GK_ATOM(frameborder, "frameborder")
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -239,7 +239,7 @@ private:
|
|||
* @param aFormSubmission the form submission object (out param)
|
||||
*/
|
||||
nsresult GetSubmissionFromForm(nsGenericHTMLElement* aForm,
|
||||
nsIContent* aOriginatingElement,
|
||||
nsGenericHTMLElement* aOriginatingElement,
|
||||
nsFormSubmission** aFormSubmission);
|
||||
|
||||
#endif /* nsIFormSubmission_h___ */
|
||||
|
|
|
@ -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__
|
||||
|
|
|
@ -803,7 +803,7 @@ GetEnumAttr(nsGenericHTMLElement* aContent,
|
|||
|
||||
nsresult
|
||||
GetSubmissionFromForm(nsGenericHTMLElement* aForm,
|
||||
nsIContent* aOriginatingElement,
|
||||
nsGenericHTMLElement* aOriginatingElement,
|
||||
nsFormSubmission** aFormSubmission)
|
||||
{
|
||||
// Get all the information necessary to encode the form data
|
||||
|
@ -812,11 +812,21 @@ GetSubmissionFromForm(nsGenericHTMLElement* aForm,
|
|||
|
||||
// Get encoding type (default: urlencoded)
|
||||
PRInt32 enctype = NS_FORM_ENCTYPE_URLENCODED;
|
||||
GetEnumAttr(aForm, nsGkAtoms::enctype, &enctype);
|
||||
if (aOriginatingElement &&
|
||||
aOriginatingElement->HasAttr(kNameSpaceID_None, nsGkAtoms::formenctype)) {
|
||||
GetEnumAttr(aOriginatingElement, nsGkAtoms::formenctype, &enctype);
|
||||
} else {
|
||||
GetEnumAttr(aForm, nsGkAtoms::enctype, &enctype);
|
||||
}
|
||||
|
||||
// Get method (default: GET)
|
||||
PRInt32 method = NS_FORM_METHOD_GET;
|
||||
GetEnumAttr(aForm, nsGkAtoms::method, &method);
|
||||
if (aOriginatingElement &&
|
||||
aOriginatingElement->HasAttr(kNameSpaceID_None, nsGkAtoms::formmethod)) {
|
||||
GetEnumAttr(aOriginatingElement, nsGkAtoms::formmethod, &method);
|
||||
} else {
|
||||
GetEnumAttr(aForm, nsGkAtoms::method, &method);
|
||||
}
|
||||
|
||||
// Get charset
|
||||
nsCAutoString charset;
|
||||
|
@ -834,7 +844,14 @@ GetSubmissionFromForm(nsGenericHTMLElement* aForm,
|
|||
if (enctype == NS_FORM_ENCTYPE_MULTIPART ||
|
||||
enctype == NS_FORM_ENCTYPE_TEXTPLAIN) {
|
||||
nsAutoString enctypeStr;
|
||||
aForm->GetAttr(kNameSpaceID_None, nsGkAtoms::enctype, enctypeStr);
|
||||
if (aOriginatingElement &&
|
||||
aOriginatingElement->HasAttr(kNameSpaceID_None,
|
||||
nsGkAtoms::formenctype)) {
|
||||
aOriginatingElement->GetAttr(kNameSpaceID_None, nsGkAtoms::formenctype,
|
||||
enctypeStr);
|
||||
} else {
|
||||
aForm->GetAttr(kNameSpaceID_None, nsGkAtoms::enctype, enctypeStr);
|
||||
}
|
||||
const PRUnichar* enctypeStrPtr = enctypeStr.get();
|
||||
SendJSWarning(doc, "ForgotPostWarning",
|
||||
&enctypeStrPtr, 1);
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
|
@ -11,19 +12,18 @@
|
|||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla.
|
||||
* 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) 2006
|
||||
* 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):
|
||||
* Axel Hecht <axel@pike.org>
|
||||
* Mounir Lamouri <mounir.lamouri@mozilla.com> (original author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* 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
|
||||
|
@ -35,6 +35,25 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
view.init();
|
||||
controller.addLocales(keys(tierMap));
|
||||
controller.loaded();
|
||||
#ifndef nsFormSubmissionConstants_h__
|
||||
#define nsFormSubmissionConstants_h__
|
||||
|
||||
static const nsAttrValue::EnumTable kFormMethodTable[] = {
|
||||
{ "get", NS_FORM_METHOD_GET },
|
||||
{ "post", NS_FORM_METHOD_POST },
|
||||
{ 0 }
|
||||
};
|
||||
// Default method is 'get'.
|
||||
static const nsAttrValue::EnumTable* kFormDefaultMethod = &kFormMethodTable[0];
|
||||
|
||||
static const nsAttrValue::EnumTable kFormEnctypeTable[] = {
|
||||
{ "multipart/form-data", NS_FORM_ENCTYPE_MULTIPART },
|
||||
{ "application/x-www-form-urlencoded", NS_FORM_ENCTYPE_URLENCODED },
|
||||
{ "text/plain", NS_FORM_ENCTYPE_TEXTPLAIN },
|
||||
{ 0 }
|
||||
};
|
||||
// Default method is 'application/x-www-form-urlencoded'.
|
||||
static const nsAttrValue::EnumTable* kFormDefaultEnctype = &kFormEnctypeTable[1];
|
||||
|
||||
#endif // nsFormSubmissionConstants_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,
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include "nsIFormControl.h"
|
||||
#include "nsIForm.h"
|
||||
#include "nsFormSubmission.h"
|
||||
#include "nsFormSubmissionConstants.h"
|
||||
#include "nsIURL.h"
|
||||
|
||||
#include "nsIFrame.h"
|
||||
|
@ -61,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)
|
||||
|
@ -78,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);
|
||||
|
@ -132,8 +133,8 @@ public:
|
|||
virtual void DoneCreatingElement();
|
||||
virtual nsXPCClassInfo* GetClassInfo();
|
||||
|
||||
// nsConstraintValidation
|
||||
PRBool IsBarredFromConstraintValidation();
|
||||
// nsIConstraintValidation
|
||||
PRBool IsBarredFromConstraintValidation() const;
|
||||
|
||||
protected:
|
||||
virtual PRBool AcceptAutofocus() const
|
||||
|
@ -182,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
|
||||
|
||||
|
@ -209,6 +211,10 @@ NS_IMPL_STRING_ATTR(nsHTMLButtonElement, AccessKey, accesskey)
|
|||
NS_IMPL_BOOL_ATTR(nsHTMLButtonElement, Autofocus, autofocus)
|
||||
NS_IMPL_BOOL_ATTR(nsHTMLButtonElement, Disabled, disabled)
|
||||
NS_IMPL_STRING_ATTR(nsHTMLButtonElement, FormAction, formaction)
|
||||
NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLButtonElement, FormEnctype, formenctype,
|
||||
kFormDefaultEnctype->tag)
|
||||
NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLButtonElement, FormMethod, formmethod,
|
||||
kFormDefaultMethod->tag)
|
||||
NS_IMPL_STRING_ATTR(nsHTMLButtonElement, FormTarget, formtarget)
|
||||
NS_IMPL_STRING_ATTR(nsHTMLButtonElement, Name, name)
|
||||
NS_IMPL_INT_ATTR_DEFAULT_VALUE(nsHTMLButtonElement, TabIndex, tabindex, 0)
|
||||
|
@ -285,17 +291,26 @@ nsHTMLButtonElement::ParseAttribute(PRInt32 aNamespaceID,
|
|||
const nsAString& aValue,
|
||||
nsAttrValue& aResult)
|
||||
{
|
||||
if (aAttribute == nsGkAtoms::type && kNameSpaceID_None == aNamespaceID) {
|
||||
// XXX ARG!! This is major evilness. ParseAttribute
|
||||
// shouldn't set members. Override SetAttr instead
|
||||
PRBool success = aResult.ParseEnumValue(aValue, kButtonTypeTable, PR_FALSE);
|
||||
if (success) {
|
||||
mType = aResult.GetEnumValue();
|
||||
} else {
|
||||
mType = kButtonDefaultType->value;
|
||||
if (aNamespaceID == kNameSpaceID_None) {
|
||||
if (aAttribute == nsGkAtoms::type) {
|
||||
// XXX ARG!! This is major evilness. ParseAttribute
|
||||
// shouldn't set members. Override SetAttr instead
|
||||
PRBool success = aResult.ParseEnumValue(aValue, kButtonTypeTable, PR_FALSE);
|
||||
if (success) {
|
||||
mType = aResult.GetEnumValue();
|
||||
} else {
|
||||
mType = kButtonDefaultType->value;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
return success;
|
||||
if (aAttribute == nsGkAtoms::formmethod) {
|
||||
return aResult.ParseEnumValue(aValue, kFormMethodTable, PR_FALSE);
|
||||
}
|
||||
if (aAttribute == nsGkAtoms::formenctype) {
|
||||
return aResult.ParseEnumValue(aValue, kFormEnctypeTable, PR_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
|
||||
|
@ -597,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,
|
||||
|
@ -637,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)
|
||||
|
||||
|
|
|
@ -65,6 +65,7 @@
|
|||
#include "nsIWebProgress.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsFormData.h"
|
||||
#include "nsFormSubmissionConstants.h"
|
||||
|
||||
// radio buttons
|
||||
#include "nsIDOMHTMLInputElement.h"
|
||||
|
@ -78,25 +79,10 @@
|
|||
#include "mozAutoDocUpdate.h"
|
||||
#include "nsIHTMLCollection.h"
|
||||
|
||||
#include "nsIConstraintValidation.h"
|
||||
|
||||
static const int NS_FORM_CONTROL_LIST_HASHTABLE_SIZE = 16;
|
||||
|
||||
static const nsAttrValue::EnumTable kFormMethodTable[] = {
|
||||
{ "get", NS_FORM_METHOD_GET },
|
||||
{ "post", NS_FORM_METHOD_POST },
|
||||
{ 0 }
|
||||
};
|
||||
// Default method is 'get'.
|
||||
static const nsAttrValue::EnumTable* kFormDefaultMethod = &kFormMethodTable[0];
|
||||
|
||||
static const nsAttrValue::EnumTable kFormEnctypeTable[] = {
|
||||
{ "multipart/form-data", NS_FORM_ENCTYPE_MULTIPART },
|
||||
{ "application/x-www-form-urlencoded", NS_FORM_ENCTYPE_URLENCODED },
|
||||
{ "text/plain", NS_FORM_ENCTYPE_TEXTPLAIN },
|
||||
{ 0 }
|
||||
};
|
||||
// Default method is 'application/x-www-form-urlencoded'.
|
||||
static const nsAttrValue::EnumTable* kFormDefaultEnctype = &kFormEnctypeTable[1];
|
||||
|
||||
// nsHTMLFormElement
|
||||
|
||||
PRBool nsHTMLFormElement::gFirstFormSubmitted = PR_FALSE;
|
||||
|
@ -421,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,
|
||||
|
@ -695,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!");
|
||||
|
@ -704,7 +707,11 @@ nsHTMLFormElement::DoSubmit(nsEvent* aEvent)
|
|||
//
|
||||
// prepare the submission object
|
||||
//
|
||||
BuildSubmission(getter_Transfers(submission), aEvent);
|
||||
nsresult rv = BuildSubmission(getter_Transfers(submission), aEvent);
|
||||
if (NS_FAILED(rv)) {
|
||||
mIsSubmitting = PR_FALSE;
|
||||
return rv;
|
||||
}
|
||||
|
||||
// XXXbz if the script global is that for an sXBL/XBL2 doc, it won't
|
||||
// be a window...
|
||||
|
@ -741,10 +748,17 @@ nsHTMLFormElement::BuildSubmission(nsFormSubmission** aFormSubmission,
|
|||
NS_ASSERTION(!mPendingSubmission, "tried to build two submissions!");
|
||||
|
||||
// Get the originating frame (failure is non-fatal)
|
||||
nsIContent *originatingElement = nsnull;
|
||||
nsGenericHTMLElement* originatingElement = nsnull;
|
||||
if (aEvent) {
|
||||
if (NS_FORM_EVENT == aEvent->eventStructType) {
|
||||
originatingElement = ((nsFormEvent *)aEvent)->originator;
|
||||
nsIContent* originator = ((nsFormEvent *)aEvent)->originator;
|
||||
if (originator) {
|
||||
if (!originator->IsHTML()) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
originatingElement =
|
||||
static_cast<nsGenericHTMLElement*>(((nsFormEvent *)aEvent)->originator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1191,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
|
||||
|
@ -1542,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
|
||||
|
|
|
@ -57,6 +57,7 @@
|
|||
#include "nsIFormControl.h"
|
||||
#include "nsIForm.h"
|
||||
#include "nsFormSubmission.h"
|
||||
#include "nsFormSubmissionConstants.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsIFormControlFrame.h"
|
||||
|
@ -296,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,
|
||||
|
@ -304,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
|
||||
|
||||
|
@ -386,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) {
|
||||
|
@ -409,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.
|
||||
|
@ -448,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
|
||||
|
@ -491,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -552,6 +562,10 @@ NS_IMPL_BOOL_ATTR(nsHTMLInputElement, Autofocus, autofocus)
|
|||
//NS_IMPL_BOOL_ATTR(nsHTMLInputElement, Checked, checked)
|
||||
NS_IMPL_BOOL_ATTR(nsHTMLInputElement, Disabled, disabled)
|
||||
NS_IMPL_STRING_ATTR(nsHTMLInputElement, FormAction, formaction)
|
||||
NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLInputElement, FormEnctype, formenctype,
|
||||
kFormDefaultEnctype->tag)
|
||||
NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLInputElement, FormMethod, formmethod,
|
||||
kFormDefaultMethod->tag)
|
||||
NS_IMPL_STRING_ATTR(nsHTMLInputElement, FormTarget, formtarget)
|
||||
NS_IMPL_BOOL_ATTR(nsHTMLInputElement, Multiple, multiple)
|
||||
NS_IMPL_NON_NEGATIVE_INT_ATTR(nsHTMLInputElement, MaxLength, maxlength)
|
||||
|
@ -887,8 +901,9 @@ nsHTMLInputElement::SetFileNames(const nsTArray<nsString>& aFileNames)
|
|||
}
|
||||
|
||||
UpdateFileList();
|
||||
|
||||
|
||||
SetValueChanged(PR_TRUE);
|
||||
UpdateAllValidityStates(PR_TRUE);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1081,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;
|
||||
|
@ -1089,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;
|
||||
|
@ -1113,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;
|
||||
}
|
||||
|
||||
|
@ -1206,7 +1223,7 @@ nsHTMLInputElement::MaybeSubmitForm(nsPresContext* aPresContext)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
void
|
||||
nsHTMLInputElement::SetCheckedInternal(PRBool aChecked, PRBool aNotify)
|
||||
{
|
||||
//
|
||||
|
@ -1234,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -2017,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;
|
||||
}
|
||||
|
||||
|
@ -2029,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
|
||||
|
@ -2063,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
|
||||
|
@ -2145,6 +2182,12 @@ nsHTMLInputElement::ParseAttribute(PRInt32 aNamespaceID,
|
|||
if (aAttribute == nsGkAtoms::align) {
|
||||
return ParseAlignValue(aValue, aResult);
|
||||
}
|
||||
if (aAttribute == nsGkAtoms::formmethod) {
|
||||
return aResult.ParseEnumValue(aValue, kFormMethodTable, PR_FALSE);
|
||||
}
|
||||
if (aAttribute == nsGkAtoms::formenctype) {
|
||||
return aResult.ParseEnumValue(aValue, kFormEnctypeTable, PR_FALSE);
|
||||
}
|
||||
if (ParseImageAttribute(aAttribute, aValue, aResult)) {
|
||||
// We have to call |ParseImageAttribute| unconditionally since we
|
||||
// don't know if we're going to have a type="image" attribute yet,
|
||||
|
@ -2749,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;
|
||||
}
|
||||
|
||||
|
@ -2864,7 +2911,7 @@ nsHTMLInputElement::AddedToRadioGroup(PRBool aNotify)
|
|||
}
|
||||
|
||||
void
|
||||
nsHTMLInputElement::WillRemoveFromRadioGroup()
|
||||
nsHTMLInputElement::WillRemoveFromRadioGroup(PRBool aNotify)
|
||||
{
|
||||
//
|
||||
// If the input element is not in a form and
|
||||
|
@ -2893,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);
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -3125,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()
|
||||
|
@ -3140,7 +3207,7 @@ nsHTMLInputElement::IsTooLong()
|
|||
GetMaxLength(&maxLength);
|
||||
GetTextLength(&textLength);
|
||||
|
||||
return (maxLength >= 0) && (textLength > maxLength);
|
||||
return maxLength >= 0 && textLength > maxLength;
|
||||
}
|
||||
|
||||
PRBool
|
||||
|
@ -3157,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
|
||||
|
@ -3228,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;
|
||||
}
|
||||
|
||||
|
@ -3248,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 ||
|
||||
|
@ -3259,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;
|
||||
|
@ -3286,7 +3391,7 @@ nsHTMLInputElement::GetValidationMessage(nsAString& aValidationMessage,
|
|||
aValidationMessage = message;
|
||||
break;
|
||||
}
|
||||
case VALIDATION_MESSAGE_VALUE_MISSING:
|
||||
case VALIDITY_STATE_VALUE_MISSING:
|
||||
{
|
||||
nsXPIDLString message;
|
||||
nsCAutoString key;
|
||||
|
@ -3309,7 +3414,7 @@ nsHTMLInputElement::GetValidationMessage(nsAString& aValidationMessage,
|
|||
aValidationMessage = message;
|
||||
break;
|
||||
}
|
||||
case VALIDATION_MESSAGE_TYPE_MISMATCH:
|
||||
case VALIDITY_STATE_TYPE_MISMATCH:
|
||||
{
|
||||
nsXPIDLString message;
|
||||
nsCAutoString key;
|
||||
|
@ -3325,7 +3430,7 @@ nsHTMLInputElement::GetValidationMessage(nsAString& aValidationMessage,
|
|||
aValidationMessage = message;
|
||||
break;
|
||||
}
|
||||
case VALIDATION_MESSAGE_PATTERN_MISMATCH:
|
||||
case VALIDITY_STATE_PATTERN_MISMATCH:
|
||||
{
|
||||
nsXPIDLString message;
|
||||
nsAutoString title;
|
||||
|
@ -3344,7 +3449,7 @@ nsHTMLInputElement::GetValidationMessage(nsAString& aValidationMessage,
|
|||
break;
|
||||
}
|
||||
default:
|
||||
rv = nsConstraintValidation::GetValidationMessage(aValidationMessage, aType);
|
||||
rv = nsIConstraintValidation::GetValidationMessage(aValidationMessage, aType);
|
||||
}
|
||||
|
||||
return rv;
|
||||
|
@ -3546,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)
|
||||
|
@ -3616,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
|
||||
{
|
||||
|
@ -3714,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
|
||||
|
|
|
@ -200,6 +200,11 @@ _TEST_FILES = \
|
|||
test_bug345512.html \
|
||||
test_bug566064.html \
|
||||
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>
|
||||
|
|
|
@ -18,7 +18,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=535043
|
|||
<textarea maxlength="-1"></textarea>
|
||||
<textarea maxlength="0"></textarea>
|
||||
<textarea maxlength="2"></textarea>
|
||||
<textarea maxlength="257"></textarea>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="text/javascript">
|
||||
|
@ -27,7 +26,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=535043
|
|||
function checkTextArea(textArea) {
|
||||
textArea.value = '';
|
||||
textArea.focus();
|
||||
for (var j = 0; j < 259; j++) {
|
||||
for (var j = 0; j < 3; j++) {
|
||||
synthesizeKey('x', {});
|
||||
}
|
||||
var htmlMaxLength = textArea.getAttribute('maxlength');
|
||||
|
@ -45,7 +44,7 @@ function checkTextArea(textArea) {
|
|||
'maxlength in DOM does not match provided value');
|
||||
}
|
||||
if (textArea.maxLength == -1) {
|
||||
is(textArea.value.length, 259,
|
||||
is(textArea.value.length, 3,
|
||||
'textarea with maxLength -1 should have no length limit');
|
||||
} else {
|
||||
is(textArea.value.length, textArea.maxLength, 'textarea has maxLength ' +
|
||||
|
@ -60,7 +59,7 @@ SimpleTest.waitForFocus(function() {
|
|||
}
|
||||
|
||||
textArea = textAreas[0];
|
||||
testNums = [-42, -1, 0, 2, 257];
|
||||
testNums = [-42, -1, 0, 2];
|
||||
for (var i = 0; i < testNums.length; i++) {
|
||||
textArea.removeAttribute('maxlength');
|
||||
|
||||
|
@ -80,7 +79,12 @@ SimpleTest.waitForFocus(function() {
|
|||
textArea.setAttribute('maxlength', testNums[i]);
|
||||
checkTextArea(textArea);
|
||||
}
|
||||
|
||||
SimpleTest.finish();
|
||||
});
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -0,0 +1,207 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=566160
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 566160</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"/>
|
||||
</head>
|
||||
<body onload="setTimeout(runTests);">
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=566160">Mozilla Bug 566160</a>
|
||||
<p id="display"></p>
|
||||
<style>
|
||||
iframe { width: 130px; height: 100px;}
|
||||
</style>
|
||||
<iframe name='frame1' id='frame1'></iframe>
|
||||
<iframe name='frame2' id='frame2'></iframe>
|
||||
<iframe name='frame3' id='frame3'></iframe>
|
||||
<iframe name='frame3bis' id='frame3bis'></iframe>
|
||||
<iframe name='frame4' id='frame4'></iframe>
|
||||
<iframe name='frame5' id='frame5'></iframe>
|
||||
<iframe name='frame6' id='frame6'></iframe>
|
||||
<iframe name='frame7' id='frame7'></iframe>
|
||||
<iframe name='frame8' id='frame8'></iframe>
|
||||
<iframe name='frame9' id='frame9'></iframe>
|
||||
<div id="content">
|
||||
<!-- submit controls with formaction that are validated with a CLICK -->
|
||||
<form target="frame1" action="data:text/html," method="POST">
|
||||
<input name='foo' value='foo'>
|
||||
<input type='submit' id='is' formmethod="GET">
|
||||
</form>
|
||||
<form target="frame2" action="data:text/html," method="POST">
|
||||
<input name='bar' value='bar'>
|
||||
<input type='image' id='ii' formmethod="GET">
|
||||
</form>
|
||||
<form target="frame3" action="data:text/html," method="POST">
|
||||
<input name='tulip' value='tulip'>
|
||||
<button type='submit' id='bs' formmethod="GET">submit</button>
|
||||
</form>
|
||||
<form target="frame3bis" action="data:text/html," method="POST">
|
||||
<input name='tulipbis' value='tulipbis'>
|
||||
<button type='submit' id='bsbis' formmethod="GET">submit</button>
|
||||
</form>
|
||||
|
||||
<!-- submit controls with formaction that are validated with ENTER -->
|
||||
<form target="frame4" action="data:text/html," method="POST">
|
||||
<input name='footulip' value='footulip'>
|
||||
<input type='submit' id='is2' formmethod="GET">
|
||||
</form>
|
||||
<form target="frame5" action="data:text/html," method="POST">
|
||||
<input name='foobar' value='foobar'>
|
||||
<input type='image' id='ii2' formmethod="GET">
|
||||
</form>
|
||||
<form target="frame6" action="data:text/html," method="POST">
|
||||
<input name='tulip2' value='tulip2'>
|
||||
<button type='submit' id='bs2' formmethod="GET">submit</button>
|
||||
</form>
|
||||
|
||||
<!-- check that when submitting a from from an element
|
||||
which is not a submit control, @formaction isn't used -->
|
||||
<form target='frame7' action="data:text/html," method="GET">
|
||||
<input id='enter' name='input' value='enter' formmethod="POST">
|
||||
</form>
|
||||
|
||||
<!-- If formmethod isn't set, it's default value shouldn't be used -->
|
||||
<form target="frame8" action="data:text/html," method="POST">
|
||||
<input name='tulip8' value='tulip8'>
|
||||
<input type='submit' id='i8'>
|
||||
</form>
|
||||
|
||||
<!-- If formmethod is set but has an invalid value, the default value should
|
||||
be used. -->
|
||||
<form target="frame9" action="data:text/html," method="POST">
|
||||
<input name='tulip9' value='tulip9'>
|
||||
<input type='submit' id='i9' formmethod="">
|
||||
</form>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 566160 **/
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var gTestResults = {
|
||||
frame1: "data:text/html,?foo=foo",
|
||||
frame2: "data:text/html,?bar=bar&x=0&y=0",
|
||||
frame3: "data:text/html,?tulip=tulip",
|
||||
frame3bis: "data:text/html,?tulipbis=tulipbis",
|
||||
frame4: "data:text/html,?footulip=footulip",
|
||||
frame5: "data:text/html,?foobar=foobar&x=0&y=0",
|
||||
frame6: "data:text/html,?tulip2=tulip2",
|
||||
frame7: "data:text/html,?input=enter",
|
||||
frame8: "data:text/html,",
|
||||
frame9: "data:text/html,?tulip9=tulip9",
|
||||
};
|
||||
|
||||
var gPendingLoad = 0; // Has to be set after depending on the frames number.
|
||||
|
||||
function runTests()
|
||||
{
|
||||
// We add a load event for the frames which will be called when the forms
|
||||
// will be submitted.
|
||||
var frames = [ document.getElementById('frame1'),
|
||||
document.getElementById('frame2'),
|
||||
document.getElementById('frame3'),
|
||||
document.getElementById('frame3bis'),
|
||||
document.getElementById('frame4'),
|
||||
document.getElementById('frame5'),
|
||||
document.getElementById('frame6'),
|
||||
document.getElementById('frame7'),
|
||||
document.getElementById('frame8'),
|
||||
document.getElementById('frame9'),
|
||||
];
|
||||
gPendingLoad = frames.length;
|
||||
|
||||
for (var i=0; i<frames.length; i++) {
|
||||
frames[i].setAttribute('onload', "frameLoaded(this);");
|
||||
}
|
||||
|
||||
/**
|
||||
* We are going to focus each element before interacting with either for
|
||||
* simulating the ENTER key (synthesizeKey) or a click (synthesizeMouse) or
|
||||
* using .click(). This because it may be needed (ENTER) and because we want
|
||||
* to have the element visible in the iframe.
|
||||
*
|
||||
* Focusing the first element (id='is') is launching the tests.
|
||||
*/
|
||||
document.getElementById('is').addEventListener('focus', function(aEvent) {
|
||||
aEvent.target.removeEventListener('focus', arguments.callee, false);
|
||||
synthesizeMouse(document.getElementById('is'), 5, 5, {});
|
||||
document.getElementById('ii').focus();
|
||||
}, false);
|
||||
|
||||
document.getElementById('ii').addEventListener('focus', function(aEvent) {
|
||||
aEvent.target.removeEventListener('focus', arguments.callee, false);
|
||||
synthesizeMouse(document.getElementById('ii'), 5, 5, {});
|
||||
document.getElementById('bs').focus();
|
||||
}, false);
|
||||
|
||||
document.getElementById('bs').addEventListener('focus', function(aEvent) {
|
||||
aEvent.target.removeEventListener('focus', arguments.callee, false);
|
||||
synthesizeMouse(document.getElementById('bs'), 5, 5, {});
|
||||
document.getElementById('bsbis').focus();
|
||||
}, false);
|
||||
|
||||
document.getElementById('bsbis').addEventListener('focus', function(aEvent) {
|
||||
aEvent.target.removeEventListener('focus', arguments.callee, false);
|
||||
document.getElementById('bsbis').click();
|
||||
document.getElementById('is2').focus();
|
||||
}, false);
|
||||
|
||||
document.getElementById('is2').addEventListener('focus', function(aEvent) {
|
||||
aEvent.target.removeEventListener('focus', arguments.callee, false);
|
||||
synthesizeKey("VK_RETURN", {});
|
||||
document.getElementById('ii2').focus();
|
||||
}, false);
|
||||
|
||||
document.getElementById('ii2').addEventListener('focus', function(aEvent) {
|
||||
aEvent.target.removeEventListener('focus', arguments.callee, false);
|
||||
synthesizeKey("VK_RETURN", {});
|
||||
document.getElementById('bs2').focus();
|
||||
}, false);
|
||||
|
||||
document.getElementById('bs2').addEventListener('focus', function(aEvent) {
|
||||
aEvent.target.removeEventListener('focus', arguments.callee, false);
|
||||
synthesizeKey("VK_RETURN", {});
|
||||
document.getElementById('enter').focus();
|
||||
}, false);
|
||||
|
||||
document.getElementById('enter').addEventListener('focus', function(aEvent) {
|
||||
aEvent.target.removeEventListener('focus', arguments.callee, false);
|
||||
synthesizeKey("VK_RETURN", {});
|
||||
document.getElementById('i8').focus();
|
||||
}, false);
|
||||
|
||||
document.getElementById('i8').addEventListener('focus', function(aEvent) {
|
||||
aEvent.target.removeEventListener('focus', arguments.callee, false);
|
||||
synthesizeKey("VK_RETURN", {});
|
||||
document.getElementById('i9').focus();
|
||||
}, false);
|
||||
|
||||
document.getElementById('i9').addEventListener('focus', function(aEvent) {
|
||||
aEvent.target.removeEventListener('focus', arguments.callee, false);
|
||||
synthesizeKey("VK_RETURN", {});
|
||||
}, false);
|
||||
|
||||
document.getElementById('is').focus();
|
||||
}
|
||||
|
||||
function frameLoaded(aFrame) {
|
||||
// Check if formaction/action has the correct behavior.
|
||||
is(aFrame.contentWindow.location.href, gTestResults[aFrame.name],
|
||||
"the method/formmethod attribute doesn't have the correct behavior");
|
||||
|
||||
if (--gPendingLoad == 0) {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,206 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=566160
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 566160</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"/>
|
||||
</head>
|
||||
<body onload="setTimeout(runTests);">
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=566160">Mozilla Bug 566160</a>
|
||||
<p id="display"></p>
|
||||
<style>
|
||||
iframe { width: 130px; height: 100px;}
|
||||
</style>
|
||||
<iframe name='frame1' id='frame1'></iframe>
|
||||
<iframe name='frame2' id='frame2'></iframe>
|
||||
<iframe name='frame3' id='frame3'></iframe>
|
||||
<iframe name='frame3bis' id='frame3bis'></iframe>
|
||||
<iframe name='frame4' id='frame4'></iframe>
|
||||
<iframe name='frame5' id='frame5'></iframe>
|
||||
<iframe name='frame6' id='frame6'></iframe>
|
||||
<iframe name='frame7' id='frame7'></iframe>
|
||||
<iframe name='frame8' id='frame8'></iframe>
|
||||
<iframe name='frame9' id='frame9'></iframe>
|
||||
<div id="content">
|
||||
<!-- submit controls with formaction that are validated with a CLICK -->
|
||||
<form target="frame1" action="form_submit_server.sjs" method="POST">
|
||||
<input name='foo' value='foo'>
|
||||
<input type='submit' id='is' formenctype='multipart/form-data'>
|
||||
</form>
|
||||
<form target="frame2" action="form_submit_server.sjs" method="POST">
|
||||
<input name='bar' value='bar'>
|
||||
<input type='image' id='ii' formenctype='multipart/form-data'>
|
||||
</form>
|
||||
<form target="frame3" action="form_submit_server.sjs" method="POST">
|
||||
<input name='tulip' value='tulip'>
|
||||
<button type='submit' id='bs' formenctype="multipart/form-data">submit</button>
|
||||
</form>
|
||||
<form target="frame3bis" action="form_submit_server.sjs" method="POST">
|
||||
<input name='tulipbis' value='tulipbis'>
|
||||
<button type='submit' id='bsbis' formenctype="multipart/form-data">submit</button>
|
||||
</form>
|
||||
|
||||
<!-- submit controls with formaction that are validated with ENTER -->
|
||||
<form target="frame4" action="form_submit_server.sjs" method="POST">
|
||||
<input name='footulip' value='footulip'>
|
||||
<input type='submit' id='is2' formenctype="multipart/form-data">
|
||||
</form>
|
||||
<form target="frame5" action="form_submit_server.sjs" method="POST">
|
||||
<input name='foobar' value='foobar'>
|
||||
<input type='image' id='ii2' formenctype="multipart/form-data">
|
||||
</form>
|
||||
<form target="frame6" action="form_submit_server.sjs" method="POST">
|
||||
<input name='tulip2' value='tulip2'>
|
||||
<button type='submit' id='bs2' formenctype="multipart/form-data">submit</button>
|
||||
</form>
|
||||
|
||||
<!-- check that when submitting a from from an element
|
||||
which is not a submit control, @formaction isn't used -->
|
||||
<form target='frame7' action="form_submit_server.sjs" method="POST">
|
||||
<input id='enter' name='input' value='enter' formenctype="multipart/form-data">
|
||||
</form>
|
||||
|
||||
<!-- If formenctype isn't set, it's default value shouldn't be used -->
|
||||
<form target="frame8" action="form_submit_server.sjs" method="POST" enctype="multipart/form-data">
|
||||
<input name='tulip8' value='tulip8'>
|
||||
<input type='submit' id='i8'>
|
||||
</form>
|
||||
|
||||
<!-- If formenctype is set but has an invalid value, the default value should
|
||||
be used. -->
|
||||
<form target="frame9" action="form_submit_server.sjs" method="POST" enctype="multipart/form-data">
|
||||
<input name='tulip9' value='tulip9'>
|
||||
<input type='submit' id='i9' formenctype="">
|
||||
</form>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 566160 **/
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
var gTestResults = {
|
||||
frame1: '[{\"headers\":{\"Content-Disposition\":\"form-data; name=\\\"foo\\\"\"},\"body\":\"foo\"}]',
|
||||
frame2: '[{\"headers\":{\"Content-Disposition\":\"form-data; name=\\\"bar\\\"\"},\"body\":\"bar\"},{\"headers\":{\"Content-Disposition\":\"form-data; name=\\\"x\\\"\"},\"body\":\"0\"},{\"headers\":{\"Content-Disposition\":\"form-data; name=\\\"y\\\"\"},\"body\":\"0\"}]',
|
||||
frame3: '[{\"headers\":{\"Content-Disposition\":\"form-data; name=\\\"tulip\\\"\"},\"body\":\"tulip\"}]',
|
||||
frame3bis: '[{\"headers\":{\"Content-Disposition\":\"form-data; name=\\\"tulipbis\\\"\"},\"body\":\"tulipbis\"}]',
|
||||
frame4: '[{\"headers\":{\"Content-Disposition\":\"form-data; name=\\\"footulip\\\"\"},\"body\":\"footulip\"}]',
|
||||
frame5: '[{\"headers\":{\"Content-Disposition\":\"form-data; name=\\\"foobar\\\"\"},\"body\":\"foobar\"},{\"headers\":{\"Content-Disposition\":\"form-data; name=\\\"x\\\"\"},\"body\":\"0\"},{\"headers\":{\"Content-Disposition\":\"form-data; name=\\\"y\\\"\"},\"body\":\"0\"}]',
|
||||
frame6: '[{\"headers\":{\"Content-Disposition\":\"form-data; name=\\\"tulip2\\\"\"},\"body\":\"tulip2\"}]',
|
||||
frame7: '[]',
|
||||
frame8: '[{\"headers\":{\"Content-Disposition\":\"form-data; name=\\\"tulip8\\\"\"},\"body\":\"tulip8\"}]',
|
||||
frame9: '[]',
|
||||
};
|
||||
|
||||
var gPendingLoad = 0; // Has to be set after depending on the frames number.
|
||||
|
||||
function runTests()
|
||||
{
|
||||
// We add a load event for the frames which will be called when the forms
|
||||
// will be submitted.
|
||||
var frames = [ document.getElementById('frame1'),
|
||||
document.getElementById('frame2'),
|
||||
document.getElementById('frame3'),
|
||||
document.getElementById('frame3bis'),
|
||||
document.getElementById('frame4'),
|
||||
document.getElementById('frame5'),
|
||||
document.getElementById('frame6'),
|
||||
document.getElementById('frame7'),
|
||||
document.getElementById('frame8'),
|
||||
document.getElementById('frame9'),
|
||||
];
|
||||
gPendingLoad = frames.length;
|
||||
|
||||
for (var i=0; i<frames.length; i++) {
|
||||
frames[i].setAttribute('onload', "frameLoaded(this);");
|
||||
}
|
||||
|
||||
/**
|
||||
* We are going to focus each element before interacting with either for
|
||||
* simulating the ENTER key (synthesizeKey) or a click (synthesizeMouse) or
|
||||
* using .click(). This because it may be needed (ENTER) and because we want
|
||||
* to have the element visible in the iframe.
|
||||
*
|
||||
* Focusing the first element (id='is') is launching the tests.
|
||||
*/
|
||||
document.getElementById('is').addEventListener('focus', function(aEvent) {
|
||||
aEvent.target.removeEventListener('focus', arguments.callee, false);
|
||||
synthesizeMouse(document.getElementById('is'), 5, 5, {});
|
||||
document.getElementById('ii').focus();
|
||||
}, false);
|
||||
|
||||
document.getElementById('ii').addEventListener('focus', function(aEvent) {
|
||||
aEvent.target.removeEventListener('focus', arguments.callee, false);
|
||||
synthesizeMouse(document.getElementById('ii'), 5, 5, {});
|
||||
document.getElementById('bs').focus();
|
||||
}, false);
|
||||
|
||||
document.getElementById('bs').addEventListener('focus', function(aEvent) {
|
||||
aEvent.target.removeEventListener('focus', arguments.callee, false);
|
||||
synthesizeMouse(document.getElementById('bs'), 5, 5, {});
|
||||
document.getElementById('bsbis').focus();
|
||||
}, false);
|
||||
|
||||
document.getElementById('bsbis').addEventListener('focus', function(aEvent) {
|
||||
aEvent.target.removeEventListener('focus', arguments.callee, false);
|
||||
document.getElementById('bsbis').click();
|
||||
document.getElementById('is2').focus();
|
||||
}, false);
|
||||
|
||||
document.getElementById('is2').addEventListener('focus', function(aEvent) {
|
||||
aEvent.target.removeEventListener('focus', arguments.callee, false);
|
||||
synthesizeKey("VK_RETURN", {});
|
||||
document.getElementById('ii2').focus();
|
||||
}, false);
|
||||
|
||||
document.getElementById('ii2').addEventListener('focus', function(aEvent) {
|
||||
aEvent.target.removeEventListener('focus', arguments.callee, false);
|
||||
synthesizeKey("VK_RETURN", {});
|
||||
document.getElementById('bs2').focus();
|
||||
}, false);
|
||||
|
||||
document.getElementById('bs2').addEventListener('focus', function(aEvent) {
|
||||
aEvent.target.removeEventListener('focus', arguments.callee, false);
|
||||
synthesizeKey("VK_RETURN", {});
|
||||
document.getElementById('enter').focus();
|
||||
}, false);
|
||||
|
||||
document.getElementById('enter').addEventListener('focus', function(aEvent) {
|
||||
aEvent.target.removeEventListener('focus', arguments.callee, false);
|
||||
synthesizeKey("VK_RETURN", {});
|
||||
document.getElementById('i8').focus();
|
||||
}, false);
|
||||
|
||||
document.getElementById('i8').addEventListener('focus', function(aEvent) {
|
||||
aEvent.target.removeEventListener('focus', arguments.callee, false);
|
||||
synthesizeKey("VK_RETURN", {});
|
||||
document.getElementById('i9').focus();
|
||||
}, false);
|
||||
|
||||
document.getElementById('i9').addEventListener('focus', function(aEvent) {
|
||||
aEvent.target.removeEventListener('focus', arguments.callee, false);
|
||||
synthesizeKey("VK_RETURN", {});
|
||||
}, false);
|
||||
|
||||
document.getElementById('is').focus();
|
||||
}
|
||||
|
||||
function frameLoaded(aFrame) {
|
||||
// Check if formaction/action has the correct behavior.
|
||||
is(aFrame.contentDocument.documentElement.textContent, gTestResults[aFrame.name],
|
||||
"the enctype/formenctype attribute doesn't have the correct behavior");
|
||||
|
||||
if (--gPendingLoad == 0) {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -37,46 +37,52 @@ var methodTestData = [
|
|||
[ "delete", "put" ],
|
||||
];
|
||||
|
||||
var form = document.createElement('form');
|
||||
|
||||
function checkAttribute(form, name, data)
|
||||
function checkAttribute(form, attrName, idlName, data)
|
||||
{
|
||||
is(form.getAttribute(name), undefined,
|
||||
"By default " + name + " content attribute should be undefined");
|
||||
is(form[name], data[0][0],
|
||||
"By default " + name + " IDL attribute should be equal to " +
|
||||
is(form.getAttribute(attrName), null,
|
||||
"By default " + attrName + " content attribute should be null");
|
||||
is(form[idlName], data[0][0],
|
||||
"By default " + idlName + " IDL attribute should be equal to " +
|
||||
data[0][0]);
|
||||
|
||||
// Valid values.
|
||||
for (i in data[1]) {
|
||||
form.setAttribute(name, data[1][i]);
|
||||
is(form.getAttribute(name), data[1][i],
|
||||
form.setAttribute(attrName, data[1][i]);
|
||||
is(form.getAttribute(attrName), data[1][i],
|
||||
"getAttribute should return the content attribute");
|
||||
is(form[name], data[1][i], "When getting, " + name + " IDL attribute " +
|
||||
is(form[idlName], data[1][i], "When getting, " + idlName + " IDL attribute " +
|
||||
"should be equal to the content attribute if the value is known");
|
||||
}
|
||||
|
||||
// Invalid values.
|
||||
for (i in data[2]) {
|
||||
form.setAttribute(name, data[2][i]);
|
||||
is(form.getAttribute(name), data[2][i],
|
||||
form.setAttribute(attrName, data[2][i]);
|
||||
is(form.getAttribute(attrName), data[2][i],
|
||||
"getAttribute should return the content attribute");
|
||||
is(form[name], data[0][0], "When getting, " + name + " IDL attribute " +
|
||||
is(form[idlName], data[0][0], "When getting, " + idlName + " IDL attribute " +
|
||||
"should return the default value if the content attribute value isn't known");
|
||||
}
|
||||
|
||||
// TODO values.
|
||||
for (i in data[3]) {
|
||||
form.setAttribute(name, data[3][i]);
|
||||
is(form.getAttribute(name), data[3][i],
|
||||
form.setAttribute(attrName, data[3][i]);
|
||||
is(form.getAttribute(attrName), data[3][i],
|
||||
"getAttribute should return the content attribute");
|
||||
todo_is(form[name], data[3][i], "When getting, " + name + " IDL attribute " +
|
||||
todo_is(form[idlName], data[3][i], "When getting, " + idlName + " IDL attribute " +
|
||||
"should be equal to the content attribute if the value is known");
|
||||
}
|
||||
}
|
||||
|
||||
checkAttribute(form, 'enctype', enctypeTestData);
|
||||
checkAttribute(form, 'method', methodTestData);
|
||||
var form = document.createElement('form');
|
||||
var input = document.createElement('input');
|
||||
var button = document.createElement('button');
|
||||
|
||||
checkAttribute(form, 'enctype', 'enctype', enctypeTestData);
|
||||
checkAttribute(form, 'method', 'method', methodTestData);
|
||||
checkAttribute(input, 'formenctype', 'formEnctype', enctypeTestData);
|
||||
checkAttribute(input, 'formmethod', 'formMethod', methodTestData);
|
||||
checkAttribute(button, 'formenctype', 'formEnctype', enctypeTestData);
|
||||
checkAttribute(button, 'formmethod', 'formMethod', methodTestData);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -113,7 +113,6 @@ _TEST_FILES = \
|
|||
test_load_candidates.html \
|
||||
test_load_source.html \
|
||||
test_media_selection.html \
|
||||
test_mixed_principals.html \
|
||||
test_mozLoadFrom.html \
|
||||
test_networkState.html \
|
||||
test_new_audio.html \
|
||||
|
@ -147,6 +146,8 @@ _TEST_FILES = \
|
|||
# test_videoDocumentTitle.html
|
||||
# Bug 493692:
|
||||
# test_preload_suspend.html
|
||||
# Bug 567954 and Bug 574586:
|
||||
# test_mixed_principals.html
|
||||
# Disabled since we don't play Wave files standalone, for now
|
||||
# test_audioDocumentTitle.html
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include "nsDebug.h"
|
||||
#include "gfxContext.h"
|
||||
#include "nsSVGUtils.h"
|
||||
#include "gfxPlatform.h"
|
||||
|
||||
class nsSVGElement;
|
||||
class nsIContent;
|
||||
|
@ -63,7 +64,7 @@ public:
|
|||
public:
|
||||
PathGenerator(nsSVGElement* aSVGElement)
|
||||
: mSVGElement(aSVGElement),
|
||||
mGfxContext(nsSVGUtils::GetThebesComputationalSurface()),
|
||||
mGfxContext(gfxPlatform::GetPlatform()->ScreenReferenceSurface()),
|
||||
mHaveReceivedCommands(PR_FALSE)
|
||||
{}
|
||||
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#include "nsSVGUtils.h"
|
||||
#include "nsSVGPoint.h"
|
||||
#include "gfxContext.h"
|
||||
#include "gfxPlatform.h"
|
||||
|
||||
nsSVGElement::NumberInfo nsSVGPathElement::sNumberInfo =
|
||||
{ &nsGkAtoms::pathLength, 0 };
|
||||
|
@ -1041,7 +1042,7 @@ nsSVGPathList::Playback(gfxContext *aCtx)
|
|||
already_AddRefed<gfxFlattenedPath>
|
||||
nsSVGPathList::GetFlattenedPath(const gfxMatrix& aMatrix)
|
||||
{
|
||||
gfxContext ctx(nsSVGUtils::GetThebesComputationalSurface());
|
||||
gfxContext ctx(gfxPlatform::GetPlatform()->ScreenReferenceSurface());
|
||||
|
||||
ctx.SetMatrix(aMatrix);
|
||||
Playback(&ctx);
|
||||
|
|
|
@ -369,7 +369,7 @@
|
|||
error types. -->
|
||||
<div id="securityOverrideDiv">
|
||||
<a id="securityOverrideLink" href="javascript:showSecuritySection();" >&securityOverride.linkText;</a>
|
||||
<div id="securityOverrideContent" style="display: none;">&securityOverride.warningText;</div>
|
||||
<div id="securityOverrideContent" style="display: none;">&securityOverride.warningContent;</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -642,7 +642,17 @@ nsSHEntry::AddChild(nsISHEntry * aChild, PRInt32 aOffset)
|
|||
}
|
||||
#endif
|
||||
|
||||
mChildren.InsertObjectAt(aChild, aOffset);
|
||||
// InsertObjectAt allows only appending one object.
|
||||
// If aOffset is larger than Count(), we must first manually
|
||||
// set the capacity.
|
||||
if (aOffset > mChildren.Count()) {
|
||||
mChildren.SetCount(aOffset);
|
||||
}
|
||||
if (!mChildren.InsertObjectAt(aChild, aOffset)) {
|
||||
NS_WARNING("Adding a child failed!");
|
||||
aChild->SetParent(nsnull);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -49,13 +49,15 @@
|
|||
|
||||
interface nsIDOMValidityState;
|
||||
|
||||
[scriptable, uuid(f80d0ab0-a9a0-11df-94e2-0800200c9a66)]
|
||||
[scriptable, uuid(d76a7412-f70b-43fe-becb-d30dac13cc7b)]
|
||||
interface nsIDOMHTMLButtonElement : nsIDOMHTMLElement
|
||||
{
|
||||
attribute boolean autofocus;
|
||||
attribute boolean disabled;
|
||||
readonly attribute nsIDOMHTMLFormElement form;
|
||||
attribute DOMString formAction;
|
||||
attribute DOMString formEnctype;
|
||||
attribute DOMString formMethod;
|
||||
attribute DOMString formTarget;
|
||||
|
||||
attribute DOMString name;
|
||||
|
|
|
@ -51,7 +51,7 @@ interface nsIDOMValidityState;
|
|||
* http://www.w3.org/TR/DOM-Level-2-HTML/
|
||||
*/
|
||||
|
||||
[scriptable, uuid(da7ef8a0-a9a0-11df-94e2-0800200c9a66)]
|
||||
[scriptable, uuid(e5079711-e6a9-4d3a-9b62-b4a8ef08fa7d)]
|
||||
interface nsIDOMHTMLInputElement : nsIDOMHTMLElement
|
||||
{
|
||||
attribute DOMString accept;
|
||||
|
@ -63,6 +63,8 @@ interface nsIDOMHTMLInputElement : nsIDOMHTMLElement
|
|||
attribute boolean disabled;
|
||||
readonly attribute nsIDOMHTMLFormElement form;
|
||||
attribute DOMString formAction;
|
||||
attribute DOMString formEnctype;
|
||||
attribute DOMString formMethod;
|
||||
attribute DOMString formTarget;
|
||||
|
||||
readonly attribute nsIDOMFileList files;
|
||||
|
|
|
@ -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,7 @@
|
|||
#include "nsSerializationHelper.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsIView.h"
|
||||
#include "nsIEventListenerManager.h"
|
||||
|
||||
#ifdef MOZ_WIDGET_QT
|
||||
#include <QX11EmbedWidget>
|
||||
|
@ -509,6 +510,11 @@ TabChild::~TabChild()
|
|||
if (mCx) {
|
||||
DestroyCx();
|
||||
}
|
||||
|
||||
nsIEventListenerManager* elm = mTabChildGlobal->GetListenerManager(PR_FALSE);
|
||||
if (elm) {
|
||||
elm->Disconnect();
|
||||
}
|
||||
mTabChildGlobal->mTabChild = nsnull;
|
||||
}
|
||||
|
||||
|
|
|
@ -304,7 +304,7 @@ private:
|
|||
bool InitTabChildGlobal();
|
||||
|
||||
nsCOMPtr<nsIWebNavigation> mWebNav;
|
||||
TabChildGlobal* mTabChildGlobal;
|
||||
nsRefPtr<TabChildGlobal> mTabChildGlobal;
|
||||
PRUint32 mChromeFlags;
|
||||
|
||||
DISALLOW_EVIL_CONSTRUCTORS(TabChild);
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
should go into netError.dtd -->
|
||||
|
||||
<!ENTITY securityOverride.linkText "Or you can add an exception…">
|
||||
<!ENTITY securityOverride.warningText "
|
||||
<!ENTITY securityOverride.warningContent "
|
||||
<p>You should not add an exception if you are using an internet connection that you do not trust completely or if you are not used to seeing a warning for this server.</p>
|
||||
<p>If you still wish to add an exception for this site, you can do so in your advanced encryption settings.</p>
|
||||
">
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -116,8 +116,10 @@ class GeckoAppShell
|
|||
if (!f.exists())
|
||||
f.mkdirs();
|
||||
GeckoAppShell.putenv("TMPDIR=" + f.getPath());
|
||||
|
||||
|
||||
|
||||
f = Environment.getDownloadCacheDirectory();
|
||||
GeckoAppShell.putenv("EXTERNAL_STORAGE" + f.getPath());
|
||||
|
||||
// NSPR
|
||||
System.loadLibrary("nspr4");
|
||||
System.loadLibrary("plc4");
|
||||
|
|
|
@ -458,6 +458,12 @@ public class GeckoInputConnection
|
|||
imm.updateSelection(GeckoApp.surfaceView, start, end, -1, -1);
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
mComposing = false;
|
||||
mComposingText = null;
|
||||
mUpdateRequest = null;
|
||||
}
|
||||
|
||||
// Is a composition active?
|
||||
boolean mComposing;
|
||||
// Composition text when a composition is active
|
||||
|
|
|
@ -243,6 +243,8 @@ class GeckoSurfaceView
|
|||
|
||||
if (mIMEState == IME_STATE_PASSWORD)
|
||||
outAttrs.inputType |= InputType.TYPE_TEXT_VARIATION_PASSWORD;
|
||||
|
||||
inputConnection.reset();
|
||||
return inputConnection;
|
||||
}
|
||||
|
||||
|
|
|
@ -343,6 +343,8 @@ nsPermissionManager::CreateTable()
|
|||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// create the table
|
||||
// SQL also lives in automation.py.in. If you change this SQL change that
|
||||
// one too.
|
||||
return mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||
"CREATE TABLE moz_hosts ("
|
||||
" id INTEGER PRIMARY KEY"
|
||||
|
|
|
@ -61,6 +61,7 @@ typedef struct _cairo_os2_surface
|
|||
|
||||
/* General flags: */
|
||||
cairo_bool_t blit_as_changes;
|
||||
cairo_bool_t use_24bpp;
|
||||
} cairo_os2_surface_t;
|
||||
|
||||
#endif /* CAIRO_OS2_PRIVATE_H */
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Peter Weilbacher <mozilla@Weilbacher.org>
|
||||
* Rich Walsh <dragtext@e-vertise.com>
|
||||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
|
@ -66,7 +67,7 @@
|
|||
/* Initialization counter: */
|
||||
static int cairo_os2_initialization_count = 0;
|
||||
|
||||
static void inline
|
||||
static inline void
|
||||
DisableFPUException (void)
|
||||
{
|
||||
unsigned short usCW;
|
||||
|
@ -169,43 +170,35 @@ cairo_os2_fini (void)
|
|||
*/
|
||||
void *_buffer_alloc (size_t a, size_t b, const unsigned int size)
|
||||
{
|
||||
/* check length like in the _cairo_malloc_abc macro, but we can leave
|
||||
* away the unsigned casts as our arguments are unsigned already
|
||||
*/
|
||||
size_t nbytes = b &&
|
||||
a >= INT32_MAX / b ? 0 : size &&
|
||||
a*b >= INT32_MAX / size ? 0 : a * b * size;
|
||||
void *buffer = NULL;
|
||||
#ifdef OS2_USE_PLATFORM_ALLOC
|
||||
APIRET rc = NO_ERROR;
|
||||
size_t nbytes;
|
||||
void *buffer = NULL;
|
||||
|
||||
rc = DosAllocMem ((PPVOID)&buffer,
|
||||
nbytes,
|
||||
#ifdef OS2_HIGH_MEMORY /* only if compiled with high-memory support, */
|
||||
OBJ_ANY | /* we can allocate anywhere! */
|
||||
#endif
|
||||
PAG_READ | PAG_WRITE | PAG_COMMIT);
|
||||
if (rc != NO_ERROR) {
|
||||
/* should there for some reason be another error, let's return
|
||||
* a null surface and free the buffer again, because that's
|
||||
* how a malloc failure would look like
|
||||
*/
|
||||
if (rc != ERROR_NOT_ENOUGH_MEMORY && buffer) {
|
||||
DosFreeMem (buffer);
|
||||
}
|
||||
if (!a || !b || !size ||
|
||||
a >= INT32_MAX / b || a*b >= INT32_MAX / size) {
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
buffer = malloc (nbytes);
|
||||
nbytes = a * b * size;
|
||||
|
||||
#ifdef OS2_USE_PLATFORM_ALLOC
|
||||
/* Using OBJ_ANY on a machine that isn't configured for hi-mem
|
||||
* will cause ERROR_INVALID_PARAMETER. If this occurs, or this
|
||||
* build doesn't have hi-mem enabled, fall back to using lo-mem.
|
||||
*/
|
||||
#ifdef OS2_HIGH_MEMORY
|
||||
if (!DosAllocMem (&buffer, nbytes,
|
||||
OBJ_ANY | PAG_READ | PAG_WRITE | PAG_COMMIT))
|
||||
return buffer;
|
||||
#endif
|
||||
if (DosAllocMem (&buffer, nbytes,
|
||||
PAG_READ | PAG_WRITE | PAG_COMMIT))
|
||||
return NULL;
|
||||
#else
|
||||
/* Clear the malloc'd buffer the way DosAllocMem() does. */
|
||||
buffer = malloc (nbytes);
|
||||
if (buffer) {
|
||||
memset (buffer, 0, nbytes);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* This does not seem to be needed, malloc'd space is usually
|
||||
* already zero'd out!
|
||||
*/
|
||||
/*
|
||||
* memset (buffer, 0x00, nbytes);
|
||||
*/
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
@ -303,46 +296,38 @@ _cairo_os2_surface_blit_pixels (cairo_os2_surface_t *surface,
|
|||
PRECTL prcl_begin_paint_rect)
|
||||
{
|
||||
POINTL aptlPoints[4];
|
||||
LONG lOldYInversion, rc = GPI_OK;
|
||||
LONG lOldYInversion;
|
||||
LONG rc = GPI_OK;
|
||||
|
||||
/* Enable Y Inversion for the HPS, so the
|
||||
* GpiDrawBits will work with upside-top image, not with upside-down image!
|
||||
/* Check the limits (may not be necessary) */
|
||||
if (prcl_begin_paint_rect->xLeft < 0)
|
||||
prcl_begin_paint_rect->xLeft = 0;
|
||||
if (prcl_begin_paint_rect->yBottom < 0)
|
||||
prcl_begin_paint_rect->yBottom = 0;
|
||||
if (prcl_begin_paint_rect->xRight > (LONG) surface->bitmap_info.cx)
|
||||
prcl_begin_paint_rect->xRight = (LONG) surface->bitmap_info.cx;
|
||||
if (prcl_begin_paint_rect->yTop > (LONG) surface->bitmap_info.cy)
|
||||
prcl_begin_paint_rect->yTop = (LONG) surface->bitmap_info.cy;
|
||||
|
||||
/* Exit if the rectangle is empty */
|
||||
if (prcl_begin_paint_rect->xLeft >= prcl_begin_paint_rect->xRight ||
|
||||
prcl_begin_paint_rect->yBottom >= prcl_begin_paint_rect->yTop)
|
||||
return;
|
||||
|
||||
/* Set the Target & Source coordinates */
|
||||
*((PRECTL)&aptlPoints[0]) = *prcl_begin_paint_rect;
|
||||
*((PRECTL)&aptlPoints[2]) = *prcl_begin_paint_rect;
|
||||
|
||||
/* Make the Target coordinates non-inclusive */
|
||||
aptlPoints[1].x -= 1;
|
||||
aptlPoints[1].y -= 1;
|
||||
|
||||
/* Enable Y Inversion for the HPS, so GpiDrawBits will
|
||||
* work with upside-top image, not with upside-down image!
|
||||
*/
|
||||
lOldYInversion = GpiQueryYInversion (hps_begin_paint);
|
||||
GpiEnableYInversion (hps_begin_paint, surface->bitmap_info.cy-1);
|
||||
|
||||
/* Target coordinates (Noninclusive) */
|
||||
aptlPoints[0].x = prcl_begin_paint_rect->xLeft;
|
||||
aptlPoints[0].y = prcl_begin_paint_rect->yBottom;
|
||||
|
||||
aptlPoints[1].x = prcl_begin_paint_rect->xRight-1;
|
||||
aptlPoints[1].y = prcl_begin_paint_rect->yTop-1;
|
||||
|
||||
/* Source coordinates (Inclusive) */
|
||||
aptlPoints[2].x = prcl_begin_paint_rect->xLeft;
|
||||
aptlPoints[2].y = prcl_begin_paint_rect->yBottom;
|
||||
|
||||
aptlPoints[3].x = prcl_begin_paint_rect->xRight;
|
||||
aptlPoints[3].y = (prcl_begin_paint_rect->yTop);
|
||||
|
||||
/* Some extra checking for limits
|
||||
* (Dunno if really needed, but had some crashes sometimes without it,
|
||||
* while developing the code...)
|
||||
*/
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (aptlPoints[i].x < 0)
|
||||
aptlPoints[i].x = 0;
|
||||
if (aptlPoints[i].y < 0)
|
||||
aptlPoints[i].y = 0;
|
||||
if (aptlPoints[i].x > (LONG) surface->bitmap_info.cx)
|
||||
aptlPoints[i].x = (LONG) surface->bitmap_info.cx;
|
||||
if (aptlPoints[i].y > (LONG) surface->bitmap_info.cy)
|
||||
aptlPoints[i].y = (LONG) surface->bitmap_info.cy;
|
||||
}
|
||||
}
|
||||
|
||||
/* Debug code to draw rectangle limits */
|
||||
#if 0
|
||||
{
|
||||
|
@ -364,63 +349,81 @@ _cairo_os2_surface_blit_pixels (cairo_os2_surface_t *surface,
|
|||
}
|
||||
}
|
||||
#endif
|
||||
rc = GpiDrawBits (hps_begin_paint,
|
||||
surface->pixels,
|
||||
&(surface->bitmap_info),
|
||||
4,
|
||||
aptlPoints,
|
||||
ROP_SRCCOPY,
|
||||
BBO_IGNORE);
|
||||
if (!surface->use_24bpp) {
|
||||
rc = GpiDrawBits (hps_begin_paint,
|
||||
surface->pixels,
|
||||
&(surface->bitmap_info),
|
||||
4,
|
||||
aptlPoints,
|
||||
ROP_SRCCOPY,
|
||||
BBO_IGNORE);
|
||||
if (rc != GPI_OK)
|
||||
surface->use_24bpp = TRUE;
|
||||
}
|
||||
|
||||
if (rc != GPI_OK) {
|
||||
/* if GpiDrawBits () failed then this is most likely because the
|
||||
if (surface->use_24bpp) {
|
||||
/* If GpiDrawBits () failed then this is most likely because the
|
||||
* display driver could not handle a 32bit bitmap. So we need to
|
||||
* - create a buffer that only contains 3 bytes per pixel
|
||||
* - change the bitmap info header to contain 24bit
|
||||
* - pass the new buffer to GpiDrawBits () again
|
||||
* - clean up the new buffer
|
||||
*/
|
||||
BITMAPINFOHEADER2 bmpheader;
|
||||
unsigned char *pchPixBuf, *pchPixSource;
|
||||
void *pBufStart;
|
||||
ULONG ulPixels;
|
||||
BITMAPINFO2 bmpinfo;
|
||||
unsigned char *pchPixBuf;
|
||||
unsigned char *pchTarget;
|
||||
ULONG *pulSource;
|
||||
ULONG ulX;
|
||||
ULONG ulY;
|
||||
ULONG ulPad;
|
||||
|
||||
/* allocate temporary pixel buffer */
|
||||
pchPixBuf = (unsigned char *) _buffer_alloc (surface->bitmap_info.cy,
|
||||
surface->bitmap_info.cx,
|
||||
3);
|
||||
pchPixSource = surface->pixels; /* start at beginning of pixel buffer */
|
||||
pBufStart = pchPixBuf; /* remember beginning of the new pixel buffer */
|
||||
/* Set up the bitmap header, but this time for 24bit depth. */
|
||||
bmpinfo = surface->bitmap_info;
|
||||
bmpinfo.cBitCount = 24;
|
||||
|
||||
/* copy the first three bytes for each pixel but skip over the fourth */
|
||||
for (ulPixels = 0; ulPixels < surface->bitmap_info.cx * surface->bitmap_info.cy; ulPixels++)
|
||||
{
|
||||
/* copy BGR from source buffer */
|
||||
*pchPixBuf++ = *pchPixSource++;
|
||||
*pchPixBuf++ = *pchPixSource++;
|
||||
*pchPixBuf++ = *pchPixSource++;
|
||||
pchPixSource++; /* jump over alpha channel in source buffer */
|
||||
/* The start of each row has to be DWORD aligned. Calculate the
|
||||
* of number aligned bytes per row, the total size of the bitmap,
|
||||
* and the number of padding bytes at the end of each row.
|
||||
*/
|
||||
ulX = (((bmpinfo.cx * bmpinfo.cBitCount) + 31) / 32) * 4;
|
||||
bmpinfo.cbImage = ulX * bmpinfo.cy;
|
||||
ulPad = ulX - bmpinfo.cx * 3;
|
||||
|
||||
/* Allocate temporary pixel buffer. If the rows don't need
|
||||
* padding, it has to be 1 byte larger than the size of the
|
||||
* bitmap or else the high-order byte from the last source
|
||||
* row will end up in unallocated memory.
|
||||
*/
|
||||
pchPixBuf = (unsigned char *)_buffer_alloc (1, 1,
|
||||
bmpinfo.cbImage + (ulPad ? 0 : 1));
|
||||
|
||||
if (pchPixBuf) {
|
||||
/* Copy 4 bytes from the source but advance the target ptr only
|
||||
* 3 bytes, so the high-order alpha byte will be overwritten by
|
||||
* the next copy. At the end of each row, skip over the padding.
|
||||
*/
|
||||
pchTarget = pchPixBuf;
|
||||
pulSource = (ULONG*)surface->pixels;
|
||||
for (ulY = bmpinfo.cy; ulY; ulY--) {
|
||||
for (ulX = bmpinfo.cx; ulX; ulX--) {
|
||||
*((ULONG*)pchTarget) = *pulSource++;
|
||||
pchTarget += 3;
|
||||
}
|
||||
pchTarget += ulPad;
|
||||
}
|
||||
|
||||
rc = GpiDrawBits (hps_begin_paint,
|
||||
pchPixBuf,
|
||||
&bmpinfo,
|
||||
4,
|
||||
aptlPoints,
|
||||
ROP_SRCCOPY,
|
||||
BBO_IGNORE);
|
||||
if (rc != GPI_OK)
|
||||
surface->use_24bpp = FALSE;
|
||||
|
||||
_buffer_free (pchPixBuf);
|
||||
}
|
||||
|
||||
/* jump back to start of the buffer for display and cleanup */
|
||||
pchPixBuf = pBufStart;
|
||||
|
||||
/* set up the bitmap header, but this time with 24bit depth only */
|
||||
memset (&bmpheader, 0, sizeof (bmpheader));
|
||||
bmpheader.cbFix = sizeof (BITMAPINFOHEADER2);
|
||||
bmpheader.cx = surface->bitmap_info.cx;
|
||||
bmpheader.cy = surface->bitmap_info.cy;
|
||||
bmpheader.cPlanes = surface->bitmap_info.cPlanes;
|
||||
bmpheader.cBitCount = 24;
|
||||
rc = GpiDrawBits (hps_begin_paint,
|
||||
pchPixBuf,
|
||||
(PBITMAPINFO2)&bmpheader,
|
||||
4,
|
||||
aptlPoints,
|
||||
ROP_SRCCOPY,
|
||||
BBO_IGNORE);
|
||||
|
||||
_buffer_free (pchPixBuf);
|
||||
}
|
||||
|
||||
/* Restore Y inversion */
|
||||
|
@ -434,7 +437,6 @@ _cairo_os2_surface_get_pixels_from_screen (cairo_os2_surface_t *surface,
|
|||
{
|
||||
HPS hps;
|
||||
HDC hdc;
|
||||
HAB hab;
|
||||
SIZEL sizlTemp;
|
||||
HBITMAP hbmpTemp;
|
||||
BITMAPINFO2 bmi2Temp;
|
||||
|
@ -452,19 +454,10 @@ _cairo_os2_surface_get_pixels_from_screen (cairo_os2_surface_t *surface,
|
|||
* -- Blit dirty pixels from screen to HBITMAP
|
||||
* - Copy HBITMAP lines (pixels) into our buffer
|
||||
* - Free resources
|
||||
*
|
||||
* These steps will require an Anchor Block (HAB). However,
|
||||
* WinQUeryAnchorBlock () documentation says that HAB is not
|
||||
* used in current OS/2 implementations, OS/2 deduces all information
|
||||
* it needs from the TID. Anyway, we'd be in trouble if we'd have to
|
||||
* get a HAB where we only know a HPS...
|
||||
* So, we'll simply use a fake HAB.
|
||||
*/
|
||||
|
||||
hab = (HAB) 1; /* OS/2 doesn't really use HAB... */
|
||||
|
||||
/* Create a memory device context */
|
||||
hdc = DevOpenDC (hab, OD_MEMORY,"*",0L, NULL, NULLHANDLE);
|
||||
hdc = DevOpenDC (0, OD_MEMORY,"*",0L, NULL, NULLHANDLE);
|
||||
if (!hdc) {
|
||||
return;
|
||||
}
|
||||
|
@ -472,7 +465,7 @@ _cairo_os2_surface_get_pixels_from_screen (cairo_os2_surface_t *surface,
|
|||
/* Create a memory PS */
|
||||
sizlTemp.cx = prcl_begin_paint_rect->xRight - prcl_begin_paint_rect->xLeft;
|
||||
sizlTemp.cy = prcl_begin_paint_rect->yTop - prcl_begin_paint_rect->yBottom;
|
||||
hps = GpiCreatePS (hab,
|
||||
hps = GpiCreatePS (0,
|
||||
hdc,
|
||||
&sizlTemp,
|
||||
PU_PELS | GPIT_NORMAL | GPIA_ASSOC);
|
||||
|
@ -537,7 +530,7 @@ _cairo_os2_surface_get_pixels_from_screen (cairo_os2_surface_t *surface,
|
|||
GpiQueryBitmapBits (hps,
|
||||
sizlTemp.cy - y - 1, /* lScanStart */
|
||||
1, /* lScans */
|
||||
pchTemp,
|
||||
(PBYTE)pchTemp,
|
||||
&bmi2Temp);
|
||||
|
||||
/* Go for next line */
|
||||
|
@ -722,6 +715,14 @@ _cairo_os2_surface_get_extents (void *abstract_surface,
|
|||
{
|
||||
cairo_os2_surface_t *local_os2_surface;
|
||||
|
||||
local_os2_surface = (cairo_os2_surface_t *) abstract_surface;
|
||||
if ((!local_os2_surface) ||
|
||||
(local_os2_surface->base.backend != &cairo_os2_surface_backend))
|
||||
{
|
||||
/* Invalid parameter (wrong surface)! */
|
||||
return _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
|
||||
}
|
||||
|
||||
rectangle->x = 0;
|
||||
rectangle->y = 0;
|
||||
rectangle->width = local_os2_surface->bitmap_info.cx;
|
||||
|
@ -737,14 +738,15 @@ _cairo_os2_surface_get_extents (void *abstract_surface,
|
|||
* @height: the height of the surface
|
||||
*
|
||||
* Create a Cairo surface which is bound to a given presentation space (HPS).
|
||||
* The surface will be created to have the given size.
|
||||
* By default every change to the surface will be made visible immediately by
|
||||
* blitting it into the window. This can be changed with
|
||||
* The caller retains ownership of the HPS and must dispose of it after the
|
||||
* the surface has been destroyed. The surface will be created to have the
|
||||
* given size. By default every change to the surface will be made visible
|
||||
* immediately by blitting it into the window. This can be changed with
|
||||
* cairo_os2_surface_set_manual_window_refresh().
|
||||
* Note that the surface will contain garbage when created, so the pixels have
|
||||
* to be initialized by hand first. You can use the Cairo functions to fill it
|
||||
* with black, or use cairo_surface_mark_dirty() to fill the surface with pixels
|
||||
* from the window/HPS.
|
||||
* Note that the surface will contain garbage when created, so the pixels
|
||||
* have to be initialized by hand first. You can use the Cairo functions to
|
||||
* fill it with black, or use cairo_surface_mark_dirty() to fill the surface
|
||||
* with pixels from the window/HPS.
|
||||
*
|
||||
* Return value: the newly created surface
|
||||
*
|
||||
|
@ -755,72 +757,48 @@ cairo_os2_surface_create (HPS hps_client_window,
|
|||
int width,
|
||||
int height)
|
||||
{
|
||||
cairo_os2_surface_t *local_os2_surface;
|
||||
cairo_os2_surface_t *local_os2_surface = 0;
|
||||
cairo_status_t status;
|
||||
int rc;
|
||||
|
||||
/* Check the size of the window */
|
||||
if ((width <= 0) ||
|
||||
(height <= 0))
|
||||
{
|
||||
/* Invalid window size! */
|
||||
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
|
||||
if ((width <= 0) || (height <= 0)) {
|
||||
status = _cairo_error (CAIRO_STATUS_INVALID_SIZE);
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
/* Allocate an OS/2 surface structure. */
|
||||
local_os2_surface = (cairo_os2_surface_t *) malloc (sizeof (cairo_os2_surface_t));
|
||||
if (!local_os2_surface) {
|
||||
/* Not enough memory! */
|
||||
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
|
||||
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
/* Initialize the OS/2 specific parts of the surface! */
|
||||
memset(local_os2_surface, 0, sizeof(cairo_os2_surface_t));
|
||||
|
||||
/* Create mutex semaphore */
|
||||
rc = DosCreateMutexSem (NULL,
|
||||
&(local_os2_surface->hmtx_use_private_fields),
|
||||
0,
|
||||
FALSE);
|
||||
if (rc != NO_ERROR) {
|
||||
/* Could not create mutex semaphore! */
|
||||
free (local_os2_surface);
|
||||
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
|
||||
/* Allocate resources: mutex & event semaphores and the pixel buffer */
|
||||
if (DosCreateMutexSem (NULL,
|
||||
&(local_os2_surface->hmtx_use_private_fields),
|
||||
0,
|
||||
FALSE))
|
||||
{
|
||||
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
/* Save PS handle */
|
||||
local_os2_surface->hps_client_window = hps_client_window;
|
||||
|
||||
/* Defaults */
|
||||
local_os2_surface->hwnd_client_window = NULLHANDLE;
|
||||
local_os2_surface->blit_as_changes = TRUE;
|
||||
local_os2_surface->pixel_array_lend_count = 0;
|
||||
rc = DosCreateEventSem (NULL,
|
||||
&(local_os2_surface->hev_pixel_array_came_back),
|
||||
0,
|
||||
FALSE);
|
||||
|
||||
if (rc != NO_ERROR) {
|
||||
/* Could not create event semaphore! */
|
||||
DosCloseMutexSem (local_os2_surface->hmtx_use_private_fields);
|
||||
free (local_os2_surface);
|
||||
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
|
||||
if (DosCreateEventSem (NULL,
|
||||
&(local_os2_surface->hev_pixel_array_came_back),
|
||||
0,
|
||||
FALSE))
|
||||
{
|
||||
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
/* Prepare BITMAPINFO2 structure for our buffer */
|
||||
memset (&(local_os2_surface->bitmap_info), 0, sizeof (local_os2_surface->bitmap_info));
|
||||
local_os2_surface->bitmap_info.cbFix = sizeof (BITMAPINFOHEADER2);
|
||||
local_os2_surface->bitmap_info.cx = width;
|
||||
local_os2_surface->bitmap_info.cy = height;
|
||||
local_os2_surface->bitmap_info.cPlanes = 1;
|
||||
local_os2_surface->bitmap_info.cBitCount = 32;
|
||||
|
||||
/* Allocate memory for pixels */
|
||||
local_os2_surface->pixels = (unsigned char *) _buffer_alloc (height, width, 4);
|
||||
if (!(local_os2_surface->pixels)) {
|
||||
/* Not enough memory for the pixels! */
|
||||
DosCloseEventSem (local_os2_surface->hev_pixel_array_came_back);
|
||||
DosCloseMutexSem (local_os2_surface->hmtx_use_private_fields);
|
||||
free (local_os2_surface);
|
||||
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
|
||||
if (!local_os2_surface->pixels) {
|
||||
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
/* Create image surface from pixel array */
|
||||
|
@ -830,22 +808,91 @@ cairo_os2_surface_create (HPS hps_client_window,
|
|||
width, /* Width */
|
||||
height, /* Height */
|
||||
width * 4); /* Rowstride */
|
||||
|
||||
status = local_os2_surface->image_surface->base.status;
|
||||
if (status) {
|
||||
/* Could not create image surface! */
|
||||
_buffer_free (local_os2_surface->pixels);
|
||||
DosCloseEventSem (local_os2_surface->hev_pixel_array_came_back);
|
||||
DosCloseMutexSem (local_os2_surface->hmtx_use_private_fields);
|
||||
free (local_os2_surface);
|
||||
return _cairo_surface_create_in_error (status);
|
||||
}
|
||||
if (status)
|
||||
goto error_exit;
|
||||
|
||||
/* Set values for OS/2-specific data that aren't zero/NULL/FALSE.
|
||||
* Note: hps_client_window may be null if this was called by
|
||||
* cairo_os2_surface_create_for_window().
|
||||
*/
|
||||
local_os2_surface->hps_client_window = hps_client_window;
|
||||
local_os2_surface->blit_as_changes = TRUE;
|
||||
|
||||
/* Prepare BITMAPINFO2 structure for our buffer */
|
||||
local_os2_surface->bitmap_info.cbFix = sizeof (BITMAPINFOHEADER2);
|
||||
local_os2_surface->bitmap_info.cx = width;
|
||||
local_os2_surface->bitmap_info.cy = height;
|
||||
local_os2_surface->bitmap_info.cPlanes = 1;
|
||||
local_os2_surface->bitmap_info.cBitCount = 32;
|
||||
|
||||
/* Initialize base surface */
|
||||
_cairo_surface_init (&local_os2_surface->base,
|
||||
&cairo_os2_surface_backend,
|
||||
_cairo_content_from_format (CAIRO_FORMAT_ARGB32));
|
||||
|
||||
/* Successful exit */
|
||||
return (cairo_surface_t *)local_os2_surface;
|
||||
|
||||
error_exit:
|
||||
|
||||
/* This point will only be reached if an error occured */
|
||||
|
||||
if (local_os2_surface) {
|
||||
if (local_os2_surface->pixels)
|
||||
_buffer_free (local_os2_surface->pixels);
|
||||
if (local_os2_surface->hev_pixel_array_came_back)
|
||||
DosCloseEventSem (local_os2_surface->hev_pixel_array_came_back);
|
||||
if (local_os2_surface->hmtx_use_private_fields)
|
||||
DosCloseMutexSem (local_os2_surface->hmtx_use_private_fields);
|
||||
free (local_os2_surface);
|
||||
}
|
||||
|
||||
return _cairo_surface_create_in_error (status);
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_os2_surface_create_for_window:
|
||||
* @hwnd_client_window: the window handle to bind the surface to
|
||||
* @width: the width of the surface
|
||||
* @height: the height of the surface
|
||||
*
|
||||
* Create a Cairo surface which is bound to a given window; the caller retains
|
||||
* ownership of the window. This is a convenience function for use with
|
||||
* windows that will only be updated when cairo_os2_surface_refresh_window()
|
||||
* is called (usually in response to a WM_PAINT message). It avoids the need
|
||||
* to create a persistent HPS for every window and assumes that one will be
|
||||
* supplied by the caller when a cairo function needs one. If it isn't, an
|
||||
* HPS will be created on-the-fly and released before the function which needs
|
||||
* it returns.
|
||||
*
|
||||
* Return value: the newly created surface
|
||||
*
|
||||
* Since: 1.10
|
||||
**/
|
||||
cairo_surface_t *
|
||||
cairo_os2_surface_create_for_window (HWND hwnd_client_window,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
cairo_os2_surface_t *local_os2_surface;
|
||||
|
||||
/* A window handle must be provided. */
|
||||
if (!hwnd_client_window) {
|
||||
return _cairo_surface_create_in_error (
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY));
|
||||
}
|
||||
|
||||
/* Create the surface. */
|
||||
local_os2_surface = (cairo_os2_surface_t *)
|
||||
cairo_os2_surface_create (0, width, height);
|
||||
|
||||
/* If successful, save the hwnd & turn off automatic repainting. */
|
||||
if (!local_os2_surface->image_surface->base.status) {
|
||||
local_os2_surface->hwnd_client_window = hwnd_client_window;
|
||||
local_os2_surface->blit_as_changes = FALSE;
|
||||
}
|
||||
|
||||
return (cairo_surface_t *)local_os2_surface;
|
||||
}
|
||||
|
||||
|
@ -1014,6 +1061,7 @@ cairo_os2_surface_refresh_window (cairo_surface_t *surface,
|
|||
{
|
||||
cairo_os2_surface_t *local_os2_surface;
|
||||
RECTL rclTemp;
|
||||
HPS hpsTemp = 0;
|
||||
|
||||
local_os2_surface = (cairo_os2_surface_t *) surface;
|
||||
if ((!local_os2_surface) ||
|
||||
|
@ -1023,9 +1071,19 @@ cairo_os2_surface_refresh_window (cairo_surface_t *surface,
|
|||
return;
|
||||
}
|
||||
|
||||
/* Manage defaults (NULLs) */
|
||||
if (!hps_begin_paint)
|
||||
/* If an HPS wasn't provided, see if we can get one. */
|
||||
if (!hps_begin_paint) {
|
||||
hps_begin_paint = local_os2_surface->hps_client_window;
|
||||
if (!hps_begin_paint) {
|
||||
if (local_os2_surface->hwnd_client_window) {
|
||||
hpsTemp = WinGetPS(local_os2_surface->hwnd_client_window);
|
||||
hps_begin_paint = hpsTemp;
|
||||
}
|
||||
/* No HPS & no way to get one, so exit */
|
||||
if (!hps_begin_paint)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (prcl_begin_paint_rect == NULL) {
|
||||
/* Update the whole window! */
|
||||
|
@ -1046,6 +1104,8 @@ cairo_os2_surface_refresh_window (cairo_surface_t *surface,
|
|||
!= NO_ERROR)
|
||||
{
|
||||
/* Could not get mutex! */
|
||||
if (hpsTemp)
|
||||
WinReleasePS(hpsTemp);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1073,6 +1133,9 @@ cairo_os2_surface_refresh_window (cairo_surface_t *surface,
|
|||
}
|
||||
|
||||
DosReleaseMutexSem (local_os2_surface->hmtx_use_private_fields);
|
||||
|
||||
if (hpsTemp)
|
||||
WinReleasePS(hpsTemp);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
|
@ -1109,10 +1172,10 @@ _cairo_os2_surface_finish (void *abstract_surface)
|
|||
* @surface: the cairo surface to associate with the window handle
|
||||
* @hwnd_client_window: the window handle of the client window
|
||||
*
|
||||
* Sets window handle for surface. If Cairo wants to blit into the window
|
||||
* because it is set to blit as the surface changes (see
|
||||
* cairo_os2_surface_set_manual_window_refresh()), then there are two ways it
|
||||
* can choose:
|
||||
* Sets window handle for surface; the caller retains ownership of the window.
|
||||
* If Cairo wants to blit into the window because it is set to blit as the
|
||||
* surface changes (see cairo_os2_surface_set_manual_window_refresh()), then
|
||||
* there are two ways it can choose:
|
||||
* If it knows the HWND of the surface, then it invalidates that area, so the
|
||||
* application will get a WM_PAINT message and it can call
|
||||
* cairo_os2_surface_refresh_window() to redraw that area. Otherwise cairo itself
|
||||
|
@ -1214,6 +1277,74 @@ cairo_os2_surface_get_manual_window_refresh (cairo_surface_t *surface)
|
|||
return !(local_os2_surface->blit_as_changes);
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_os2_surface_get_hps:
|
||||
* @surface: the cairo surface to be querued
|
||||
* @hps: HPS currently associated with the surface (if any)
|
||||
*
|
||||
* This API retrieves the HPS associated with the surface.
|
||||
*
|
||||
* Return value: %CAIRO_STATUS_SUCCESS if the hps could be retrieved,
|
||||
* %CAIRO_STATUS_SURFACE_TYPE_MISMATCH if the surface is not an OS/2 surface,
|
||||
* %CAIRO_STATUS_NULL_POINTER if the hps argument is null
|
||||
*
|
||||
* Since: 1.10
|
||||
**/
|
||||
cairo_status_t
|
||||
cairo_os2_surface_get_hps (cairo_surface_t *surface,
|
||||
HPS *hps)
|
||||
{
|
||||
cairo_os2_surface_t *local_os2_surface;
|
||||
|
||||
local_os2_surface = (cairo_os2_surface_t *) surface;
|
||||
if ((!local_os2_surface) ||
|
||||
(local_os2_surface->base.backend != &cairo_os2_surface_backend))
|
||||
{
|
||||
/* Invalid parameter (wrong surface)! */
|
||||
return _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
|
||||
}
|
||||
if (!hps)
|
||||
{
|
||||
return _cairo_error (CAIRO_STATUS_NULL_POINTER);
|
||||
}
|
||||
*hps = local_os2_surface->hps_client_window;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_os2_surface_set_hps:
|
||||
* @surface: the cairo surface to associate with the HPS
|
||||
* @hps: new HPS to be associated with the surface (the HPS may be null)
|
||||
*
|
||||
* This API replaces the HPS associated with the surface with a new one.
|
||||
* The caller retains ownership of the HPS and must dispose of it after
|
||||
* the surface has been destroyed or it has been replaced by another
|
||||
* call to this function.
|
||||
*
|
||||
* Return value: %CAIRO_STATUS_SUCCESS if the hps could be replaced,
|
||||
* %CAIRO_STATUS_SURFACE_TYPE_MISMATCH if the surface is not an OS/2 surface,
|
||||
*
|
||||
* Since: 1.10
|
||||
**/
|
||||
cairo_status_t
|
||||
cairo_os2_surface_set_hps (cairo_surface_t *surface,
|
||||
HPS hps)
|
||||
{
|
||||
cairo_os2_surface_t *local_os2_surface;
|
||||
|
||||
local_os2_surface = (cairo_os2_surface_t *) surface;
|
||||
if ((!local_os2_surface) ||
|
||||
(local_os2_surface->base.backend != &cairo_os2_surface_backend))
|
||||
{
|
||||
/* Invalid parameter (wrong surface)! */
|
||||
return _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
|
||||
}
|
||||
local_os2_surface->hps_client_window = hps;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_os2_surface_mark_dirty_rectangle (void *surface,
|
||||
int x,
|
||||
|
@ -1331,5 +1462,11 @@ static const cairo_surface_backend_t cairo_os2_surface_backend = {
|
|||
NULL, /* stroke */
|
||||
NULL, /* fill */
|
||||
NULL, /* show_glyphs */
|
||||
NULL /* snapshot */
|
||||
NULL, /* snapshot */
|
||||
NULL, /* is_similar */
|
||||
NULL, /* fill_stroke */
|
||||
NULL, /* create_solid_pattern_surface */
|
||||
NULL, /* can_repaint_solid_pattern_surface */
|
||||
NULL, /* has_show_text_glyphs */
|
||||
NULL /* show_text_glyphs */
|
||||
};
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Peter Weilbacher <mozilla@Weilbacher.org>
|
||||
* Rich Walsh <dragtext@e-vertise.com>
|
||||
*/
|
||||
|
||||
#ifndef _CAIRO_OS2_H_
|
||||
|
@ -65,6 +66,11 @@ cairo_os2_surface_create (HPS hps_client_window,
|
|||
int width,
|
||||
int height);
|
||||
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_os2_surface_create_for_window (HWND hwnd_client_window,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
cairo_public void
|
||||
cairo_os2_surface_set_hwnd (cairo_surface_t *surface,
|
||||
HWND hwnd_client_window);
|
||||
|
@ -87,6 +93,14 @@ cairo_os2_surface_set_manual_window_refresh (cairo_surface_t *surface,
|
|||
cairo_public cairo_bool_t
|
||||
cairo_os2_surface_get_manual_window_refresh (cairo_surface_t *surface);
|
||||
|
||||
cairo_public cairo_status_t
|
||||
cairo_os2_surface_get_hps (cairo_surface_t *surface,
|
||||
HPS *hps);
|
||||
|
||||
cairo_public cairo_status_t
|
||||
cairo_os2_surface_set_hps (cairo_surface_t *surface,
|
||||
HPS hps);
|
||||
|
||||
#else /* CAIRO_HAS_OS2_SURFACE */
|
||||
# error Cairo was not compiled with support for the OS/2 backend
|
||||
#endif /* CAIRO_HAS_OS2_SURFACE */
|
||||
|
|
|
@ -114,11 +114,14 @@
|
|||
#define cairo_os2_fini _moz_cairo_os2_fini
|
||||
#define cairo_os2_init _moz_cairo_os2_init
|
||||
#define cairo_os2_surface_create _moz_cairo_os2_surface_create
|
||||
#define cairo_os2_surface_create_for_window _moz_cairo_os2_surface_create_for_window
|
||||
#define cairo_os2_surface_get_manual_window_refresh _moz_cairo_os2_surface_get_manual_window_refresh
|
||||
#define cairo_os2_surface_refresh_window _moz_cairo_os2_surface_refresh_window
|
||||
#define cairo_os2_surface_set_hwnd _moz_cairo_os2_surface_set_hwnd
|
||||
#define cairo_os2_surface_set_manual_window_refresh _moz_cairo_os2_surface_set_manual_window_refresh
|
||||
#define cairo_os2_surface_set_size _moz_cairo_os2_surface_set_size
|
||||
#define cairo_os2_surface_get_hps _moz_cairo_os2_surface_get_hps
|
||||
#define cairo_os2_surface_set_hps _moz_cairo_os2_surface_set_hps
|
||||
#define cairo_paint _moz_cairo_paint
|
||||
#define cairo_paint_with_alpha _moz_cairo_paint_with_alpha
|
||||
#define cairo_path_destroy _moz_cairo_path_destroy
|
||||
|
|
|
@ -169,8 +169,8 @@ const PRUint8 kUseAltDCFor_SURFACE_DIM = 0x08; // Use it for getting the Sur
|
|||
#endif
|
||||
|
||||
#define NS_IDEVICE_CONTEXT_IID \
|
||||
{ 0x41391E7C, 0x9ED5, 0x4A60, \
|
||||
{ 0x88, 0x72, 0x06, 0x15, 0x73, 0xF5, 0x0E, 0xE7 } }
|
||||
{ 0x30a9d22f, 0x8e51, 0x40af, \
|
||||
{ 0xa1, 0xf5, 0x48, 0xe3, 0x00, 0xaa, 0xa9, 0x27 } }
|
||||
|
||||
typedef enum {
|
||||
eSystemFont_Caption, // css2
|
||||
|
@ -231,8 +231,7 @@ public:
|
|||
NS_IMETHOD CreateRenderingContext(nsIWidget *aWidget, nsIRenderingContext *&aContext) = 0;
|
||||
|
||||
/**
|
||||
* Create a rendering context and initialize it. This API should *only* be called
|
||||
* on device contexts whose SupportsNativeWidgets() method return PR_FALSE.
|
||||
* Create a rendering context and initialize it.
|
||||
* @param aContext out parameter for new rendering context
|
||||
* @return error status
|
||||
*/
|
||||
|
@ -245,15 +244,6 @@ public:
|
|||
*/
|
||||
NS_IMETHOD CreateRenderingContextInstance(nsIRenderingContext *&aContext) = 0;
|
||||
|
||||
/**
|
||||
* Query the device to see if it supports native widgets. If not, then
|
||||
* nsIWidget->Create() calls should be avoided.
|
||||
* @param aSupportsWidgets out paramater. If PR_TRUE, then native widgets
|
||||
* can be created.
|
||||
* @return error status
|
||||
*/
|
||||
NS_IMETHOD SupportsNativeWidgets(PRBool &aSupportsWidgets) = 0;
|
||||
|
||||
/**
|
||||
* We are in the process of creating the native widget for aWidget.
|
||||
* Do any device-specific processing required to initialize the
|
||||
|
|
|
@ -790,13 +790,6 @@ nsThebesDeviceContext::CreateRenderingContextInstance(nsIRenderingContext *&aCon
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsThebesDeviceContext::SupportsNativeWidgets(PRBool &aSupportsWidgets)
|
||||
{
|
||||
aSupportsWidgets = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsThebesDeviceContext::ClearCachedSystemFonts()
|
||||
{
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче