This commit is contained in:
Dan Witte 2010-08-20 23:51:54 -07:00
Родитель c4c08588db df5c0741c3
Коммит 55caf04feb
512 изменённых файлов: 21041 добавлений и 8448 удалений

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

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

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

@ -76,7 +76,7 @@
button.style.visibility = "hidden";
} else {
var newLabel = button.getAttribute("label2");
button.setAttribute("label", newLabel);
button.textContent = newLabel;
buttonClicked = true;
}
}
@ -139,11 +139,9 @@
</div>
<!-- Button -->
<xul:button xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
id="errorTryAgain"
label="&retry.label;"
label2="&robots.dontpress;"
oncommand="robotButton();" />
<button id="errorTryAgain"
label2="&robots.dontpress;"
onclick="robotButton();">&retry.label;</button>
<img src="chrome://browser/content/aboutRobots-widget-left.png"
style="position: absolute; bottom: -12px; left: -10px;"/>

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

@ -60,7 +60,7 @@
</html:head>
<popupset id="contextmenus">
<popup id="tabListContext">
<menupopup id="tabListContext">
<menuitem label="&tabs.context.openTab.label;"
accesskey="&tabs.context.openTab.accesskey;"
oncommand="RemoteTabViewer.openSelected()"
@ -82,7 +82,7 @@
accesskey="&tabs.context.refreshList.accesskey;"
oncommand="RemoteTabViewer.buildList()"
showFor="all"/>
</popup>
</menupopup>
</popupset>
<richlistbox context="tabListContext" id="tabsList" seltype="multiple"
align="center" flex="1"

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

@ -3,6 +3,8 @@
%brandDTD;
<!ENTITY % browserDTD SYSTEM "chrome://browser/locale/browser.dtd" >
%browserDTD;
<!ENTITY % baseMenuDTD SYSTEM "chrome://browser/locale/baseMenuOverlay.dtd" >
%baseMenuDTD;
<!ENTITY % globalRegionDTD SYSTEM "chrome://global-region/locale/region.dtd">
%globalRegionDTD;
<!ENTITY % charsetDTD SYSTEM "chrome://global/locale/charsetOverlay.dtd" >

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

@ -653,7 +653,6 @@ HistoryMenu.prototype = {
m = undoPopup.appendChild(document.createElement("menuitem"));
m.id = "menu_restoreAllTabs";
m.setAttribute("label", strings.getString("menuRestoreAllTabs.label"));
m.setAttribute("accesskey", strings.getString("menuRestoreAllTabs.accesskey"));
m.addEventListener("command", function() {
for (var i = 0; i < undoItems.length; i++)
undoCloseTab();
@ -731,7 +730,6 @@ HistoryMenu.prototype = {
let m = undoPopup.appendChild(document.createElement("menuitem"));
m.id = "menu_restoreAllWindows";
m.setAttribute("label", gNavigatorBundle.getString("menuRestoreAllWindows.label"));
m.setAttribute("accesskey", gNavigatorBundle.getString("menuRestoreAllWindows.accesskey"));
m.setAttribute("oncommand",
"for (var i = 0; i < " + undoItems.length + "; i++) undoCloseWindow();");
},

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

@ -139,32 +139,32 @@ let TabView = {
// ----------
updateContextMenu: function(tab, popup) {
let separator = document.getElementById("context_tabViewNamedGroups");
let isEmpty = true;
while(popup.lastChild && popup.lastChild.id != "context_namedGroups")
popup.removeChild(popup.lastChild);
while (popup.firstChild && popup.firstChild != separator)
popup.removeChild(popup.firstChild);
let self = this;
this._initFrame(function() {
let activeGroup = tab.tabItem.parent;
let groupItems = self._window.GroupItems.groupItems;
groupItems.forEach(function(groupItem) {
if (groupItem.getTitle().length > 0 &&
(!activeGroup || activeGroup.id != groupItem.id)) {
let menuItem = self._createGroupMenuItem(groupItem);
popup.appendChild(menuItem);
popup.insertBefore(menuItem, separator);
isEmpty = false;
}
});
document.getElementById("context_namedGroups").hidden = isEmpty;
separator.hidden = isEmpty;
});
},
// ----------
_createGroupMenuItem : function(groupItem) {
let menuItem = document.createElement("menuitem")
menuItem.setAttribute("class", "group");
menuItem.setAttribute("label", groupItem.getTitle());
menuItem.setAttribute(
"oncommand",

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

@ -1450,12 +1450,6 @@ function delayedStartup(isLoadingBlank, mustLoadSidebar) {
// bookmark-all-tabs command
gBookmarkAllTabsHandler.init();
// Attach a listener to watch for "command" events bubbling up from error
// pages. This lets us fix bugs like 401575 which require error page UI to
// do privileged things, without letting error pages have any privilege
// themselves.
gBrowser.addEventListener("command", BrowserOnCommand, false);
ctrlTab.readPref();
gPrefService.addObserver(ctrlTab.prefName, ctrlTab, false);
gPrefService.addObserver(allTabs.prefName, allTabs, false);
@ -2491,9 +2485,9 @@ function BrowserImport()
/**
* Handle command events bubbling up from error page content
*/
function BrowserOnCommand(event) {
function BrowserOnClick(event) {
// Don't trust synthetic events
if (!event.isTrusted)
if (!event.isTrusted || event.target.localName != "button")
return;
var ot = event.originalTarget;
@ -3588,6 +3582,9 @@ function updateEditUIVisibility()
let editMenuPopupState = document.getElementById("menu_EditPopup").state;
let contextMenuPopupState = document.getElementById("contentAreaContextMenu").state;
let placesContextMenuPopupState = document.getElementById("placesContext").state;
#ifdef MENUBAR_CAN_AUTOHIDE
let appMenuPopupState = document.getElementById("appmenu-popup").state;
#endif
// The UI is visible if the Edit menu is opening or open, if the context menu
// is open, or if the toolbar has been customized to include the Cut, Copy,
@ -3598,6 +3595,10 @@ function updateEditUIVisibility()
contextMenuPopupState == "open" ||
placesContextMenuPopupState == "showing" ||
placesContextMenuPopupState == "open" ||
#ifdef MENUBAR_CAN_AUTOHIDE
appMenuPopupState == "showing" ||
appMenuPopupState == "open" ||
#endif
document.getElementById("cut-button") ||
document.getElementById("copy-button") ||
document.getElementById("paste-button") ? true : false;
@ -4080,6 +4081,7 @@ var XULBrowserWindow = {
onStateChange: function (aWebProgress, aRequest, aStateFlags, aStatus) {
const nsIWebProgressListener = Ci.nsIWebProgressListener;
const nsIChannel = Ci.nsIChannel;
if (aStateFlags & nsIWebProgressListener.STATE_START &&
aStateFlags & nsIWebProgressListener.STATE_IS_NETWORK) {
@ -4526,17 +4528,33 @@ var CombinedStopReload = {
};
var TabsProgressListener = {
#ifdef MOZ_CRASHREPORTER
onStateChange: function (aBrowser, aWebProgress, aRequest, aStateFlags, aStatus) {
#ifdef MOZ_CRASHREPORTER
if (aRequest instanceof Ci.nsIChannel &&
aStateFlags & Ci.nsIWebProgressListener.STATE_START &&
aStateFlags & Ci.nsIWebProgressListener.STATE_IS_DOCUMENT &&
gCrashReporter.enabled) {
gCrashReporter.annotateCrashReport("URL", aRequest.URI.spec);
}
},
#endif
// Attach a listener to watch for "click" events bubbling up from error
// pages and other similar page. This lets us fix bugs like 401575 which
// require error page UI to do privileged things, without letting error
// pages have any privilege themselves.
// We can't look for this during onLocationChange since at that point the
// document URI is not yet the about:-uri of the error page.
if (aStateFlags & Ci.nsIWebProgressListener.STATE_STOP &&
/^about:/.test(aBrowser.contentWindow.document.documentURI)) {
aBrowser.addEventListener("click", BrowserOnClick, false);
aBrowser.addEventListener("pagehide", function () {
aBrowser.removeEventListener("click", BrowserOnClick, false);
aBrowser.removeEventListener("pagehide", arguments.callee, true);
}, true);
}
},
onLocationChange: function (aBrowser, aWebProgress, aRequest, aLocationURI) {
// Filter out any sub-frame loads
if (aBrowser.contentWindow == aWebProgress.DOMWindow)
@ -4675,7 +4693,7 @@ nsBrowserAccess.prototype = {
}
}
function onViewToolbarsPopupShowing(aEvent) {
function onViewToolbarsPopupShowing(aEvent, aInsertPoint) {
var popup = aEvent.target;
if (popup != aEvent.currentTarget)
return;
@ -4689,7 +4707,7 @@ function onViewToolbarsPopupShowing(aEvent) {
popup.removeChild(deadItem);
}
var firstMenuItem = popup.firstChild;
var firstMenuItem = aInsertPoint || popup.firstChild;
for (i = 0; i < gNavToolbox.childNodes.length; ++i) {
var toolbar = gNavToolbox.childNodes[i];
@ -5844,15 +5862,12 @@ function warnAboutClosingWindow() {
return gBrowser.warnAboutClosingTabs(true);
// Figure out if there's at least one other browser window around.
let foundOtherBrowserWindow = false;
let e = Services.wm.getEnumerator("navigator:browser");
while (e.hasMoreElements() && !foundOtherBrowserWindow) {
while (e.hasMoreElements()) {
let win = e.getNext();
if (win != window && win.toolbar.visible)
foundOtherBrowserWindow = true;
return gBrowser.warnAboutClosingTabs(true);
}
if (foundOtherBrowserWindow)
return gBrowser.warnAboutClosingTabs(true);
let os = Services.obs;
@ -7454,6 +7469,10 @@ let gPrivateBrowsingUI = {
// Disable the menu item in auto-start mode
document.getElementById("privateBrowsingItem")
.setAttribute("disabled", "true");
#ifdef MENUBAR_CAN_AUTOHIDE
document.getElementById("appmenu_privateBrowsing")
.setAttribute("disabled", "true");
#endif
document.getElementById("Tools:PrivateBrowsing")
.setAttribute("disabled", "true");
}
@ -7521,6 +7540,10 @@ let gPrivateBrowsingUI = {
// Enable the menu item in after exiting the auto-start mode
document.getElementById("privateBrowsingItem")
.removeAttribute("disabled");
#ifdef MENUBAR_CAN_AUTOHIDE
document.getElementById("appmenu_privateBrowsing")
.removeAttribute("disabled");
#endif
document.getElementById("Tools:PrivateBrowsing")
.removeAttribute("disabled");
@ -7539,6 +7562,11 @@ let gPrivateBrowsingUI = {
let pbMenuItem = document.getElementById("privateBrowsingItem");
pbMenuItem.setAttribute("label", pbMenuItem.getAttribute(aMode + "label"));
pbMenuItem.setAttribute("accesskey", pbMenuItem.getAttribute(aMode + "accesskey"));
#ifdef MENUBAR_CAN_AUTOHIDE
let appmenupbMenuItem = document.getElementById("appmenu_privateBrowsing");
appmenupbMenuItem.setAttribute("label", appmenupbMenuItem.getAttribute(aMode + "label"));
appmenupbMenuItem.setAttribute("accesskey", appmenupbMenuItem.getAttribute(aMode + "accesskey"));
#endif
},
toggleMode: function PBUI_toggleMode() {

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

@ -128,13 +128,11 @@
oncommand="gBrowser.unpinTab(TabContextMenu.contextTab);"/>
<menu id="context_tabViewMenu" label="&moveToGroup.label;"
accesskey="&moveToGroup.accesskey;">
<menupopup id="context_tabViewMenuPopup"
<menupopup id="context_tabViewMenuPopup"
onpopupshowing="if (event.target == this) TabView.updateContextMenu(TabContextMenu.contextTab, this);">
<menuitem label="&moveToNewGroup.label;"
accesskey="&moveToNewGroup.accesskey;"
<menuseparator id="context_tabViewNamedGroups" hidden="true"/>
<menuitem label="&moveToNewGroup.label;"
oncommand="TabView.moveTabTo(TabContextMenu.contextTab, null);"/>
<menuitem id="context_namedGroups" label="&namedGroups.label;"
disabled="true"/>
</menupopup>
</menu>
<menuseparator/>
@ -451,148 +449,300 @@
</popupset>
#ifdef MENUBAR_CAN_AUTOHIDE
<hbox id="appmenu-button-container">
<button id="appmenu-button"
type="menu"
label="&brandShortName;"
style="-moz-user-focus: ignore;">
<menupopup id="appmenu-popup">
<hbox flex="1" class="split-menuitem">
<menuitem id="appmenu_newTab"
class="split-menuitem-item"
flex="1"
label="&tabCmd.label;"
command="cmd_newNavigatorTab"/>
<menu class="split-menuitem-menu">
<menupopup>
<menuitem id="appmenu_newTab_sub"
label="&tabCmd.label;"
command="cmd_newNavigatorTab"/>
<menuitem id="appmenu_newNavigator"
label="&newNavigatorCmd.label;"
command="cmd_newNavigator"/>
</menupopup>
</menu>
</hbox>
<menuseparator/>
<menuitem id="appmenu_savePage"
label="&savePageCmd.label;"
command="Browser:SavePage"/>
<menuitem id="appmenu_sendLink"
label="&sendPageCmd.label;"
command="Browser:SendLink"/>
<hbox flex="1" class="split-menuitem">
<menuitem id="appmenu_print"
class="split-menuitem-item"
flex="1"
label="&appMenuPrintCmd.label;"
command="cmd_print"/>
<menu class="split-menuitem-menu">
<menupopup>
<menuitem id="menu_printSetup"
label="&printSetupCmd.label;"
command="cmd_pageSetup"/>
<menuitem id="menu_printPreview"
label="&printPreviewCmd.label;"
command="cmd_printPreview"/>
</menupopup>
</menu>
</hbox>
<menuitem id="appmenu_find"
label="&findOnCmd.label;"
command="cmd_find"/>
<menuseparator/>
<menu id="appmenu_history"
label="&historyMenu.label;">
<menupopup id="appmenu_history_popup"
placespopup="true"
oncommand="this.parentNode._placesView._onCommand(event);"
onclick="checkForMiddleClick(this, event);"
onpopupshowing="if (!this.parentNode._placesView)
new HistoryMenu(event);"
tooltip="bhTooltip"
popupsinherittooltip="true">
<menuitem id="appmenu_sanitizeHistory"
label="&clearRecentHistory.label;"
key="key_sanitize"
command="Tools:Sanitize"/>
<menuseparator/>
<menuitem id="appmenu_showAllHistory"
label="&showAllHistoryCmd2.label;"
key="showAllHistoryKb"
command="Browser:ShowAllHistory"/>
<menuseparator class="hide-if-empty-places-result"/>
</menupopup>
</menu>
<menuseparator/>
<menu id="appmenu_developer"
label="&developerMenu.label;">
<menupopup id="appmenu_developer_popup">
<menuitem id="appmenu_pageSource"
label="&pageSourceCmd.label;"
command="View:PageSource"/>
<menuseparator/>
<menuitem id="appmenu_pageInspect"
type="checkbox"
label="&inspectMenu.label;"
command="Tools:Inspect"/>
<menuitem id="appmenu_webConsole"
label="&webConsoleCmd.label;"
oncommand="HUDConsoleUI.toggleHUD();"/>
</menupopup>
</menu>
<menuseparator/>
<menu id="appmenu_customize"
label="&appMenuCustomize.label;">
<menupopup id="appmenu_customizeMenu"
onpopupshowing="onViewToolbarsPopupShowing(event);">
<menuseparator/>
<menuitem command="cmd_ToggleTabsOnTop"
type="checkbox"
label="&viewTabsOnTop.label;"/>
<menuitem id="appmenu_toolbarLayout"
label="&appMenuToolbarLayout.label;"
command="cmd_CustomizeToolbars"/>
<menu id="appmenu_sidebars"
label="&appMenuSidebars.label;">
<menupopup id="appmenu_sidebarMenu">
<menuitem id="appmenu_bookmarksSidebar"
key="viewBookmarksSidebarKb"
observes="viewBookmarksSidebar"/>
<menuitem id="appmenu_historySidebar"
key="key_gotoHistory"
observes="viewHistorySidebar"
label="&historyButton.label;"/>
<hbox id="appmenu-button-container">
<button id="appmenu-button"
type="menu"
label="&brandShortName;"
style="-moz-user-focus: ignore;">
<menupopup id="appmenu-popup"
onpopupshowing="updateEditUIVisibility();">
<hbox>
<vbox id="appmenuPrimaryPane">
<hbox flex="1"
class="split-menuitem">
<menuitem id="appmenu_newTab"
class="split-menuitem-item"
flex="1"
label="&tabCmd.label;"
command="cmd_newNavigatorTab"/>
<menu class="split-menuitem-menu">
<menupopup>
<menuitem id="appmenu_newTab_popup"
label="&tabCmd.label;"
command="cmd_newNavigatorTab"/>
<menuitem id="appmenu_newNavigator"
label="&newNavigatorCmd.label;"
command="cmd_newNavigator"/>
<menuseparator/>
<menuitem id="appmenu_openFile"
label="&openFileCmd.label;"
command="Browser:OpenFile"/>
</menupopup>
</menu>
</hbox>
<menuitem id="appmenu_privateBrowsing"
class="menuitem-iconic"
label="&privateBrowsingCmd.start.label;"
accesskey="&privateBrowsingCmd.start.accesskey;"
startlabel="&privateBrowsingCmd.start.label;"
stoplabel="&privateBrowsingCmd.stop.label;"
command="Tools:PrivateBrowsing"/>
<menuseparator class="menu-seperator"/>
<hbox class="split-menuitem">
<menuitem id="appmenu-edit-menuitem"
label="&editMenu.label;"
disabled="true"/>
<toolbarbutton id="appmenu-cut"
class="appmenu-edit-button"
command="cmd_cut"
onclick="if (!this.disabled) hidePopup();"
tooltiptext="&cutButton.tooltip;"/>
<toolbarbutton id="appmenu-copy"
class="appmenu-edit-button"
command="cmd_copy"
onclick="if (!this.disabled) hidePopup();"
tooltiptext="&copyButton.tooltip;"/>
<toolbarbutton id="appmenu-paste"
class="appmenu-edit-button"
command="cmd_paste"
onclick="if (!this.disabled) hidePopup();"
tooltiptext="&pasteButton.tooltip;"/>
</hbox>
<menuitem id="appmenu_find"
label="&appMenuFind.label;"
command="cmd_find"/>
<menuseparator/>
<menuitem id="appmenu_savePage"
label="&savePageCmd.label;"
command="Browser:SavePage"/>
<menuitem id="appmenu_sendLink"
label="&sendPageCmd.label;"
command="Browser:SendLink"/>
<hbox flex="1"
class="split-menuitem">
<menuitem id="appmenu_print"
class="menuitem-iconic"
flex="1"
label="&printCmd.label;"
command="cmd_print"/>
<menu class="split-menuitem-menu">
<menupopup>
<menuitem id="appmenu_print_popup"
class="menuitem-iconic"
label="&printCmd.label;"
command="cmd_print"/>
<menuitem id="appmenu_printPreview"
label="&printPreviewCmd.label;"
command="cmd_printPreview"/>
<menuitem id="appmenu_printSetup"
label="&printSetupCmd.label;"
command="cmd_pageSetup"/>
</menupopup>
</menu>
<menuseparator/>
<menuitem id="appmenu_openAddons"
</hbox>
<menuseparator/>
<menu id="appmenu_developer"
label="&developerMenu.label;">
<menupopup id="appmenu_developer_popup">
<menuitem id="appmenu_webConsole"
label="&webConsoleCmd.label;"
type="checkbox"
oncommand="HUDConsoleUI.toggleHUD();"/>
<menuitem id="appmenu_pageInspect"
label="&inspectMenu.label;"
type="checkbox"
command="Tools:Inspect"/>
<menuseparator/>
<menuitem id="appmenu_pageSource"
label="&viewPageSourceCmd.label;"
command="View:PageSource"/>
<menuseparator/>
<menuitem label="&goOfflineCmd.label;"
accesskey="&goOfflineCmd.accesskey;"
type="checkbox"
oncommand="BrowserOffline.toggleOfflineStatus();"/>
</menupopup>
</menu>
<menuseparator/>
<menuitem id="appmenu_fullScreen"
label="&fullScreenCmd.label;"
type="checkbox"
observes="View:FullScreen"/>
<menuitem id="appmenu-quit"
class="menuitem-iconic"
#ifdef XP_WIN
label="&quitApplicationCmdWin.label;"
#else
label="&quitApplicationCmd.label;"
#endif
command="cmd_quitApplication"/>
</vbox>
<vbox id="appmenuSecondaryPane">
<hbox class="split-menuitem">
<menuitem id="appmenu_BookmarkItem"
class="menuitem-iconic"
flex="1"
label="&bookmarksMenu.label;"
command="Browser:ShowAllBookmarks"/>
<menu id="appmenuBookmarkMenu"
class="split-menuitem-menu">
<menupopup id="appmenuBookmarkMenu_popup"
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'));"
tooltip="bhTooltip"
popupsinherittooltip="true">
<menuseparator id="appmenuBookmarkMenu_unsorted_seperator"/>
<menuitem id="appmenuBookmarkMenu_unsorted-menuitem"
label="&appMenuUnsorted.label;"
oncommand="PlacesCommandHook.showPlacesOrganizer('UnfiledBookmarks');"
class="menuitem-iconic"/>
<menuitem id="appmenuBookmarkMenu_organize_bookmarks"
label="&organizeBookmarks.label;"
key="manBookmarkKb"
command="Browser:ShowAllBookmarks"
context=""/>
<menuseparator/>
<menuitem id="appmenuBookmarkThisPage"
class="menuitem-iconic"
label="&bookmarkThisPageCmd.label;"
command="Browser:AddBookmarkAs"
key="addBookmarkAsKb"/>
<menuitem id="subscribeToPageMenuitem"
class="menuitem-iconic"
label="&subscribeToPageMenuitem.label;"
oncommand="return FeedHandler.subscribeToFeed(null, event);"
onclick="checkForMiddleClick(this, event);"
disabled="true"/>
<menu id="subscribeToPageMenupopup"
class="menu-iconic"
label="&subscribeToPageMenupopup.label;"
hidden="true">
<menupopup id="subscribeToPageSubmenuMenupopup"
onpopupshowing="return FeedHandler.buildFeedList(event.target);"
oncommand="return FeedHandler.subscribeToFeed(null, event);"
onclick="checkForMiddleClick(this, event);"/>
</menu>
<menuseparator/>
</menupopup>
</menu>
</hbox>
<hbox class="split-menuitem">
<menuitem id="appmenu_HistoryItem"
class="menuitem-iconic"
flex="1"
label="&historyMenu.label;"
command="Browser:ShowAllHistory"/>
<menu id="appmenu_history"
class="split-menuitem-menu">
<menupopup id="appmenu_history_popup"
placespopup="true"
oncommand="this.parentNode._placesView._onCommand(event);"
onclick="checkForMiddleClick(this, event);"
onpopupshowing="if (!this.parentNode._placesView) new HistoryMenu(event);"
tooltip="bhTooltip"
popupsinherittooltip="true">
<menuitem id="appmenu_showAllHistory"
label="&showAllHistoryCmd2.label;"
key="showAllHistoryKb"
command="Browser:ShowAllHistory"/>
<menuseparator/>
<menuitem id="appmenu_sanitizeHistory"
label="&clearRecentHistory.label;"
key="key_sanitize"
command="Tools:Sanitize"/>
<menuseparator class="hide-if-empty-places-result"/>
<menu id="historyUndoMenu"
label="&historyUndoMenu.label;"
disabled="true">
<menupopup id="historyUndoPopup"
onpopupshowing="_placesView.populateUndoSubmenu();"/>
</menu>
<menu id="historyUndoWindowMenu"
label="&historyUndoWindowMenu.label;"
disabled="true">
<menupopup id="historyUndoPopup"
onpopupshowing="_placesView.populateUndoWindowSubmenu();"/>
</menu>
<menuseparator/>
</menupopup>
</menu>
</hbox>
<menuitem id="appmenu_downloads"
label="&downloads.label;"
command="Tools:Downloads"/>
<spacer id="appmenuSecondaryPane-spacer"/>
<menuitem id="appmenu_addons"
class="menuitem-iconic"
label="&addons.label;"
command="Tools:Addons"/>
</menupopup>
</menu>
<menuitem id="appmenu_preferences"
<hbox class="split-menuitem">
<menuitem id="appmenu_customize"
label="&preferencesCmd.label;"
class="split-menuitem-item"
flex="1"
oncommand="openPreferences();"/>
<menu class="split-menuitem-menu"
label="&preferencesCmd.label;">
<menupopup id="appmenu_customizeMenu"
onpopupshowing="onViewToolbarsPopupShowing(event, (document.getElementById('appmenuToggleStatusbar')));">
<menuitem id="appmenu_preferences"
#ifdef XP_UNIX
label="&preferencesCmdUnix.label;"
label="&preferencesCmdUnix.label;"
#else
label="&preferencesCmd.label;"
label="&preferencesCmd.label;"
#endif
oncommand="openPreferences();"/>
<menuitem id="appmenu_openHelp"
label="&appMenuHelp.label;"
oncommand="openHelpLink('firefox-help')"
onclick="checkForMiddleClick(this, event);"/>
<menuseparator/>
<menuitem id="appmenu_quit"
#ifdef XP_WIN
label="&quitApplicationCmdWin.label;"
#else
label="&quitApplicationCmd.label;"
#endif
command="cmd_quitApplication"/>
</menupopup>
</button>
</hbox>
oncommand="openPreferences();"/>
<menuseparator/>
<menuitem id="appmenuToggleStatusbar"
type="checkbox"
command="cmd_toggleTaskbar"
observes="toggle_taskbar"/>
<menuseparator/>
<menuitem id="appmenuToggleTabs"
label="&viewTabsOnTop.label;"
type="checkbox"
command="cmd_ToggleTabsOnTop"/>
<menuitem id="appmenu_toolbarLayout"
label="&appMenuToolbarLayout.label;"
command="cmd_CustomizeToolbars"/>
</menupopup>
</menu>
</hbox>
<hbox class="split-menuitem">
<menuitem id="appmenu_helpItem"
flex="1"
label="&helpMenu.label;"
oncommand="openHelpLink('firefox-help')"/>
<menu id="appmenu_about_menu"
class="split-menuitem-menu">
<menupopup>
<menuitem id="appmenu_openHelp"
label="&helpMenu.label;"
oncommand="openHelpLink('firefox-help')"
onclick="checkForMiddleClick(this, event);"/>
<menuitem id="appmenu_help_getting_started"
label="&appMenuGettingStarted.label;"
oncommand="gBrowser.selectedTab = gBrowser.addTab('http://www.mozilla.com/firefox/central/');"
onclick="checkForMiddleClick(this, event);"/>
<menuseparator/>
<menuitem id="appmenu_help_about"
label="&aboutProduct.label;"
oncommand="openAboutDialog();"/>
</menupopup>
</menu>
</hbox>
</vbox>
</hbox>
</menupopup>
</button>
</hbox>
#endif
<deck flex="1" id="tab-view-deck">

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

@ -1202,8 +1202,6 @@
b._fastFind = this.fastFind;
b.droppedLinkHandler = handleDroppedLink;
this.tabContainer.adjustTabstrip();
// Dispatch a new tab notification. We do this once we're
// entirely done, so that things are in a consistent state
// even if the event listener opens or closes tabs.
@ -1258,10 +1256,8 @@
<parameter name="aAll"/>
<body>
<![CDATA[
var tabsToClose = this.tabs.length;
if (!aAll)
tabsToClose = this.visibleTabs.length - (1 + this._numPinnedTabs);
var tabsToClose = (aAll ? this.tabs.length : this.visibleTabs.length - 1)
- gBrowser._numPinnedTabs;
if (tabsToClose <= 1)
return true;
@ -2744,11 +2740,13 @@
return;
if (this.mTabstrip.smoothScroll) {
let selected = this.selectedItem.getBoundingClientRect();
let selected = !this.selectedItem.pinned &&
this.selectedItem.getBoundingClientRect();
// Can we make both the new tab and the selected tab completely visible?
if (Math.max(tab.right - selected.left, selected.right - tab.left) <=
scrollRect.width) {
if (!selected ||
Math.max(tab.right - selected.left, selected.right - tab.left) <=
scrollRect.width) {
this.mTabstrip.ensureElementIsVisible(aTab);
return;
}
@ -2849,6 +2847,8 @@
if (tab.parentNode != this)
return;
this.adjustTabstrip();
if (tab.getAttribute("selected") == "true") {
this._fillTrailingGap();
this._handleTabSelect();

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

@ -13,7 +13,7 @@ function test() {
waitForExplicitFinish();
Services.prefs.setBoolPref("browser.tabs.animate", true);
nextAsyncText();
preperForNextText();
}
function tabAdded() {
@ -46,10 +46,15 @@ var asyncTests = [
}
];
function nextAsyncText() {
function preperForNextText() {
info("tests left: " + asyncTests.length + "; starting next");
var tab = gBrowser.addTab("about:blank", { skipAnimation: true });
executeSoon(function () {
nextAsyncText(tab);
});
}
function nextAsyncText(tab) {
var gotCloseEvent = false;
tab.addEventListener("TabClose", function () {
@ -68,7 +73,7 @@ function nextAsyncText() {
is(tab.parentNode, null, "tab removed after at most " + MAX_WAIT_TIME + " ms");
if (asyncTests.length)
nextAsyncText();
preperForNextText();
else
cleanup();
}, DEFAULT_ANIMATION_LENGTH);

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

@ -246,7 +246,7 @@
<h2>&certerror.whatShouldIDo.heading;</h2>
<div id="whatShouldIDoContentText">
<p>&certerror.whatShouldIDo.content;</p>
<xul:button xmlns:xul='http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul' id='getMeOutOfHereButton' label='&certerror.getMeOutOfHere.label;'/>
<button id='getMeOutOfHereButton'>&certerror.getMeOutOfHere.label;</button>
</div>
</div>
@ -262,7 +262,7 @@
<div>
<p>&certerror.expert.content;</p>
<p>&certerror.expert.contentPara2;</p>
<xul:button xmlns:xul='http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul' id='exceptionDialogButton' label='&certerror.addException.label;'/>
<button id='exceptionDialogButton'>&certerror.addException.label;</button>
</div>
</div>
</div>

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

@ -0,0 +1,39 @@
/* ***** 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):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#feedSubscribeLine {
-moz-binding: url(subscribe.xml#feedreaderUI);
}

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

@ -16,14 +16,17 @@
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<html id="feedHandler"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>&feedPage.title;</title>
<link rel="stylesheet"
href="chrome://browser/skin/feeds/subscribe.css"
type="text/css"
media="all"/>
<link rel="stylesheet"
href="chrome://browser/content/feeds/subscribe.css"
type="text/css"
media="all"/>
<script type="application/javascript"
src="chrome://browser/content/feeds/subscribe.js"/>
</head>
@ -34,30 +37,8 @@
<p id="feedSubscriptionInfo1" />
<p id="feedSubscriptionInfo2" />
</div>
<!-- XXXmano this can't have any whitespace in it. Otherwise you would see
how much XUL-in-XHTML sucks, see bug 348830 -->
<div id="feedSubscribeLine"
><xul:vbox
><xul:hbox align="center"
><xul:description id="subscribeUsingDescription"
/><xul:menulist id="handlersMenuList" aria-labelledby="subscribeUsingDescription"
><xul:menupopup menugenerated="true" id="handlersMenuPopup"
><xul:menuitem id="liveBookmarksMenuItem" label="&feedLiveBookmarks;" class="menuitem-iconic" image="chrome://browser/skin/page-livemarks.png" selected="true"
/><xul:menuseparator
/></xul:menupopup
></xul:menulist
></xul:hbox
><xul:hbox
><xul:checkbox id="alwaysUse" checked="false"
/></xul:hbox
><xul:hbox align="center"
><xul:spacer flex="1"
/><xul:button label="&feedSubscribeNow;" id="subscribeButton"
/></xul:hbox
></xul:vbox
></div
></div>
<div id="feedSubscribeLine"></div>
</div>
</div>
<script type="application/javascript">

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

@ -0,0 +1,72 @@
<!-- ***** 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):
-
- Alternatively, the contents of this file may be used under the terms of
- either the GNU General Public License Version 2 or later (the "GPL"), or
- the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- in which case the provisions of the GPL or the LGPL are applicable instead
- of those above. If you wish to allow use of your version of this file only
- under the terms of either the GPL or the LGPL, and not to allow others to
- use your version of this file under the terms of the MPL, indicate your
- decision by deleting the provisions above and replace them with the notice
- and other provisions required by the LGPL or the GPL. 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 ***** -->
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE bindings [
<!ENTITY % feedDTD
SYSTEM "chrome://browser/locale/feeds/subscribe.dtd">
%feedDTD;
]>
<bindings id="feedBindings"
xmlns="http://www.mozilla.org/xbl"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<binding id="feedreaderUI">
<content>
<xul:vbox>
<xul:hbox align="center">
<xul:description anonid="subscribeUsingDescription" class="subscribeUsingDescription"/>
<xul:menulist anonid="handlersMenuList" class="handlersMenuList" aria-labelledby="subscribeUsingDescription">
<xul:menupopup menugenerated="true" anonid="handlersMenuPopup" class="handlersMenuPopup">
<xul:menuitem anonid="liveBookmarksMenuItem" label="&feedLiveBookmarks;" class="menuitem-iconic liveBookmarksMenuItem" image="chrome://browser/skin/page-livemarks.png" selected="true"/>
<xul:menuseparator/>
</xul:menupopup>
</xul:menulist>
</xul:hbox>
<xul:hbox>
<xul:checkbox anonid="alwaysUse" class="alwaysUse" checked="false"/>
</xul:hbox>
<xul:hbox align="center">
<xul:spacer flex="1"/>
<xul:button label="&feedSubscribeNow;" anonid="subscribeButton" class="subscribeButton"/>
</xul:hbox>
</xul:vbox>
</content>
<resources>
<stylesheet src="chrome://browser/skin/feeds/subscribe-ui.css"/>
</resources>
</binding>
</bindings>

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

@ -1,3 +1,5 @@
browser.jar:
* content/browser/feeds/subscribe.xhtml (content/subscribe.xhtml)
* content/browser/feeds/subscribe.js (content/subscribe.js)
* content/browser/feeds/subscribe.xml (content/subscribe.xml)
content/browser/feeds/subscribe.css (content/subscribe.css)

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

@ -730,6 +730,15 @@ FeedWriter.prototype = {
Cu.evalInSandbox(codeStr, this._contentSandbox);
},
/**
* Helper method to get an element in the XBL binding where the handler
* selection UI lives
*/
_getUIElement: function FW__getUIElement(id) {
return this._document.getAnonymousElementByAttribute(
this._document.getElementById("feedSubscribeLine"), "anonid", id);
},
/**
* Displays a prompt from which the user may choose a (client) feed reader.
* @return - true if a feed reader was selected, false otherwise.
@ -775,7 +784,7 @@ FeedWriter.prototype = {
},
_setAlwaysUseCheckedState: function FW__setAlwaysUseCheckedState(feedType) {
var checkbox = this._document.getElementById("alwaysUse");
var checkbox = this._getUIElement("alwaysUse");
if (checkbox) {
var alwaysUse = false;
try {
@ -802,18 +811,17 @@ FeedWriter.prototype = {
}
this._contentSandbox.subscribeUsing =
this._document.getElementById("subscribeUsingDescription");
this._getUIElement("subscribeUsingDescription");
this._contentSandbox.label = this._getString(stringLabel);
var codeStr = "subscribeUsing.setAttribute('value', label);"
Cu.evalInSandbox(codeStr, this._contentSandbox);
},
_setAlwaysUseLabel: function FW__setAlwaysUseLabel() {
var checkbox = this._document.getElementById("alwaysUse");
var checkbox = this._getUIElement("alwaysUse");
if (checkbox) {
var handlersMenuList = this._document.getElementById("handlersMenuList");
if (handlersMenuList) {
var handlerName = this._getSelectedItemFromMenulist(handlersMenuList)
if (this._handlersMenuList) {
var handlerName = this._getSelectedItemFromMenulist(this._handlersMenuList)
.getAttribute("label");
var stringLabel = "alwaysUseForFeeds";
switch (this._getFeedType()) {
@ -843,7 +851,7 @@ FeedWriter.prototype = {
}
if (event.type == "command") {
switch (event.target.id) {
switch (event.target.getAttribute("anonid")) {
case "subscribeButton":
this.subscribe();
break;
@ -856,8 +864,7 @@ FeedWriter.prototype = {
* selected). If we don't show the filepicker here, it will be shown
* when clicking "Subscribe Now".
*/
var popupbox = this._document.getElementById("handlersMenuList")
.firstChild.boxObject;
var popupbox = this._handlersMenuList.firstChild.boxObject;
popupbox.QueryInterface(Components.interfaces.nsIPopupBoxObject);
if (popupbox.popupState == "hiding" && !this._chooseClientApp()) {
// Select the (per-prefs) selected handler if no application was
@ -884,11 +891,10 @@ FeedWriter.prototype = {
switch (handler) {
case "web": {
var handlersMenuList = this._document.getElementById("handlersMenuList");
if (handlersMenuList) {
if (this._handlersMenuList) {
var url = prefs.getComplexValue(getPrefWebForType(feedType), Ci.nsISupportsString).data;
var handlers =
handlersMenuList.getElementsByAttribute("webhandlerurl", url);
this._handlersMenuList.getElementsByAttribute("webhandlerurl", url);
if (handlers.length == 0) {
LOG("FeedWriter._setSelectedHandler: selected web handler isn't in the menulist")
return;
@ -926,7 +932,7 @@ FeedWriter.prototype = {
}
case "bookmarks":
default: {
var liveBookmarksMenuItem = this._document.getElementById("liveBookmarksMenuItem");
var liveBookmarksMenuItem = this._getUIElement("liveBookmarksMenuItem");
if (liveBookmarksMenuItem)
this._safeDoCommand(liveBookmarksMenuItem);
}
@ -934,7 +940,7 @@ FeedWriter.prototype = {
},
_initSubscriptionUI: function FW__initSubscriptionUI() {
var handlersMenuPopup = this._document.getElementById("handlersMenuPopup");
var handlersMenuPopup = this._getUIElement("handlersMenuPopup");
if (!handlersMenuPopup)
return;
@ -957,11 +963,13 @@ FeedWriter.prototype = {
codeStr = "header.className = 'feedBackground'; ";
}
var liveBookmarksMenuItem = this._getUIElement("liveBookmarksMenuItem");
// Last-selected application
var menuItem = this._document.createElementNS(XUL_NS, "menuitem");
menuItem.id = "selectedAppMenuItem";
menuItem.className = "menuitem-iconic";
var menuItem = liveBookmarksMenuItem.cloneNode(false);
menuItem.removeAttribute("selected");
menuItem.setAttribute("anonid", "selectedAppMenuItem");
menuItem.className = "menuitem-iconic selectedAppMenuItem";
menuItem.setAttribute("handlerType", "client");
try {
var prefs = Cc["@mozilla.org/preferences-service;1"].
@ -990,9 +998,10 @@ FeedWriter.prototype = {
this._defaultSystemReader = Cc["@mozilla.org/browser/shell-service;1"].
getService(Ci.nsIShellService).
defaultFeedReader;
menuItem = this._document.createElementNS(XUL_NS, "menuitem");
menuItem.id = "defaultHandlerMenuItem";
menuItem.className = "menuitem-iconic";
menuItem = liveBookmarksMenuItem.cloneNode(false);
menuItem.removeAttribute("selected");
menuItem.setAttribute("anonid", "defaultHandlerMenuItem");
menuItem.className = "menuitem-iconic defaultHandlerMenuItem";
menuItem.setAttribute("handlerType", "client");
this._initMenuItemWithFile(menuItem, this._defaultSystemReader);
@ -1011,9 +1020,10 @@ FeedWriter.prototype = {
}
// "Choose Application..." menuitem
menuItem = this._document.createElementNS(XUL_NS, "menuitem");
menuItem.id = "chooseApplicationMenuItem";
menuItem.className = "menuitem-iconic";
menuItem = liveBookmarksMenuItem.cloneNode(false);
menuItem.removeAttribute("selected");
menuItem.setAttribute("anonid", "chooseApplicationMenuItem");
menuItem.className = "menuitem-iconic chooseApplicationMenuItem";
menuItem.setAttribute("label", this._getString("chooseApplicationMenuItem"));
this._contentSandbox.chooseAppMenuItem = menuItem;
@ -1021,7 +1031,7 @@ FeedWriter.prototype = {
// separator
this._contentSandbox.chooseAppSep =
this._document.createElementNS(XUL_NS, "menuseparator")
menuItem = liveBookmarksMenuItem.nextSibling.cloneNode(false);
codeStr += "handlersMenuPopup.appendChild(chooseAppSep); ";
Cu.evalInSandbox(codeStr, this._contentSandbox);
@ -1036,7 +1046,8 @@ FeedWriter.prototype = {
var handlers = wccr.getContentHandlers(this._getMimeTypeForFeedType(feedType));
if (handlers.length != 0) {
for (var i = 0; i < handlers.length; ++i) {
menuItem = this._document.createElementNS(XUL_NS, "menuitem");
menuItem = liveBookmarksMenuItem.cloneNode(false);
menuItem.removeAttribute("selected");
menuItem.className = "menuitem-iconic";
menuItem.setAttribute("label", handlers[i].name);
menuItem.setAttribute("handlerType", "web");
@ -1072,8 +1083,7 @@ FeedWriter.prototype = {
handlersMenuPopup.addEventListener("command", this, false);
// Set up the "Subscribe Now" button
this._document
.getElementById("subscribeButton")
this._getUIElement("subscribeButton")
.addEventListener("command", this, false);
// first-run ui
@ -1139,6 +1149,7 @@ FeedWriter.prototype = {
_document: null,
_feedURI: null,
_feedPrincipal: null,
_handlersMenuList: null,
// nsIFeedWriter
init: function FW_init(aWindow) {
@ -1149,6 +1160,8 @@ FeedWriter.prototype = {
this._window = window;
this._document = window.document;
this._document.getElementById("feedSubscribeLine").offsetTop;
this._handlersMenuList = this._getUIElement("handlersMenuList");
var secman = Cc["@mozilla.org/scriptsecuritymanager;1"].
getService(Ci.nsIScriptSecurityManager);
@ -1195,11 +1208,9 @@ FeedWriter.prototype = {
},
close: function FW_close() {
this._document
.getElementById("handlersMenuPopup")
this._getUIElement("handlersMenuPopup")
.removeEventListener("command", this, false);
this._document
.getElementById("subscribeButton")
this._getUIElement("subscribeButton")
.removeEventListener("command", this, false);
this._document = null;
this._window = null;
@ -1246,19 +1257,17 @@ FeedWriter.prototype = {
var prefs = Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefBranch);
var defaultHandler = "reader";
var useAsDefault = this._document.getElementById("alwaysUse")
.getAttribute("checked");
var useAsDefault = this._getUIElement("alwaysUse").getAttribute("checked");
var handlersMenuList = this._document.getElementById("handlersMenuList");
var selectedItem = this._getSelectedItemFromMenulist(handlersMenuList);
var selectedItem = this._getSelectedItemFromMenulist(this._handlersMenuList);
// Show the file picker before subscribing if the
// choose application menuitem was chosen using the keyboard
if (selectedItem.id == "chooseApplicationMenuItem") {
if (selectedItem.getAttribute("anonid") == "chooseApplicationMenuItem") {
if (!this._chooseClientApp())
return;
selectedItem = this._getSelectedItemFromMenulist(handlersMenuList);
selectedItem = this._getSelectedItemFromMenulist(this._handlersMenuList);
}
if (selectedItem.hasAttribute("webhandlerurl")) {
@ -1282,7 +1291,7 @@ FeedWriter.prototype = {
}
}
else {
switch (selectedItem.id) {
switch (selectedItem.getAttribute("anonid")) {
case "selectedAppMenuItem":
prefs.setComplexValue(getPrefAppForType(feedType), Ci.nsILocalFile,
this._selectedApp);
@ -1389,8 +1398,7 @@ FeedWriter.prototype = {
// Go through the readers menu and look for the corresponding
// reader menu-item for the page if any.
var spec = aURI.spec;
var handlersMenulist = this._document.getElementById("handlersMenuList");
var possibleHandlers = handlersMenulist.firstChild.childNodes;
var possibleHandlers = this._handlersMenuList.firstChild.childNodes;
for (var i=0; i < possibleHandlers.length ; i++) {
if (possibleHandlers[i].getAttribute("webhandlerurl") == spec) {
this._setFaviconForWebReader(aURI, possibleHandlers[i]);

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

@ -438,7 +438,7 @@ BrowserGlue.prototype = {
var browser = browserEnum.getNext();
var tabbrowser = browser.document.getElementById("content");
if (tabbrowser)
pagecount += tabbrowser.browsers.length;
pagecount += tabbrowser.browsers.length - tabbrowser._numPinnedTabs;
}
this._saveSession = false;
@ -469,7 +469,7 @@ BrowserGlue.prototype = {
getService(Ci.nsIPrivateBrowsingService).
privateBrowsingEnabled;
if (!showPrompt || inPrivateBrowsing)
return false;
return;
var quitBundle = Services.strings.createBundle("chrome://browser/locale/quitDialog.properties");
var brandBundle = Services.strings.createBundle("chrome://branding/locale/brand.properties");

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

@ -145,9 +145,9 @@
<!-- Start Private Browsing -->
<div id="startPrivateBrowsingDesc" class="showNormal">
<button xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
id="startPrivateBrowsing" label="&privatebrowsingpage.startPrivateBrowsing.label;"
accesskey="&privatebrowsingpage.startPrivateBrowsing.accesskey;"/>
<button id="startPrivateBrowsing"
accesskey="&privatebrowsingpage.startPrivateBrowsing.accesskey;"
>&privatebrowsingpage.startPrivateBrowsing.label;</button>
</div>
<!-- Footer -->

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

@ -212,15 +212,12 @@
<!-- Action buttons -->
<div id="buttons">
<!-- Commands handled in browser.js -->
<xul:button xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
id="getMeOutButton" label="&safeb.palm.accept.label;"/>
<xul:button xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
id="reportButton" label="&safeb.palm.reportPage.label;"/>
<button id="getMeOutButton">&safeb.palm.accept.label;</button>
<button id="reportButton">&safeb.palm.reportPage.label;</button>
</div>
</div>
<div id="ignoreWarning">
<xul:button xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
id="ignoreWarningButton" label="&safeb.palm.decline.label;"/>
<button id="ignoreWarningButton">&safeb.palm.decline.label;</button>
</div>
</div>
<!--

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

@ -19,7 +19,7 @@ function testMalware() {
ok(el, "Ignore warning button should be present for malware");
var style = content.getComputedStyle(el, null);
is(style.display, "-moz-box", "Ignore Warning button should be display:-moz-box for malware");
is(style.display, "inline", "Ignore Warning button should be display:inline for malware");
// Now launch the phishing test
window.addEventListener("DOMContentLoaded", testPhishing, true);
@ -33,7 +33,7 @@ function testPhishing() {
ok(el, "Ignore warning button should be present for phishing");
var style = content.getComputedStyle(el, null);
is(style.display, "-moz-box", "Ignore Warning button should be display:-moz-box for phishing");
is(style.display, "inline", "Ignore Warning button should be display:inline for phishing");
gBrowser.removeCurrentTab();
finish();

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

@ -157,7 +157,14 @@ SessionStartup.prototype = {
if (this._sessionType != Ci.nsISessionStartup.NO_SESSION) {
// wait for the first browser window to open
Services.obs.addObserver(this, "domwindowopened", true);
// Don't reset the initial window's default args (i.e. the home page(s))
// if all stored tabs are pinned.
if (!initialState.windows ||
!initialState.windows.every(function (win)
win.tabs.every(function (tab) tab.pinned)))
Services.obs.addObserver(this, "domwindowopened", true);
Services.obs.addObserver(this, "browser:purge-session-history", true);
}
},

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

@ -198,10 +198,8 @@ SessionStoreService.prototype = {
// whether we clearing history on shutdown
_clearingOnShutdown: false,
#ifndef XP_MACOSX
// whether the last window was closed and should be restored
_restoreLastWindow: false,
#endif
/* ........ Global Event Handlers .............. */
@ -290,10 +288,8 @@ SessionStoreService.prototype = {
catch (ex) { debug("The session file is invalid: " + ex); }
}
// remove the session data files if crash recovery is disabled
if (!this._resume_from_crash)
this._clearDisk();
else { // create a backup if the session data file exists
if (this._resume_from_crash) {
// create a backup if the session data file exists
try {
if (this._sessionFileBackup.exists())
this._sessionFileBackup.remove(false);
@ -318,12 +314,14 @@ SessionStoreService.prototype = {
* quit-application-granted, quit-application
*/
_uninit: function sss_uninit() {
if (this._doResumeSession()) { // save all data for session resuming
this.saveState(true);
}
else { // discard all session related data
// save all data for session resuming
this.saveState(true);
if (!this._doResumeSession()) {
// discard all session related data
this._clearDisk();
}
// Make sure to break our cycle with the save timer
if (this._saveTimer) {
this._saveTimer.cancel();
@ -359,15 +357,13 @@ SessionStoreService.prototype = {
// freeze the data at what we've got (ignoring closing windows)
this._loadState = STATE_QUITTING;
break;
#ifndef XP_MACOSX
case "browser-lastwindow-close-granted":
// last browser window is quitting.
// remember to restore the last window when another browser window is openend
// remember to restore the last window when another browser window is opened
// do not account for pref(resume_session_once) at this point, as it might be
// set by another observer getting this notice after us
this._restoreLastWindow = true;
break;
#endif
case "quit-application":
if (aData == "restart") {
this._prefBranch.setBoolPref("sessionstore.resume_session_once", true);
@ -481,10 +477,9 @@ SessionStoreService.prototype = {
this._resume_from_crash = this._prefBranch.getBoolPref("sessionstore.resume_from_crash");
// either create the file with crash recovery information or remove it
// (when _loadState is not STATE_RUNNING, that file is used for session resuming instead)
if (this._resume_from_crash)
this.saveState(true);
else if (this._loadState == STATE_RUNNING)
if (!this._resume_from_crash)
this._clearDisk();
this.saveState(true);
break;
}
break;
@ -611,7 +606,8 @@ SessionStoreService.prototype = {
// make sure that the restored tabs are first in the window
this._initialState._firstTabs = true;
this._restoreCount = this._initialState.windows ? this._initialState.windows.length : 0;
this.restoreWindow(aWindow, this._initialState, this._isCmdLineEmpty(aWindow));
this.restoreWindow(aWindow, this._initialState,
this._isCmdLineEmpty(aWindow, this._initialState));
delete this._initialState;
// _loadState changed from "stopped" to "running"
@ -631,15 +627,13 @@ SessionStoreService.prototype = {
let followUp = this._statesToRestore[aWindow.__SS_restoreID].windows.length == 1;
this.restoreWindow(aWindow, this._statesToRestore[aWindow.__SS_restoreID], true, followUp);
}
#ifndef XP_MACOSX
else if (this._restoreLastWindow && aWindow.toolbar.visible &&
this._closedWindows.length && this._doResumeSession() &&
this._closedWindows.length &&
!this._inPrivateBrowsing) {
// default to the most-recently closed window
// don't use popup windows
let state = null;
this._closedWindows = this._closedWindows.filter(function(aWinState) {
let newClosedWindows = this._closedWindows.filter(function(aWinState) {
if (!state && !aWinState.isPopup) {
state = aWinState;
return false;
@ -648,9 +642,16 @@ SessionStoreService.prototype = {
});
if (state) {
delete state.hidden;
state = { windows: [state] };
this._restoreCount = 1;
this.restoreWindow(aWindow, state, this._isCmdLineEmpty(aWindow));
#ifndef XP_MACOSX
if (!this._doResumeSession())
#endif
state.tabs = state.tabs.filter(function (tab) tab.pinned);
if (state.tabs.length > 0) {
this._closedWindows = newClosedWindows;
this._restoreCount = 1;
state = { windows: [state] };
this.restoreWindow(aWindow, state, this._isCmdLineEmpty(aWindow, state));
}
}
// we actually restored the session just now.
this._prefBranch.setBoolPref("sessionstore.resume_session_once", false);
@ -661,7 +662,6 @@ SessionStoreService.prototype = {
// undoCloseWindow was executed.
this._restoreLastWindow = false;
}
#endif
var tabbrowser = aWindow.gBrowser;
@ -1140,14 +1140,19 @@ SessionStoreService.prototype = {
* Store all session data for a window
* @param aWindow
* Window reference
* @param aPinnedOnly
* Bool collect pinned tabs only
*/
_saveWindowHistory: function sss_saveWindowHistory(aWindow) {
_saveWindowHistory: function sss_saveWindowHistory(aWindow, aPinnedOnly) {
var tabbrowser = aWindow.gBrowser;
var tabs = tabbrowser.tabs;
var tabsData = this._windows[aWindow.__SSi].tabs = [];
for (var i = 0; i < tabs.length; i++)
for (var i = 0; i < tabs.length; i++) {
if (aPinnedOnly && !tabs[i].pinned)
break;
tabsData.push(this._collectTabData(tabs[i]));
}
this._windows[aWindow.__SSi].selected = tabbrowser.mTabBox.selectedIndex + 1;
},
@ -1435,16 +1440,15 @@ SessionStoreService.prototype = {
*/
_updateTextAndScrollData: function sss_updateTextAndScrollData(aWindow) {
var browsers = aWindow.gBrowser.browsers;
for (var i = 0; i < browsers.length; i++) {
this._windows[aWindow.__SSi].tabs.forEach(function (tabData, i) {
if (browsers[i].__SS_data &&
browsers[i].__SS_data._tabStillLoading)
return; // ignore incompletely initialized tabs
try {
var tabData = this._windows[aWindow.__SSi].tabs[i];
if (browsers[i].__SS_data &&
browsers[i].__SS_data._tabStillLoading)
continue; // ignore incompletely initialized tabs
this._updateTextAndScrollDataForTab(aWindow, browsers[i], tabData);
}
catch (ex) { debug(ex); } // get as much data as possible, ignore failures (might succeed the next time)
}
}, this);
},
/**
@ -1751,12 +1755,14 @@ SessionStoreService.prototype = {
},
/**
* serialize session data as Ini-formatted string
* gather session data as object
* @param aUpdateAll
* Bool update all windows
* @returns string
* @param aPinnedOnly
* Bool collect pinned tabs only
* @returns object
*/
_getCurrentState: function sss_getCurrentState(aUpdateAll) {
_getCurrentState: function sss_getCurrentState(aUpdateAll, aPinnedOnly) {
this._handleClosedWindows();
var activeWindow = this._getMostRecentBrowserWindow();
@ -1767,7 +1773,7 @@ SessionStoreService.prototype = {
if (!this._isWindowLoaded(aWindow)) // window data is still in _statesToRestore
return;
if (aUpdateAll || this._dirtyWindows[aWindow.__SSi] || aWindow == activeWindow) {
this._collectWindowData(aWindow);
this._collectWindowData(aWindow, aPinnedOnly);
}
else { // always update the window features (whose change alone never triggers a save operation)
this._updateWindowFeatures(aWindow);
@ -1813,6 +1819,17 @@ SessionStoreService.prototype = {
}
#endif
if (aPinnedOnly) {
total = total.filter(function (win) {
win.tabs = win.tabs.filter(function (tab) tab.pinned);
return win.tabs.length > 0;
});
if (total.length == 0)
return null;
lastClosedWindowsCopy = [];
}
if (activeWindow) {
this.activeWindowSSiCache = activeWindow.__SSi || "";
}
@ -1844,12 +1861,12 @@ SessionStoreService.prototype = {
return { windows: total };
},
_collectWindowData: function sss_collectWindowData(aWindow) {
_collectWindowData: function sss_collectWindowData(aWindow, aPinnedOnly) {
if (!this._isWindowLoaded(aWindow))
return;
// update the internal state data for this window
this._saveWindowHistory(aWindow);
this._saveWindowHistory(aWindow, aPinnedOnly);
this._updateTextAndScrollData(aWindow);
this._updateCookieHosts(aWindow);
this._updateWindowFeatures(aWindow);
@ -2561,8 +2578,7 @@ SessionStoreService.prototype = {
this._dirtyWindows[aWindow.__SSi] = true;
}
if (!this._saveTimer && this._resume_from_crash &&
!this._inPrivateBrowsing) {
if (!this._saveTimer && !this._inPrivateBrowsing) {
// interval until the next disk operation is allowed
var minimalDelay = this._lastSaveTime + this._interval - Date.now();
@ -2584,15 +2600,23 @@ SessionStoreService.prototype = {
* Bool update all windows
*/
saveState: function sss_saveState(aUpdateAll) {
// if crash recovery is disabled, only save session resuming information
if (!this._resume_from_crash && this._loadState == STATE_RUNNING)
return;
// if we're in private browsing mode, do nothing
if (this._inPrivateBrowsing)
return;
var oState = this._getCurrentState(aUpdateAll);
var pinnedOnly = false;
if (this._loadState == STATE_QUITTING && !this._doResumeSession() ||
/* if crash recovery is disabled, only save session resuming information */
this._loadState == STATE_RUNNING && !this._resume_from_crash)
pinnedOnly = true;
var oState = this._getCurrentState(aUpdateAll, pinnedOnly);
if (!oState)
return;
if (pinnedOnly)
this._prefBranch.setBoolPref("sessionstore.resume_session_once", true);
oState.session = {
state: this._loadState == STATE_RUNNING ? STATE_RUNNING_STR : STATE_STOPPED_STR,
lastUpdate: Date.now()
@ -2756,12 +2780,19 @@ SessionStoreService.prototype = {
* C.f.: nsBrowserContentHandler's defaultArgs implementation.
* @returns bool
*/
_isCmdLineEmpty: function sss_isCmdLineEmpty(aWindow) {
var defaultArgs = Cc["@mozilla.org/browser/clh;1"].
getService(Ci.nsIBrowserHandler).defaultArgs;
if (aWindow.arguments && aWindow.arguments[0] &&
aWindow.arguments[0] == defaultArgs)
aWindow.arguments[0] = null;
_isCmdLineEmpty: function sss_isCmdLineEmpty(aWindow, aState) {
var pinnedOnly = aState.windows &&
aState.windows.every(function (win)
win.tabs.every(function (tab) tab.pinned));
if (!pinnedOnly) {
let defaultArgs = Cc["@mozilla.org/browser/clh;1"].
getService(Ci.nsIBrowserHandler).defaultArgs;
if (aWindow.arguments &&
aWindow.arguments[0] &&
aWindow.arguments[0] == defaultArgs)
aWindow.arguments[0] = null;
}
return !aWindow.arguments || !aWindow.arguments[0];
},

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

@ -114,6 +114,7 @@ _BROWSER_TEST_FILES = \
browser_524745.js \
browser_528776.js \
browser_579879.js \
browser_580512.js \
browser_586147.js \
$(NULL)

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

@ -485,7 +485,7 @@ function test() {
/**
* Test 8: Test if closing can be denied on Mac
* Futhermore prepares the testNotificationCount test (Test 6)
* Futhermore prepares the testNotificationCount test (Test 7)
* @note: Mac only
*/
function testMacNotifications(nextFn, iteration) {

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

@ -0,0 +1,68 @@
const URIS_PINNED = ["about:license", "about:about"];
const URIS_NORMAL_A = ["about:mozilla"];
const URIS_NORMAL_B = ["about:buildconfig"];
function test() {
waitForExplicitFinish();
isnot(Services.prefs.getIntPref("browser.startup.page"), 3,
"pref to save session must not be set for this test");
ok(!Services.prefs.getBoolPref("browser.sessionstore.resume_session_once"),
"pref to save session once must not be set for this test");
document.documentElement.setAttribute("windowtype", "navigator:browsertestdummy");
openWinWithCb(closeFirstWin, URIS_PINNED.concat(URIS_NORMAL_A));
}
function closeFirstWin(win) {
win.gBrowser.pinTab(win.gBrowser.tabs[0]);
win.gBrowser.pinTab(win.gBrowser.tabs[1]);
win.BrowserTryToCloseWindow();
ok(win.closed, "window closed");
openWinWithCb(checkSecondWin, URIS_NORMAL_B, URIS_PINNED.concat(URIS_NORMAL_B));
}
function checkSecondWin(win) {
is(win.gBrowser.browsers[0].currentURI.spec, URIS_PINNED[0], "first pinned tab restored");
is(win.gBrowser.browsers[1].currentURI.spec, URIS_PINNED[1], "second pinned tab restored");
ok(win.gBrowser.tabs[0].pinned, "first pinned tab is still pinned");
ok(win.gBrowser.tabs[1].pinned, "second pinned tab is still pinned");
win.close();
// cleanup
document.documentElement.setAttribute("windowtype", "navigator:browser");
finish();
}
function openWinWithCb(cb, argURIs, expectedURIs) {
if (!expectedURIs)
expectedURIs = argURIs;
var win = openDialog("chrome://browser/content/", "_blank",
"chrome,all,dialog=no", argURIs.join("|"));
win.addEventListener("load", function () {
info("the window loaded");
var expectedLoads = expectedURIs.length;
win.gBrowser.addTabsProgressListener({
onStateChange: function (aBrowser, aWebProgress, aRequest, aStateFlags, aStatus) {
if (aRequest &&
aStateFlags & Ci.nsIWebProgressListener.STATE_STOP &&
aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK &&
expectedURIs.indexOf(aRequest.QueryInterface(Ci.nsIChannel).originalURI.spec) > -1 &&
--expectedLoads <= 0) {
win.gBrowser.removeTabsProgressListener(this);
info("all tabs loaded");
is(win.gBrowser.tabs.length, expectedURIs.length, "didn't load any unexpected tabs");
executeSoon(function () {
cb(win);
});
}
}
});
}, false);
}

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

@ -650,6 +650,9 @@ xpicleanup@BIN_SUFFIX@
modules/distribution.js
modules/DownloadLastDir.jsm
modules/DownloadPaths.jsm
#ifdef XP_WIN
modules/DownloadTaskbarProgress.jsm
#endif
modules/DownloadUtils.jsm
modules/FileUtils.jsm
modules/Geometry.jsm

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

@ -27,8 +27,6 @@
<!ENTITY moveToGroup.label "Move to Group">
<!ENTITY moveToGroup.accesskey "M">
<!ENTITY moveToNewGroup.label "New Group">
<!ENTITY moveToNewGroup.accesskey "N">
<!ENTITY namedGroups.label "Named Groups">
<!ENTITY bookmarkThisTab.label "Bookmark This Tab">
<!ENTITY bookmarkThisTab.accesskey "B">
<!ENTITY bookmarkAllTabs.label "Bookmark All Tabs…">
@ -267,11 +265,12 @@
<!ENTITY showAllHistoryCmd2.label "Show All History">
<!ENTITY showAllHistoryCmd.commandkey "H">
<!ENTITY appMenuPrintCmd.label "Print">
<!ENTITY appMenuCustomize.label "Customize">
<!ENTITY appMenuToolbarLayout.label "Toolbar Layout…">
<!ENTITY appMenuSidebars.label "Sidebars">
<!ENTITY appMenuHelp.label "Help">
<!ENTITY appMenuFind.label "Find…">
<!ENTITY appMenuUnsorted.label "Unsorted Bookmarks">
<!ENTITY appMenuGettingStarted.label "Getting Started">
<!ENTITY developerMenu.label "Developer">

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

@ -142,11 +142,9 @@ menuOpenAllInTabs.label=Open All in Tabs
# History menu
menuRestoreAllTabs.label=Restore All Tabs
menuRestoreAllTabs.accesskey=R
# LOCALIZATION NOTE (menuRestoreAllWindows, menuUndoCloseWindowLabel, menuUndoCloseWindowSingleTabLabel):
# see bug 394759
menuRestoreAllWindows.label=Restore All Windows
menuRestoreAllWindows.accesskey=R
# LOCALIZATION NOTE (menuUndoCloseWindowLabel): Semi-colon list of plural forms.
# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
# #1 Window Title, #2 Number of tabs

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

@ -178,6 +178,6 @@ netError.xhtml) because it exposes functionality specific to firefox. -->
<!ENTITY securityOverride.warningText "
<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>
<xul:button xmlns:xul='http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul' id='getMeOutOfHereButton' label='&securityOverride.getMeOutOfHereButton;'/>
<xul:button xmlns:xul='http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul' id='exceptionDialogButton' label='&securityOverride.exceptionButtonLabel;'/>
<button id='getMeOutOfHereButton'>&securityOverride.getMeOutOfHereButton;</button>
<button id='exceptionDialogButton'>&securityOverride.exceptionButtonLabel;</button>
">

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

@ -1529,9 +1529,3 @@ listitem.style-section {
panel[dimmed="true"] {
opacity: 0.5;
}
/* Tab view context menu */
#context_tabViewMenuPopup > menuitem.group {
-moz-padding-start: 40px;
}

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

@ -0,0 +1,61 @@
/* ***** 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):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
.alwaysUse {
padding: 5px;
}
.handlersMenuPopup > menuitem {
-moz-padding-start: 23px;
}
.handlersMenuPopup > menuitem.menuitem-iconic {
-moz-padding-start: 2px;
}
.handlersMenuPopup > .menuitem-iconic > .menu-iconic-left {
display: -moz-box;
min-width: 16px;
-moz-padding-end: 2px;
}
.chooseApplicationMenuItem {
list-style-image: url("moz-icon://dummy.exe?size=16");
}
#feedHeader[dir="rtl"] .handlersMenuList > menupopup {
direction: rtl;
}

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

@ -1,8 +1,3 @@
*[hidden] {
display: none;
}
html {
background: -moz-Dialog;
font: 3mm tahoma,arial,helvetica,sans-serif;
@ -67,33 +62,6 @@ html {
padding-top: 0.2em;
}
#alwaysUse {
padding: 5px;
}
#handlersMenuList > menupopup > menuitem {
-moz-padding-start: 23px;
}
#handlersMenuList > menupopup > menuitem.menuitem-iconic {
-moz-padding-start: 2px;
}
#handlersMenuList > menupopup > .menuitem-iconic > .menu-iconic-left {
display: -moz-box;
min-width: 16px;
-moz-padding-end: 2px;
}
#chooseApplicationMenuItem {
list-style-image: url("moz-icon://dummy.exe?size=16");
}
#feedHeader[dir="rtl"] #handlersMenuList > menupopup {
direction: rtl;
}
/* Don't print subscription UI */
@media print {
#feedHeaderContainer {

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

@ -42,6 +42,7 @@ browser.jar:
skin/classic/browser/feeds/audioFeedIcon.png (feeds/audioFeedIcon.png)
skin/classic/browser/feeds/audioFeedIcon16.png (feeds/audioFeedIcon16.png)
skin/classic/browser/feeds/subscribe.css (feeds/subscribe.css)
skin/classic/browser/feeds/subscribe-ui.css (feeds/subscribe-ui.css)
skin/classic/browser/places/bookmarksMenu.png (places/bookmarksMenu.png)
skin/classic/browser/places/bookmarksToolbar.png (places/bookmarksToolbar.png)
skin/classic/browser/places/calendar.png (places/calendar.png)

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

@ -2117,9 +2117,3 @@ panel[dimmed="true"] {
#sync-status-button.statusbarpanel-iconic {
padding: 0 5px;
}
/* Tab view context menu */
#context_tabViewMenuPopup > menuitem.group {
-moz-padding-start: 40px;
}

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

@ -0,0 +1,43 @@
/* ***** 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):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
.alwaysUse {
padding: 3px;
}
.chooseApplicationMenuItem {
list-style-image: url("chrome://browser/skin/preferences/application.png");
}

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

@ -1,8 +1,3 @@
*[hidden] {
display: none;
}
html {
background: -moz-Dialog;
font: 3mm tahoma,arial,helvetica,sans-serif;
@ -54,18 +49,10 @@ html {
padding: 0 1em 1em 2em;
}
#alwaysUse {
padding: 3px;
}
#feedHeader[firstrun="true"] #feedSubscribeLine {
padding-left: 3.7em;
}
#chooseApplicationMenuItem {
list-style-image: url("chrome://browser/skin/preferences/application.png");
}
/* Don't print subscription UI */
@media print {
#feedHeaderContainer {

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

@ -55,6 +55,7 @@ browser.jar:
skin/classic/browser/toolbarbutton-dropmarker.png
skin/classic/browser/urlbar-favicon-glow.png
skin/classic/browser/feeds/subscribe.css (feeds/subscribe.css)
skin/classic/browser/feeds/subscribe-ui.css (feeds/subscribe-ui.css)
skin/classic/browser/feeds/feedIcon.png (feeds/feedIcon.png)
skin/classic/browser/feeds/feedIcon16.png (feeds/feedIcon16.png)
skin/classic/browser/feeds/videoFeedIcon.png (feeds/videoFeedIcon.png)

Двоичные данные
browser/themes/winstripe/browser/appmenu-icons.png Normal file

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

После

Ширина:  |  Высота:  |  Размер: 2.2 KiB

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

@ -171,6 +171,114 @@ statusbarpanel#statusbar-display {
color: -moz-menuhovertext;
}
/* Style Firefox App Menu popup */
.appmenu-edit-button {
-moz-appearance: none;
border: 1px solid transparent;
padding: 2px;
background: transparent;
-moz-border-radius: 3px;
}
.appmenu-edit-button[disabled="true"] {
opacity: .3;
}
@media all and (-moz-windows-default-theme) {
#appmenu-popup {
-moz-appearance: none;
background: white;
border: 1px solid rgba(0,0,0,.5);
}
#appmenuPrimaryPane {
margin-right: -1px;
background-color: rgba(255,255,255,0.5);
border-right: 1px solid #c4c4c5;
padding-left: 2px;
}
#appmenuSecondaryPane {
-moz-appearance: none;
background-color: #f1f5fb;
-moz-box-shadow: 1px 0 3px rgb(204,214,234) inset;
border: 0;
padding-top: 5px;
font-family: "Segoe UI Semibold", "Segoe UI", sans-serif;
}
.appmenu-edit-button:not([disabled]):hover {
border: 1px solid #b8d6fb;
-moz-box-shadow: inset 0 0 1px white;
background: -moz-linear-gradient(#fafbfd, #ebf3fd);
-moz-transition: .2s ease-in;
}
}
#appmenuSecondaryPane-spacer {
min-height: 1em;
}
#appmenu_print,
#appmenu_print_popup,
.appmenu-edit-button,
#appmenu-quit {
list-style-image: url("appmenu-icons.png");
}
#appmenu-cut {
-moz-image-region: rect(0 16px 16px 0);
}
#appmenu-copy {
-moz-image-region: rect(0 32px 16px 16px);
}
#appmenu-paste {
-moz-image-region: rect(0 48px 16px 32px);
}
#appmenu_print,
#appmenu_print_popup {
-moz-image-region: rect(0 64px 16px 48px);
}
#appmenu-quit {
-moz-image-region: rect(0 80px 16px 64px);
}
#appmenu-edit-menuitem {
-moz-appearance: none;
background: transparent;
font-style: italic;
}
#appmenu_BookmarkItem {
list-style-image: url("chrome://browser/skin/places/bookmark.png");
-moz-image-region: rect(0px 48px 16px 32px);
}
#appmenu_privateBrowsing {
list-style-image: url("chrome://browser/skin/Privacy-16.png");
}
#appmenuBookmarkMenu_unsorted-menuitem {
list-style-image: url("chrome://browser/skin/places/unsortedBookmarks.png");
}
#appmenu_addons {
list-style-image: url("chrome://mozapps/skin/extensions/extensionGeneric-16.png");
}
#appmenu-button #subscribeToPageMenuitem:not([disabled]),
#appmenu-button #subscribeToPageMenupopup:not([hidden]) {
list-style-image: url("chrome://browser/skin/feeds/feed-icons-16.png");
-moz-image-region: rect(0px 16px 16px 0px);
}
#appmenuBookmarkThisPage {
list-style-image: url("chrome://browser/skin/places/bookmark.png");
-moz-image-region: rect(0 16px 16px 0);
}
/* XXX: stop-gap until the button can be drawn in the title bar */
%ifdef WINSTRIPE_AERO
@media not all and (-moz-windows-compositor) {
@ -880,7 +988,7 @@ toolbar:not([iconsize="small"])[mode="icons"] #forward-button:not([disabled="tru
}
#urlbar > .autocomplete-history-dropmarker:-moz-system-metric(touch-enabled) {
min-width: .64cm;
min-width: 6.4mozmm;
}
#urlbar > .autocomplete-history-dropmarker:hover:active,
@ -1123,7 +1231,7 @@ richlistitem[type="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-i
}
.tabbrowser-tabs:-moz-system-metric(touch-enabled) {
min-height: .73cm;
min-height: 7.3mozmm;
}
.tabbrowser-tabs:not([overflow="true"]) {
@ -1281,11 +1389,11 @@ richlistitem[type="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-i
#TabsToolbar > toolbarbutton,
#TabsToolbar > toolbarpaletteitem > toolbarbutton,
#TabsToolbar > #bookmarks-menu-button-container > #bookmarks-menu-button {
min-width: .81cm;
min-width: 8.1mozmm;
}
.tabs-newtab-button {
min-width: 1cm;
min-width: 10mozmm;
}
}
@ -1817,9 +1925,3 @@ listitem.style-section {
panel[dimmed="true"] {
opacity: 0.5;
}
/* Tab view context menu */
#context_tabViewMenuPopup > menuitem.group {
-moz-padding-start: 40px;
}

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

@ -0,0 +1,61 @@
/* ***** 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):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
.alwaysUse {
padding: 5px;
}
.handlersMenuPopup > menuitem {
-moz-padding-start: 23px;
}
.handlersMenuPopup > menuitem.menuitem-iconic {
-moz-padding-start: 2px;
}
.handlersMenuPopup > .menuitem-iconic > .menu-iconic-left {
display: -moz-box;
min-width: 16px;
-moz-padding-end: 2px;
}
.chooseApplicationMenuItem {
list-style-image: url("chrome://browser/skin/preferences/application.png");
}
#feedHeader[dir="rtl"] .handlersMenuList > menupopup {
direction: rtl;
}

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

@ -1,8 +1,3 @@
*[hidden] {
display: none;
}
html {
background: -moz-Dialog;
font: 3mm tahoma,arial,helvetica,sans-serif;
@ -33,6 +28,10 @@ html {
color: InfoText;
}
#feedIntroText {
display: none;
}
.feedBackground {
background: url("chrome://browser/skin/feeds/feedIcon.png") 0% 10% no-repeat InfoBackground;
}
@ -49,10 +48,6 @@ html {
background-position: 100% 10%;
}
#feedIntroText {
display: none;
}
#feedHeader[firstrun="true"] #feedIntroText {
padding-top: 0.1em;
-moz-padding-start: 0.6em;
@ -67,33 +62,6 @@ html {
padding-top: 0.2em;
}
#alwaysUse {
padding: 5px;
}
#handlersMenuList > menupopup > menuitem {
-moz-padding-start: 23px;
}
#handlersMenuList > menupopup > menuitem.menuitem-iconic {
-moz-padding-start: 2px;
}
#handlersMenuList > menupopup > .menuitem-iconic > .menu-iconic-left {
display: -moz-box;
min-width: 16px;
-moz-padding-end: 2px;
}
#chooseApplicationMenuItem {
list-style-image: url("chrome://browser/skin/preferences/application.png");
}
#feedHeader[dir="rtl"] #handlersMenuList > menupopup {
direction: rtl;
}
/* Don't print subscription UI */
@media print {
#feedHeaderContainer {

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

@ -12,6 +12,7 @@ browser.jar:
skin/classic/browser/aboutSyncTabs.css
#endif
skin/classic/browser/actionicon-tab.png
skin/classic/browser/appmenu-icons.png
skin/classic/browser/appmenu-dropmarker.png
* skin/classic/browser/browser.css (browser.css)
* skin/classic/browser/engineManager.css (engineManager.css)
@ -54,6 +55,7 @@ browser.jar:
skin/classic/browser/feeds/videoFeedIcon.png (feeds/videoFeedIcon.png)
skin/classic/browser/feeds/videoFeedIcon16.png (feeds/videoFeedIcon16.png)
skin/classic/browser/feeds/subscribe.css (feeds/subscribe.css)
skin/classic/browser/feeds/subscribe-ui.css (feeds/subscribe-ui.css)
skin/classic/browser/places/places.css (places/places.css)
* skin/classic/browser/places/organizer.css (places/organizer.css)
skin/classic/browser/places/bookmark.png (places/bookmark.png)
@ -125,6 +127,7 @@ browser.jar:
#endif
skin/classic/aero/browser/actionicon-tab.png (actionicon-tab.png)
skin/classic/aero/browser/appmenu-dropmarker.png
skin/classic/aero/browser/appmenu-icons.png
* skin/classic/aero/browser/browser.css (browser-aero.css)
* skin/classic/aero/browser/engineManager.css (engineManager.css)
skin/classic/aero/browser/fullscreen-video.css

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

@ -51,6 +51,7 @@ import sys
import threading
import tempfile
import zipfile
import sqlite3
SCRIPT_DIR = os.path.abspath(os.path.realpath(os.path.dirname(sys.argv[0])))
sys.path.insert(0, SCRIPT_DIR)
@ -289,6 +290,30 @@ class Automation(object):
return locations
def setupPermissionsDatabase(self, profileDir, permissions):
# Open database and create table
permDB = sqlite3.connect(os.path.join(profileDir, "permissions.sqlite"))
cursor = permDB.cursor();
cursor.execute("""CREATE TABLE moz_hosts (
id INTEGER PRIMARY KEY,
host TEXT,
type TEXT,
permission INTEGER,
expireType INTEGER,
expireTime INTEGER)""")
# Insert desired permissions
c = 0
for perm in permissions.keys():
for host in permissions[perm]:
c += 1
cursor.execute("INSERT INTO moz_hosts values(?, ?, ?, 1, 0, 0)",
(c, host, perm))
# Commit and close
permDB.commit()
cursor.close()
def initializeProfile(self, profileDir, extraPrefs = [], useServerLocations = False):
" Sets up the standard testing profile."
@ -297,6 +322,11 @@ class Automation(object):
shutil.rmtree(profileDir, True)
os.mkdir(profileDir)
# Set up permissions database
locations = self.readLocations()
self.setupPermissionsDatabase(profileDir,
{'allowXULXBL':map(lambda l: l.host, locations)});
part = """\
user_pref("browser.dom.window.dump.enabled", true);
user_pref("dom.allow_scripts_to_close_windows", true);
@ -354,8 +384,6 @@ user_pref("capability.principal.codebase.p1.subjectName", "");
""" % { "origin": "http://" + self.webServer + ":" + str(self.httpPort) }
prefs.append(part)
else:
locations = self.readLocations()
# Grant God-power to all the privileged servers on which tests run.
privileged = filter(lambda loc: "privileged" in loc.options, locations)
for (i, l) in itertools.izip(itertools.count(1), privileged):

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

@ -118,7 +118,7 @@ dnl ========================================================
GLIB_VERSION=1.2.0
LIBIDL_VERSION=0.6.3
PERL_VERSION=5.006
PYTHON_VERSION=2.4
PYTHON_VERSION=2.5
CAIRO_VERSION=1.8.8
PANGO_VERSION=1.14.0
GTK2_VERSION=2.10.0
@ -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

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

@ -385,6 +385,7 @@ public:
static const nsDependentSubstring TrimCharsInSet(const char* aSet,
const nsAString& aValue);
template<PRBool IsWhitespace(PRUnichar)>
static const nsDependentSubstring TrimWhitespace(const nsAString& aStr,
PRBool aTrimTrailing = PR_TRUE);

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

@ -134,9 +134,9 @@ interface nsIDOMParserJS : nsISupports
/**
* Just like nsIDOMParser.init, but callable from JS.
*/
void init(in nsIPrincipal principal,
in nsIURI documentURI,
in nsIURI baseURI);
void init([optional] in nsIPrincipal principal,
[optional] in nsIURI documentURI,
[optional] in nsIURI baseURI);
};
%{ C++

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

@ -1812,7 +1812,6 @@ nsIAtom** const kDefaultAllowedAttributes [] = {
&nsGkAtoms::alt,
&nsGkAtoms::autocomplete,
#ifdef MOZ_MEDIA
&nsGkAtoms::autobuffer,
&nsGkAtoms::autoplay,
#endif
&nsGkAtoms::axis,
@ -1872,6 +1871,7 @@ nsIAtom** const kDefaultAllowedAttributes [] = {
&nsGkAtoms::pointSize,
#ifdef MOZ_MEDIA
&nsGkAtoms::poster,
&nsGkAtoms::preload,
#endif
&nsGkAtoms::prompt,
&nsGkAtoms::readonly,

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

@ -561,6 +561,7 @@ nsContentUtils::InitializeEventTable() {
{ nsGkAtoms::onreset, NS_FORM_RESET, EventNameType_HTMLXUL, NS_EVENT },
{ nsGkAtoms::onchange, NS_FORM_CHANGE, EventNameType_HTMLXUL, NS_EVENT },
{ nsGkAtoms::onselect, NS_FORM_SELECTED, EventNameType_HTMLXUL, NS_EVENT },
{ nsGkAtoms::oninvalid, NS_FORM_INVALID, EventNameType_HTMLXUL, NS_EVENT },
{ nsGkAtoms::onload, NS_LOAD, EventNameType_All, NS_EVENT },
{ nsGkAtoms::onpopstate, NS_POPSTATE, EventNameType_HTMLXUL, NS_EVENT_NULL },
{ nsGkAtoms::onunload, NS_PAGE_UNLOAD,
@ -1912,6 +1913,7 @@ nsContentUtils::TrimCharsInSet(const char* aSet,
*/
// static
template<PRBool IsWhitespace(PRUnichar)>
const nsDependentSubstring
nsContentUtils::TrimWhitespace(const nsAString& aStr, PRBool aTrimTrailing)
{
@ -1921,7 +1923,7 @@ nsContentUtils::TrimWhitespace(const nsAString& aStr, PRBool aTrimTrailing)
aStr.EndReading(end);
// Skip whitespace characters in the beginning
while (start != end && nsCRT::IsAsciiSpace(*start)) {
while (start != end && IsWhitespace(*start)) {
++start;
}
@ -1930,7 +1932,7 @@ nsContentUtils::TrimWhitespace(const nsAString& aStr, PRBool aTrimTrailing)
while (end != start) {
--end;
if (!nsCRT::IsAsciiSpace(*end)) {
if (!IsWhitespace(*end)) {
// Step back to the last non-whitespace character.
++end;
@ -1945,6 +1947,16 @@ nsContentUtils::TrimWhitespace(const nsAString& aStr, PRBool aTrimTrailing)
return Substring(start, end);
}
// Declaring the templates we are going to use avoid linking issues without
// inlining the method. Considering there is not so much spaces checking
// methods we can consider this to be better than inlining.
template
const nsDependentSubstring
nsContentUtils::TrimWhitespace<nsCRT::IsAsciiSpace>(const nsAString&, PRBool);
template
const nsDependentSubstring
nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(const nsAString&, PRBool);
static inline void KeyAppendSep(nsACString& aKey)
{
if (!aKey.IsEmpty()) {
@ -5393,7 +5405,7 @@ nsContentUtils::CanAccessNativeAnon()
// Some code is running, we can't make the assumption, as above, but we
// can't use a native frame, so clear fp.
fp = nsnull;
} else if (!fp->script) {
} else if (!fp->hasScript()) {
fp = nsnull;
}
@ -5408,8 +5420,8 @@ nsContentUtils::CanAccessNativeAnon()
// if they've been cloned into less privileged contexts.
static const char prefix[] = "chrome://global/";
const char *filename;
if (fp && fp->script &&
(filename = fp->script->filename) &&
if (fp && fp->hasScript() &&
(filename = fp->getScript()->filename) &&
!strncmp(filename, prefix, NS_ARRAY_LENGTH(prefix) - 1)) {
return PR_TRUE;
}

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

@ -335,33 +335,40 @@ nsDOMParser::Init(nsIPrincipal* principal, nsIURI* documentURI,
NS_ENSURE_ARG(principal || documentURI);
mDocumentURI = documentURI;
if (!mDocumentURI) {
principal->GetURI(getter_AddRefs(mDocumentURI));
if (!mDocumentURI) {
// If we have the system principal, then we'll just use the null principals
// uri.
if (!mDocumentURI && !nsContentUtils::IsSystemPrincipal(principal)) {
return NS_ERROR_INVALID_ARG;
}
}
mScriptHandlingObject = do_GetWeakReference(aScriptObject);
mPrincipal = principal;
nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
NS_ENSURE_TRUE(secMan, NS_ERROR_NOT_AVAILABLE);
nsresult rv;
if (!mPrincipal) {
nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
NS_ENSURE_TRUE(secMan, NS_ERROR_NOT_AVAILABLE);
rv =
secMan->GetCodebasePrincipal(mDocumentURI, getter_AddRefs(mPrincipal));
NS_ENSURE_SUCCESS(rv, rv);
mOriginalPrincipal = mPrincipal;
} else {
mOriginalPrincipal = principal;
PRBool isSystem;
rv = secMan->IsSystemPrincipal(mPrincipal, &isSystem);
if (NS_FAILED(rv) || isSystem) {
mOriginalPrincipal = mPrincipal;
if (nsContentUtils::IsSystemPrincipal(mPrincipal)) {
// Don't give DOMParsers the system principal. Use a null
// principal instead.
mPrincipal = do_CreateInstance("@mozilla.org/nullprincipal;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
if (!mDocumentURI) {
rv = mPrincipal->GetURI(getter_AddRefs(mDocumentURI));
NS_ENSURE_SUCCESS(rv, rv);
}
}
}
NS_ENSURE_SUCCESS(rv, rv);
mBaseURI = baseURI;
// Note: if mBaseURI is null, fine. Leave it like that; that will use the
@ -507,7 +514,8 @@ nsDOMParser::Initialize(nsISupports* aOwner, JSContext* cx, JSObject* obj,
}
NS_IMETHODIMP
nsDOMParser::Init(nsIPrincipal *principal, nsIURI *documentURI, nsIURI *baseURI)
nsDOMParser::Init(nsIPrincipal *aPrincipal, nsIURI *aDocumentURI,
nsIURI *aBaseURI)
{
AttemptedInitMarker marker(&mAttemptedInit);
@ -515,6 +523,19 @@ nsDOMParser::Init(nsIPrincipal *principal, nsIURI *documentURI, nsIURI *baseURI)
NS_ENSURE_TRUE(cx, NS_ERROR_UNEXPECTED);
nsIScriptContext* scriptContext = GetScriptContextFromJSContext(cx);
return Init(principal, documentURI, baseURI,
nsCOMPtr<nsIPrincipal> principal = aPrincipal;
if (!principal && !aDocumentURI) {
nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
NS_ENSURE_TRUE(secMan, NS_ERROR_UNEXPECTED);
secMan->GetSubjectPrincipal(getter_AddRefs(principal));
// We're called from JS; there better be a subject principal, really.
NS_ENSURE_TRUE(principal, NS_ERROR_UNEXPECTED);
}
return Init(principal, aDocumentURI, aBaseURI,
scriptContext ? scriptContext->GetGlobalObject() : nsnull);
}

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

@ -42,7 +42,7 @@
#include "nsContentUtils.h"
nsFormData::nsFormData()
: nsFormSubmission(NS_LITERAL_CSTRING("UTF-8"))
: nsFormSubmission(NS_LITERAL_CSTRING("UTF-8"), nsnull)
{
}
@ -141,7 +141,7 @@ NS_IMETHODIMP
nsFormData::GetSendInfo(nsIInputStream** aBody, nsACString& aContentType,
nsACString& aCharset)
{
nsFSMultipartFormData fs(NS_LITERAL_CSTRING("UTF-8"));
nsFSMultipartFormData fs(NS_LITERAL_CSTRING("UTF-8"), nsnull);
for (PRUint32 i = 0; i < mFormData.Length(); ++i) {
if (mFormData[i].valueIsFile) {

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

@ -120,9 +120,6 @@ GK_ATOM(attribute, "attribute")
GK_ATOM(attributeSet, "attribute-set")
GK_ATOM(aural, "aural")
GK_ATOM(_auto, "auto")
#ifdef MOZ_MEDIA
GK_ATOM(autobuffer, "autobuffer")
#endif
GK_ATOM(autocheck, "autocheck")
GK_ATOM(autocomplete, "autocomplete")
GK_ATOM(autofocus, "autofocus")
@ -390,8 +387,12 @@ GK_ATOM(footer, "footer")
GK_ATOM(_for, "for")
GK_ATOM(forEach, "for-each")
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")
GK_ATOM(frameset, "frameset")
@ -654,6 +655,7 @@ GK_ATOM(onfocus, "onfocus")
GK_ATOM(onget, "onget")
GK_ATOM(onhashchange, "onhashchange")
GK_ATOM(oninput, "oninput")
GK_ATOM(oninvalid, "oninvalid")
GK_ATOM(onkeydown, "onkeydown")
GK_ATOM(onkeypress, "onkeypress")
GK_ATOM(onkeyup, "onkeyup")
@ -724,6 +726,7 @@ GK_ATOM(param, "param")
GK_ATOM(parameter, "parameter")
GK_ATOM(parent, "parent")
GK_ATOM(parsetype, "parsetype")
GK_ATOM(pattern, "pattern")
GK_ATOM(patternSeparator, "pattern-separator")
GK_ATOM(perMille, "per-mille")
GK_ATOM(percent, "percent")
@ -763,6 +766,9 @@ GK_ATOM(preceding, "preceding")
GK_ATOM(precedingSibling, "preceding-sibling")
GK_ATOM(predicate, "predicate")
GK_ATOM(prefix, "prefix")
#ifdef MOZ_MEDIA
GK_ATOM(preload, "preload")
#endif
GK_ATOM(preserve, "preserve")
GK_ATOM(preserveSpace, "preserve-space")
GK_ATOM(preventdefault, "preventdefault")
@ -797,6 +803,7 @@ GK_ATOM(removeelement, "removeelement")
GK_ATOM(renderingobserverlist, "renderingobserverlist")
GK_ATOM(repeat, "repeat")
GK_ATOM(replace, "replace")
GK_ATOM(required, "required")
GK_ATOM(reset, "reset")
GK_ATOM(resizeafter, "resizeafter")
GK_ATOM(resizebefore, "resizebefore")
@ -1209,7 +1216,6 @@ GK_ATOM(over, "over")
GK_ATOM(pad, "pad")
GK_ATOM(path, "path")
GK_ATOM(pathLength, "pathLength")
GK_ATOM(pattern, "pattern")
GK_ATOM(patternContentUnits, "patternContentUnits")
GK_ATOM(patternTransform, "patternTransform")
GK_ATOM(patternUnits, "patternUnits")

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

@ -74,6 +74,7 @@
#include "prlog.h"
#include "nsIChannelPolicy.h"
#include "nsChannelPolicy.h"
#include "nsCRT.h"
#include "mozilla/FunctionTimer.h"
@ -189,13 +190,15 @@ IsScriptEventHandler(nsIScriptElement *aScriptElement)
return PR_FALSE;
}
const nsAString& for_str = nsContentUtils::TrimWhitespace(forAttr);
const nsAString& for_str =
nsContentUtils::TrimWhitespace<nsCRT::IsAsciiSpace>(forAttr);
if (!for_str.LowerCaseEqualsLiteral("window")) {
return PR_TRUE;
}
// We found for="window", now check for event="onload".
const nsAString& event_str = nsContentUtils::TrimWhitespace(eventAttr, PR_FALSE);
const nsAString& event_str =
nsContentUtils::TrimWhitespace<nsCRT::IsAsciiSpace>(eventAttr, PR_FALSE);
if (!StringBeginsWith(event_str, NS_LITERAL_STRING("onload"),
nsCaseInsensitiveStringComparator())) {
// It ain't "onload.*".

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

@ -16,6 +16,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=564863
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<style>
* {
color: rgb(0, 0, 0);
}
#div_id {
color: rgb(10, 10, 10);
}

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

@ -92,8 +92,7 @@ WebGLContext::WebGLContext()
mPixelStoreFlipY = PR_FALSE;
mPixelStorePremultiplyAlpha = PR_FALSE;
// eventually true
mShaderValidation = PR_FALSE;
mShaderValidation = PR_TRUE;
mMapBuffers.Init();
mMapTextures.Init();

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

@ -447,26 +447,21 @@ WebGLContext::InitAndValidateGL()
gl->fEnable(LOCAL_GL_VERTEX_PROGRAM_POINT_SIZE);
}
static bool didTranslatorCheck = false;
if (!didTranslatorCheck) {
// Check the shader validator pref
nsCOMPtr<nsIPrefBranch> prefService = do_GetService(NS_PREFSERVICE_CONTRACTID);
NS_ENSURE_TRUE(prefService != nsnull, NS_ERROR_FAILURE);
// Check the shader validator pref
nsCOMPtr<nsIPrefBranch> prefService = do_GetService(NS_PREFSERVICE_CONTRACTID);
NS_ENSURE_TRUE(prefService != nsnull, NS_ERROR_FAILURE);
prefService->GetBoolPref("webgl.shader_validator", &mShaderValidation);
prefService->GetBoolPref("webgl.shader_validator", &mShaderValidation);
#if defined(USE_ANGLE)
// initialize shader translator
if (mShaderValidation) {
if (!ShInitialize()) {
LogMessage("GLSL translator initialization failed!");
return PR_FALSE;
}
// initialize shader translator
if (mShaderValidation) {
if (!ShInitialize()) {
LogMessage("GLSL translator initialization failed!");
return PR_FALSE;
}
#endif
didTranslatorCheck = true;
}
#endif
return PR_TRUE;
}

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

@ -2327,8 +2327,7 @@ nsCanvasRenderingContext2D::SetFont(const nsAString& font)
// We know the declaration is not !important, so we can use
// GetNormalBlock().
const nsCSSValue *fsaVal =
declaration->GetNormalBlock()->
ValueStorageFor(eCSSProperty_font_size_adjust);
declaration->GetNormalBlock()->ValueFor(eCSSProperty_font_size_adjust);
if (!fsaVal || (fsaVal->GetUnit() != eCSSUnit_None &&
fsaVal->GetUnit() != eCSSUnit_System_Font)) {
// We got an all-property value or a syntax error. The spec says

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

@ -50,6 +50,7 @@
#include "nsIScriptableRegion.h"
#include "nsContentUtils.h"
#include "nsIContent.h"
#include "nsCRT.h"
NS_IMPL_CYCLE_COLLECTION_2(nsDOMDataTransfer, mDragTarget, mDragImage)
@ -336,7 +337,7 @@ nsDOMDataTransfer::GetData(const nsAString& aFormat, nsAString& aData)
aData.Assign(Substring(stringdata, lastidx));
else
aData.Assign(Substring(stringdata, lastidx, idx - lastidx));
aData = nsContentUtils::TrimWhitespace(aData, PR_TRUE);
aData = nsContentUtils::TrimWhitespace<nsCRT::IsAsciiSpace>(aData, PR_TRUE);
return NS_OK;
}
lastidx = idx + 1;

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

@ -65,7 +65,7 @@ static const char* const sEventNames[] = {
"mouseout", "MozMouseHittest", "mousemove", "contextmenu", "keydown", "keyup", "keypress",
"focus", "blur", "load", "popstate", "beforeunload", "unload",
"hashchange", "readystatechange", "abort", "error",
"submit", "reset", "change", "select", "input", "text",
"submit", "reset", "change", "select", "input", "invalid", "text",
"compositionstart", "compositionend", "popupshowing", "popupshown",
"popuphiding", "popuphidden", "close", "command", "broadcast", "commandupdate",
"dragenter", "dragover", "dragexit", "dragdrop", "draggesture",
@ -1149,6 +1149,8 @@ const char* nsDOMEvent::GetEventName(PRUint32 aEventType)
return sEventNames[eDOMEvents_select];
case NS_FORM_INPUT:
return sEventNames[eDOMEvents_input];
case NS_FORM_INVALID:
return sEventNames[eDOMEvents_invalid];
case NS_RESIZE_EVENT:
return sEventNames[eDOMEvents_resize];
case NS_SCROLL_EVENT:

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

@ -88,6 +88,7 @@ public:
eDOMEvents_change,
eDOMEvents_select,
eDOMEvents_input,
eDOMEvents_invalid,
eDOMEvents_text,
eDOMEvents_compositionstart,
eDOMEvents_compositionend,

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

@ -1790,8 +1790,10 @@ nsEventStateManager::FireContextClick()
PRInt32 type = formCtrl->GetType();
allowedToDispatch = (type == NS_FORM_INPUT_TEXT ||
type == NS_FORM_INPUT_EMAIL ||
type == NS_FORM_INPUT_SEARCH ||
type == NS_FORM_INPUT_TEL ||
type == NS_FORM_INPUT_URL ||
type == NS_FORM_INPUT_PASSWORD ||
type == NS_FORM_INPUT_FILE ||
type == NS_FORM_TEXTAREA);
@ -3292,7 +3294,6 @@ nsEventStateManager::PostHandleEvent(nsPresContext* aPresContext,
//Reset target frame to null to avoid mistargeting after reentrant event
mCurrentTarget = nsnull;
mCurrentTargetContent = nsnull;
return ret;
}
@ -3612,7 +3613,6 @@ nsEventStateManager::DispatchMouseEvent(nsGUIEvent* aEvent, PRUint32 aMessage,
event.inputSource = static_cast<nsMouseEvent*>(aEvent)->inputSource;
mCurrentTargetContent = aTargetContent;
mCurrentTarget = nsnull;
nsIFrame* targetFrame = nsnull;
if (aTargetContent) {
@ -3629,7 +3629,6 @@ nsEventStateManager::DispatchMouseEvent(nsGUIEvent* aEvent, PRUint32 aMessage,
}
mCurrentTargetContent = nsnull;
mCurrentTarget = nsnull;
return targetFrame;
}
@ -3794,7 +3793,6 @@ nsEventStateManager::GenerateMouseEnterExit(nsGUIEvent* aEvent)
// reset mCurretTargetContent to what it was
mCurrentTargetContent = targetBeforeEvent;
mCurrentTarget = nsnull;
}
void

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

@ -122,26 +122,37 @@ public:
aCharset = mCharset;
}
nsIContent* GetOriginatingElement() const
{
return mOriginatingElement.get();
}
protected:
/**
* Can only be constructed by subclasses.
*
* @param aCharset the charset of the form as a string
* @param aOriginatingElement the originating element (can be null)
*/
nsFormSubmission(const nsACString& aCharset)
nsFormSubmission(const nsACString& aCharset, nsIContent* aOriginatingElement)
: mCharset(aCharset)
, mOriginatingElement(aOriginatingElement)
{
MOZ_COUNT_CTOR(nsFormSubmission);
}
// The name of the encoder charset
nsCString mCharset;
// Originating element.
nsCOMPtr<nsIContent> mOriginatingElement;
};
class nsEncodingFormSubmission : public nsFormSubmission
{
public:
nsEncodingFormSubmission(const nsACString& aCharset);
nsEncodingFormSubmission(const nsACString& aCharset,
nsIContent* aOriginatingElement);
virtual ~nsEncodingFormSubmission();
@ -169,7 +180,8 @@ public:
/**
* @param aCharset the charset of the form as a string
*/
nsFSMultipartFormData(const nsACString& aCharset);
nsFSMultipartFormData(const nsACString& aCharset,
nsIContent* aOriginatingElement);
~nsFSMultipartFormData();
virtual nsresult AddNameValuePair(const nsAString& aName,
@ -223,9 +235,11 @@ private:
* Get a submission object based on attributes in the form (ENCTYPE and METHOD)
*
* @param aForm the form to get a submission object based on
* @param aOriginatingElement the originating element (can be null)
* @param aFormSubmission the form submission object (out param)
*/
nsresult GetSubmissionFromForm(nsGenericHTMLElement* aForm,
nsGenericHTMLElement* aOriginatingElement,
nsFormSubmission** aFormSubmission);
#endif /* nsIFormSubmission_h___ */

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

@ -430,6 +430,51 @@ protected:
* Called asynchronously to release a self-reference to this element.
*/
void DoRemoveSelfReference();
/**
* Possible values of the 'preload' attribute.
*/
enum PreloadAttrValue {
PRELOAD_ATTR_EMPTY, // set to ""
PRELOAD_ATTR_NONE, // set to "none"
PRELOAD_ATTR_METADATA, // set to "metadata"
PRELOAD_ATTR_AUTO // set to "auto"
};
/**
* The preloading action to perform. These dictate how we react to the
* preload attribute. See mPreloadAction.
*/
enum PreloadAction {
PRELOAD_UNDEFINED = 0, // not determined - used only for initialization
PRELOAD_NONE = 1, // do not preload
PRELOAD_METADATA = 2, // preload only the metadata (and first frame)
PRELOAD_ENOUGH = 3 // preload enough data to allow uninterrupted
// playback
};
/**
* Suspends the load of resource at aURI, so that it can be resumed later
* by ResumeLoad(). This is called when we have a media with a 'preload'
* attribute value of 'none', during the resource selection algorithm.
*/
void SuspendLoad(nsIURI* aURI);
/**
* Resumes a previously suspended load (suspended by SuspendLoad(uri)).
* Will continue running the resource selection algorithm.
* Sets mPreloadAction to aAction.
*/
void ResumeLoad(PreloadAction aAction);
/**
* Handle a change to the preload attribute. Should be called whenever the
* value (or presence) of the preload attribute changes. The change in
* attribute value may cause a change in the mPreloadAction of this
* element. If there is a change then this method will initiate any
* behaviour that is necessary to implement the action.
*/
void UpdatePreloadAction();
nsRefPtr<nsMediaDecoder> mDecoder;
@ -482,10 +527,23 @@ protected:
// Current audio volume
float mVolume;
// If we're loading a preload:none media, we'll record the URI we're
// attempting to load in mPreloadURI, and delay loading the resource until
// the user initiates a load by either playing the resource, or explicitly
// loading it.
nsCOMPtr<nsIURI> mPreloadURI;
// Stores the current preload action for this element. Initially set to
// PRELOAD_UNDEFINED, its value is changed by calling
// UpdatePreloadAction().
PreloadAction mPreloadAction;
// Size of the media. Updated by the decoder on the main thread if
// it changes. Defaults to a width and height of -1 if not set.
nsIntSize mMediaSize;
nsRefPtr<gfxASurface> mPrintSurface;
// If true then we have begun downloading the media content.
// Set to false when completed, or not yet started.
PRPackedBool mBegun;
@ -551,11 +609,13 @@ protected:
PRPackedBool mIsRunningSelectResource;
// PR_TRUE if we suspended the decoder because we were paused,
// autobuffer and autoplay were not set, and we loaded the first frame.
// preloading metadata is enabled, autoplay was not enabled, and we loaded
// the first frame.
PRPackedBool mSuspendedAfterFirstFrame;
// PR_TRUE if we are allowed to suspend the decoder because we were paused,
// autobuffer and autoplay were not set, and we loaded the first frame.
// preloading metdata was enabled, autoplay was not enabled, and we loaded
// the first frame.
PRPackedBool mAllowSuspendAfterFirstFrame;
// PR_TRUE if we've played or completed a seek. We use this to determine
@ -571,7 +631,11 @@ protected:
// down.
PRPackedBool mShuttingDown;
nsRefPtr<gfxASurface> mPrintSurface;
// PR_TRUE if we've suspended a load in the resource selection algorithm
// due to loading a preload:none media. When PR_TRUE, the resource we'll
// load when the user initiates either playback or an explicit load is
// stored in mPreloadURI.
PRPackedBool mLoadIsSuspended;
};
#endif

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

@ -81,6 +81,7 @@ enum ButtonElementTypes {
enum InputElementTypes {
NS_FORM_INPUT_BUTTON = NS_FORM_INPUT_ELEMENT + 1,
NS_FORM_INPUT_CHECKBOX,
NS_FORM_INPUT_EMAIL,
NS_FORM_INPUT_FILE,
NS_FORM_INPUT_HIDDEN,
NS_FORM_INPUT_RESET,
@ -91,6 +92,7 @@ enum InputElementTypes {
NS_FORM_INPUT_SUBMIT,
NS_FORM_INPUT_TEL,
NS_FORM_INPUT_TEXT,
NS_FORM_INPUT_URL,
eInputElementTypesMax
};
@ -99,8 +101,8 @@ PR_STATIC_ASSERT((PRUint32)eButtonElementTypesMax < (PRUint32)NS_FORM_INPUT_ELEM
PR_STATIC_ASSERT((PRUint32)eInputElementTypesMax < 1<<8);
#define NS_IFORMCONTROL_IID \
{ 0x0dc5083b, 0xb0a8, 0x48c4, \
{ 0xb2, 0xeb, 0xc2, 0x4f, 0xfb, 0x7e, 0xc2, 0x8e } }
{ 0xc2f7723a, 0x106a, 0x47ef, \
{ 0xa9, 0xff, 0x4b, 0x4f, 0x73, 0x47, 0xe7, 0xa6 } }
/**
* Interface which all form controls (e.g. buttons, checkboxes, text,
@ -156,11 +158,8 @@ public:
* submission object
* @param aFormSubmission the form submission to notify of names/values/files
* to submit
* @param aSubmitElement the element that was pressed to submit (possibly
* null)
*/
NS_IMETHOD SubmitNamesValues(nsFormSubmission* aFormSubmission,
nsIContent* aSubmitElement) = 0;
NS_IMETHOD SubmitNamesValues(nsFormSubmission* aFormSubmission) = 0;
/**
* Save to presentation state. The form control will determine whether it

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

@ -112,6 +112,8 @@ CPPSRCS = \
nsHTMLTextAreaElement.cpp \
nsHTMLTimeRanges.cpp \
nsHTMLTitleElement.cpp \
nsDOMValidityState.cpp \
nsConstraintValidation.cpp \
$(NULL)
ifdef MOZ_MEDIA

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

@ -0,0 +1,159 @@
/* -*- 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 ***** */
#include "nsConstraintValidation.h"
#include "nsAString.h"
#include "nsGenericHTMLElement.h"
#include "nsHTMLFormElement.h"
nsConstraintValidation::~nsConstraintValidation()
{
if (mValidity) {
mValidity->Disconnect();
}
}
nsresult
nsConstraintValidation::GetValidity(nsIDOMValidityState** aValidity)
{
if (!mValidity) {
mValidity = new nsDOMValidityState(this);
}
NS_ADDREF(*aValidity = mValidity);
return NS_OK;
}
nsresult
nsConstraintValidation::GetWillValidate(PRBool* aWillValidate,
nsGenericHTMLFormElement* aElement)
{
*aWillValidate = IsCandidateForConstraintValidation(aElement);
return NS_OK;
}
nsresult
nsConstraintValidation::GetValidationMessage(nsAString & aValidationMessage,
nsGenericHTMLFormElement* aElement)
{
aValidationMessage.Truncate();
if (IsCandidateForConstraintValidation(aElement) && !IsValid()) {
if (!mCustomValidity.IsEmpty()) {
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 {
// TODO: The other messages have not been written
// because related constraint validation are not implemented yet.
// We should not be here.
return NS_ERROR_UNEXPECTED;
}
} else {
aValidationMessage.Truncate();
}
return NS_OK;
}
nsresult
nsConstraintValidation::CheckValidity(PRBool* aValidity,
nsGenericHTMLFormElement* aElement)
{
if (!IsCandidateForConstraintValidation(aElement) || IsValid()) {
*aValidity = PR_TRUE;
return NS_OK;
}
*aValidity = PR_FALSE;
return nsContentUtils::DispatchTrustedEvent(aElement->GetOwnerDoc(),
static_cast<nsIContent*>(aElement),
NS_LITERAL_STRING("invalid"),
PR_FALSE, PR_TRUE);
}
nsresult
nsConstraintValidation::SetCustomValidity(const nsAString & aError)
{
mCustomValidity.Assign(aError);
return NS_OK;
}
PRBool
nsConstraintValidation::HasCustomError() const
{
return !mCustomValidity.IsEmpty();
}
PRBool
nsConstraintValidation::IsValid()
{
return !(IsValueMissing() || HasTypeMismatch() || HasPatternMismatch() ||
IsTooLong() || HasRangeUnderflow() || HasRangeOverflow() ||
HasStepMismatch() || HasCustomError());
}
PRBool
nsConstraintValidation::IsCandidateForConstraintValidation(nsGenericHTMLFormElement* aElement)
{
/**
* An element is never candidate for constraint validation if:
* - it is disabled ;
* - TODO: or it's ancestor is a datalist element (bug 555840).
* We are doing these checks here to prevent writing them in every
* |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;
}
return !IsBarredFromConstraintValidation();
}

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

@ -0,0 +1,143 @@
/* -*- 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___

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

@ -0,0 +1,122 @@
/* -*- 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 ***** */
#include "nsDOMValidityState.h"
#include "nsDOMClassInfo.h"
#include "nsConstraintValidation.h"
DOMCI_DATA(ValidityState, nsDOMValidityState)
NS_IMPL_ADDREF(nsDOMValidityState)
NS_IMPL_RELEASE(nsDOMValidityState)
NS_INTERFACE_MAP_BEGIN(nsDOMValidityState)
NS_INTERFACE_MAP_ENTRY(nsIDOMValidityState)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMValidityState)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(ValidityState)
NS_INTERFACE_MAP_END
nsDOMValidityState::nsDOMValidityState(nsConstraintValidation* aConstraintValidation)
: mConstraintValidation(aConstraintValidation)
{
}
NS_IMETHODIMP
nsDOMValidityState::GetValueMissing(PRBool* aValueMissing)
{
*aValueMissing = mConstraintValidation && mConstraintValidation->IsValueMissing();
return NS_OK;
}
NS_IMETHODIMP
nsDOMValidityState::GetTypeMismatch(PRBool* aTypeMismatch)
{
*aTypeMismatch = mConstraintValidation && mConstraintValidation->HasTypeMismatch();
return NS_OK;
}
NS_IMETHODIMP
nsDOMValidityState::GetPatternMismatch(PRBool* aPatternMismatch)
{
*aPatternMismatch = mConstraintValidation && mConstraintValidation->HasPatternMismatch();
return NS_OK;
}
NS_IMETHODIMP
nsDOMValidityState::GetTooLong(PRBool* aTooLong)
{
*aTooLong = mConstraintValidation && mConstraintValidation->IsTooLong();
return NS_OK;
}
NS_IMETHODIMP
nsDOMValidityState::GetRangeUnderflow(PRBool* aRangeUnderflow)
{
*aRangeUnderflow = mConstraintValidation && mConstraintValidation->HasRangeUnderflow();
return NS_OK;
}
NS_IMETHODIMP
nsDOMValidityState::GetRangeOverflow(PRBool* aRangeOverflow)
{
*aRangeOverflow = mConstraintValidation && mConstraintValidation->HasRangeOverflow();
return NS_OK;
}
NS_IMETHODIMP
nsDOMValidityState::GetStepMismatch(PRBool* aStepMismatch)
{
*aStepMismatch = mConstraintValidation && mConstraintValidation->HasStepMismatch();
return NS_OK;
}
NS_IMETHODIMP
nsDOMValidityState::GetCustomError(PRBool* aCustomError)
{
*aCustomError = mConstraintValidation && mConstraintValidation->HasCustomError();
return NS_OK;
}
NS_IMETHODIMP
nsDOMValidityState::GetValid(PRBool* aValid)
{
*aValid = !mConstraintValidation || mConstraintValidation->IsValid();
return NS_OK;
}

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

@ -0,0 +1,67 @@
/* -*- 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 nsDOMValidityState_h__
#define nsDOMValidityState_h__
#include "nsIDOMValidityState.h"
class nsConstraintValidation;
class nsDOMValidityState : public nsIDOMValidityState
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIDOMVALIDITYSTATE
friend class nsConstraintValidation;
protected:
// This function should be called by nsConstraintValidation
// to set mConstraintValidation to null to be sure it will not be called.
void Disconnect()
{
mConstraintValidation = nsnull;
}
nsDOMValidityState(nsConstraintValidation* aConstraintValidation);
nsConstraintValidation* mConstraintValidation;
};
#endif // nsDOMValidityState_h__

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

@ -98,8 +98,9 @@ public:
*/
nsFSURLEncoded(const nsACString& aCharset,
PRInt32 aMethod,
nsIDocument* aDocument)
: nsEncodingFormSubmission(aCharset),
nsIDocument* aDocument,
nsIContent* aOriginatingElement)
: nsEncodingFormSubmission(aCharset, aOriginatingElement),
mMethod(aMethod),
mDocument(aDocument),
mWarnedFileControl(PR_FALSE)
@ -403,8 +404,9 @@ nsFSURLEncoded::URLEncode(const nsAString& aStr, nsCString& aEncoded)
// --------------------------------------------------------------------------
nsFSMultipartFormData::nsFSMultipartFormData(const nsACString& aCharset)
: nsEncodingFormSubmission(aCharset)
nsFSMultipartFormData::nsFSMultipartFormData(const nsACString& aCharset,
nsIContent* aOriginatingElement)
: nsEncodingFormSubmission(aCharset, aOriginatingElement)
{
mPostDataStream =
do_CreateInstance("@mozilla.org/io/multiplex-input-stream;1");
@ -595,8 +597,8 @@ nsFSMultipartFormData::AddPostDataStream()
class nsFSTextPlain : public nsEncodingFormSubmission
{
public:
nsFSTextPlain(const nsACString& aCharset)
: nsEncodingFormSubmission(aCharset)
nsFSTextPlain(const nsACString& aCharset, nsIContent* aOriginatingElement)
: nsEncodingFormSubmission(aCharset, aOriginatingElement)
{
}
@ -691,8 +693,9 @@ nsFSTextPlain::GetEncodedSubmission(nsIURI* aURI,
// --------------------------------------------------------------------------
nsEncodingFormSubmission::nsEncodingFormSubmission(const nsACString& aCharset)
: nsFormSubmission(aCharset)
nsEncodingFormSubmission::nsEncodingFormSubmission(const nsACString& aCharset,
nsIContent* aOriginatingElement)
: nsFormSubmission(aCharset, aOriginatingElement)
{
nsCAutoString charset(aCharset);
// canonical name is passed so that we just have to check against
@ -800,6 +803,7 @@ GetEnumAttr(nsGenericHTMLElement* aContent,
nsresult
GetSubmissionFromForm(nsGenericHTMLElement* aForm,
nsGenericHTMLElement* aOriginatingElement,
nsFormSubmission** aFormSubmission)
{
// Get all the information necessary to encode the form data
@ -808,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;
@ -821,21 +835,29 @@ GetSubmissionFromForm(nsGenericHTMLElement* aForm,
// Choose encoder
if (method == NS_FORM_METHOD_POST &&
enctype == NS_FORM_ENCTYPE_MULTIPART) {
*aFormSubmission = new nsFSMultipartFormData(charset);
*aFormSubmission = new nsFSMultipartFormData(charset, aOriginatingElement);
} else if (method == NS_FORM_METHOD_POST &&
enctype == NS_FORM_ENCTYPE_TEXTPLAIN) {
*aFormSubmission = new nsFSTextPlain(charset);
*aFormSubmission = new nsFSTextPlain(charset, aOriginatingElement);
} else {
nsIDocument* doc = aForm->GetOwnerDoc();
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);
}
*aFormSubmission = new nsFSURLEncoded(charset, method, doc);
*aFormSubmission = new nsFSURLEncoded(charset, method, doc,
aOriginatingElement);
}
NS_ENSURE_TRUE(*aFormSubmission, NS_ERROR_OUT_OF_MEMORY);

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

@ -0,0 +1,59 @@
/* -*- 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
*
* 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 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__

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

@ -1916,7 +1916,8 @@ nsGenericHTMLElement::MapBackgroundInto(const nsMappedAttributes* aAttributes,
return;
nsPresContext* presContext = aData->mPresContext;
if (!aData->mColorData->mBackImage && presContext->UseDocumentColors()) {
if (aData->mColorData->mBackImage.GetUnit() == eCSSUnit_Null &&
presContext->UseDocumentColors()) {
// background
const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::background);
if (value && value->Type() == nsAttrValue::eString) {
@ -1946,11 +1947,9 @@ nsGenericHTMLElement::MapBackgroundInto(const nsMappedAttributes* aAttributes,
doc->NodePrincipal(), doc);
buffer->Release();
if (NS_LIKELY(img != 0)) {
// Use nsRuleDataColor's temporary mTempBackImage to
// make a value list.
aData->mColorData->mTempBackImage.mValue.SetImageValue(img);
aData->mColorData->mBackImage =
&aData->mColorData->mTempBackImage;
nsCSSValueList* list =
aData->mColorData->mBackImage.SetListValue();
list->mValue.SetImageValue(img);
}
}
}
@ -1958,10 +1957,8 @@ nsGenericHTMLElement::MapBackgroundInto(const nsMappedAttributes* aAttributes,
else if (presContext->CompatibilityMode() == eCompatibility_NavQuirks) {
// in NavQuirks mode, allow the empty string to set the
// background to empty
// Use nsRuleDataColor's temporary mTempBackImage to make a value list.
aData->mColorData->mBackImage = nsnull;
aData->mColorData->mTempBackImage.mValue.SetNoneValue();
aData->mColorData->mBackImage = &aData->mColorData->mTempBackImage;
nsCSSValueList* list = aData->mColorData->mBackImage.SetListValue();
list->mValue.SetNoneValue();
}
}
}
@ -2706,8 +2703,10 @@ nsGenericHTMLFormElement::IsSingleLineTextControlInternal(PRBool aExcludePasswor
PRInt32 aType) const
{
return aType == NS_FORM_INPUT_TEXT ||
aType == NS_FORM_INPUT_EMAIL ||
aType == NS_FORM_INPUT_SEARCH ||
aType == NS_FORM_INPUT_TEL ||
aType == NS_FORM_INPUT_URL ||
(!aExcludePassword && aType == NS_FORM_INPUT_PASSWORD);
}

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

@ -494,6 +494,19 @@ public:
NS_HIDDEN_(nsresult) GetEditor(nsIEditor** aEditor);
NS_HIDDEN_(nsresult) GetEditorInternal(nsIEditor** aEditor);
/**
* Helper method for NS_IMPL_URI_ATTR macro.
* Gets the absolute URI value of an attribute, by resolving any relative
* URIs in the attribute against the baseuri of the element. If the attribute
* isn't a relative URI the value of the attribute is returned as is. Only
* works for attributes in null namespace.
*
* @param aAttr name of attribute.
* @param aBaseAttr name of base attribute.
* @param aResult result value [out]
*/
NS_HIDDEN_(nsresult) GetURIAttr(nsIAtom* aAttr, nsIAtom* aBaseAttr, nsAString& aResult);
protected:
/**
* Add/remove this element to the documents name cache
@ -654,19 +667,6 @@ protected:
*/
NS_HIDDEN_(nsresult) SetFloatAttr(nsIAtom* aAttr, float aValue);
/**
* Helper method for NS_IMPL_URI_ATTR macro.
* Gets the absolute URI value of an attribute, by resolving any relative
* URIs in the attribute against the baseuri of the element. If the attribute
* isn't a relative URI the value of the attribute is returned as is. Only
* works for attributes in null namespace.
*
* @param aAttr name of attribute.
* @param aBaseAttr name of base attribute.
* @param aResult result value [out]
*/
NS_HIDDEN_(nsresult) GetURIAttr(nsIAtom* aAttr, nsIAtom* aBaseAttr, nsAString& aResult);
/**
* Helper for GetURIAttr and GetHrefURIForAnchors which returns an
* nsIURI in the out param.
@ -840,6 +840,11 @@ public:
virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
/**
* Returns if the control can be disabled.
*/
PRBool CanBeDisabled() const;
protected:
virtual nsresult BeforeSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString* aValue, PRBool aNotify);
@ -855,11 +860,6 @@ protected:
return PR_FALSE;
}
/**
* Returns true if the control can be disabled
*/
PRBool CanBeDisabled() const;
void UpdateEditableFormControlState();
PRBool IsSingleLineTextControlInternal(PRBool aExcludePassword, PRInt32 mType) const;

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

@ -120,9 +120,10 @@ nsHTMLAudioElement::Initialize(nsISupports* aOwner, JSContext* aContext,
JSObject *aObj, PRUint32 argc, jsval *argv)
{
// Audio elements created using "new Audio(...)" should have
// 'autobuffer' set (since the script must intend to play the audio)
nsresult rv = SetAttr(kNameSpaceID_None, nsGkAtoms::autobuffer,
NS_LITERAL_STRING("autobuffer"), PR_TRUE);
// 'preload' set to 'auto' (since the script must intend to
// play the audio)
nsresult rv = SetAttr(kNameSpaceID_None, nsGkAtoms::preload,
NS_LITERAL_STRING("auto"), PR_TRUE);
if (NS_FAILED(rv))
return rv;

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

@ -45,6 +45,7 @@
#include "nsIFormControl.h"
#include "nsIForm.h"
#include "nsFormSubmission.h"
#include "nsFormSubmissionConstants.h"
#include "nsIURL.h"
#include "nsIFrame.h"
@ -61,6 +62,7 @@
#include "nsLayoutErrors.h"
#include "nsFocusManager.h"
#include "nsHTMLFormElement.h"
#include "nsConstraintValidation.h"
#define NS_IN_SUBMIT_CLICK (1 << 0)
#define NS_OUTER_ACTIVATE_EVENT (1 << 1)
@ -76,7 +78,8 @@ static const nsAttrValue::EnumTable kButtonTypeTable[] = {
static const nsAttrValue::EnumTable* kButtonDefaultType = &kButtonTypeTable[2];
class nsHTMLButtonElement : public nsGenericHTMLFormElement,
public nsIDOMHTMLButtonElement
public nsIDOMHTMLButtonElement,
public nsConstraintValidation
{
public:
nsHTMLButtonElement(already_AddRefed<nsINodeInfo> aNodeInfo);
@ -100,11 +103,12 @@ public:
// overriden nsIFormControl methods
NS_IMETHOD_(PRUint32) GetType() const { return mType; }
NS_IMETHOD Reset();
NS_IMETHOD SubmitNamesValues(nsFormSubmission* aFormSubmission,
nsIContent* aSubmitElement);
NS_IMETHOD SubmitNamesValues(nsFormSubmission* aFormSubmission);
NS_IMETHOD SaveState();
PRBool RestoreState(nsPresState* aState);
PRInt32 IntrinsicState() const;
/**
* Called when an attribute is about to be changed
*/
@ -128,6 +132,10 @@ public:
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
virtual void DoneCreatingElement();
virtual nsXPCClassInfo* GetClassInfo();
// nsConstraintValidation
PRBool IsBarredFromConstraintValidation();
protected:
virtual PRBool AcceptAutofocus() const
{
@ -181,6 +189,9 @@ NS_INTERFACE_TABLE_HEAD(nsHTMLButtonElement)
nsGenericHTMLFormElement)
NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLButtonElement)
// nsConstraintValidation
NS_IMPL_NSCONSTRAINTVALIDATION(nsHTMLButtonElement)
// nsIDOMHTMLButtonElement
@ -198,6 +209,12 @@ nsHTMLButtonElement::GetForm(nsIDOMHTMLFormElement** aForm)
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)
NS_IMPL_STRING_ATTR(nsHTMLButtonElement, Value, value)
@ -273,17 +290,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,
@ -330,7 +356,7 @@ nsHTMLButtonElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
// tell the form that we are about to enter a click handler.
// that means that if there are scripted submissions, the
// latest one will be deferred until after the exit point of the handler.
mForm->OnSubmitClickBegin();
mForm->OnSubmitClickBegin(this);
}
}
@ -515,15 +541,14 @@ nsHTMLButtonElement::Reset()
}
NS_IMETHODIMP
nsHTMLButtonElement::SubmitNamesValues(nsFormSubmission* aFormSubmission,
nsIContent* aSubmitElement)
nsHTMLButtonElement::SubmitNamesValues(nsFormSubmission* aFormSubmission)
{
nsresult rv = NS_OK;
//
// We only submit if we were the button pressed
//
if (aSubmitElement != this) {
if (aFormSubmission->GetOriginatingElement() != this) {
return NS_OK;
}
@ -622,3 +647,19 @@ nsHTMLButtonElement::RestoreState(nsPresState* aState)
return PR_FALSE;
}
PRInt32
nsHTMLButtonElement::IntrinsicState() const
{
return NS_EVENT_STATE_OPTIONAL | nsGenericHTMLFormElement::IntrinsicState();
}
// nsConstraintValidation
PRBool
nsHTMLButtonElement::IsBarredFromConstraintValidation()
{
return (mType == NS_FORM_BUTTON_BUTTON ||
mType == NS_FORM_BUTTON_RESET);
}

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

@ -41,10 +41,12 @@
#include "nsStyleConsts.h"
#include "nsIForm.h"
#include "nsIFormControl.h"
#include "nsConstraintValidation.h"
class nsHTMLFieldSetElement : public nsGenericHTMLFormElement,
public nsIDOMHTMLFieldSetElement
public nsIDOMHTMLFieldSetElement,
public nsConstraintValidation
{
public:
nsHTMLFieldSetElement(already_AddRefed<nsINodeInfo> aNodeInfo);
@ -68,10 +70,12 @@ public:
// nsIFormControl
NS_IMETHOD_(PRUint32) GetType() const { return NS_FORM_FIELDSET; }
NS_IMETHOD Reset();
NS_IMETHOD SubmitNamesValues(nsFormSubmission* aFormSubmission,
nsIContent* aSubmitElement);
NS_IMETHOD SubmitNamesValues(nsFormSubmission* aFormSubmission);
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
virtual nsXPCClassInfo* GetClassInfo();
// nsConstraintValidation
PRBool IsBarredFromConstraintValidation() { return PR_TRUE; };
};
// construction, destruction
@ -107,6 +111,8 @@ NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLFieldSetElement)
// nsIDOMHTMLFieldSetElement
// nsConstraintValidation
NS_IMPL_NSCONSTRAINTVALIDATION(nsHTMLFieldSetElement)
NS_IMPL_ELEMENT_CLONE(nsHTMLFieldSetElement)
@ -128,8 +134,7 @@ nsHTMLFieldSetElement::Reset()
}
NS_IMETHODIMP
nsHTMLFieldSetElement::SubmitNamesValues(nsFormSubmission* aFormSubmission,
nsIContent* aSubmitElement)
nsHTMLFieldSetElement::SubmitNamesValues(nsFormSubmission* aFormSubmission)
{
return NS_OK;
}

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

@ -65,6 +65,7 @@
#include "nsIWebProgress.h"
#include "nsIDocShell.h"
#include "nsFormData.h"
#include "nsFormSubmissionConstants.h"
// radio buttons
#include "nsIDOMHTMLInputElement.h"
@ -80,23 +81,6 @@
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;
@ -200,6 +184,7 @@ ShouldBeInElements(nsIFormControl* aFormControl)
case NS_FORM_BUTTON_SUBMIT :
case NS_FORM_INPUT_BUTTON :
case NS_FORM_INPUT_CHECKBOX :
case NS_FORM_INPUT_EMAIL :
case NS_FORM_INPUT_FILE :
case NS_FORM_INPUT_HIDDEN :
case NS_FORM_INPUT_RESET :
@ -209,6 +194,7 @@ ShouldBeInElements(nsIFormControl* aFormControl)
case NS_FORM_INPUT_SUBMIT :
case NS_FORM_INPUT_TEXT :
case NS_FORM_INPUT_TEL :
case NS_FORM_INPUT_URL :
case NS_FORM_SELECT :
case NS_FORM_TEXTAREA :
case NS_FORM_FIELDSET :
@ -373,6 +359,7 @@ nsHTMLFormElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
}
NS_IMPL_STRING_ATTR(nsHTMLFormElement, AcceptCharset, acceptcharset)
NS_IMPL_STRING_ATTR(nsHTMLFormElement, Action, action)
NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLFormElement, Enctype, enctype,
kFormDefaultEnctype->tag)
NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLFormElement, Method, method,
@ -381,7 +368,7 @@ NS_IMPL_STRING_ATTR(nsHTMLFormElement, Name, name)
NS_IMPL_STRING_ATTR(nsHTMLFormElement, Target, target)
NS_IMETHODIMP
nsHTMLFormElement::GetAction(nsAString& aValue)
nsHTMLFormElement::GetMozActionUri(nsAString& aValue)
{
GetAttr(kNameSpaceID_None, nsGkAtoms::action, aValue);
if (aValue.IsEmpty()) {
@ -391,12 +378,6 @@ nsHTMLFormElement::GetAction(nsAString& aValue)
return GetURIAttr(nsGkAtoms::action, nsnull, aValue);
}
NS_IMETHODIMP
nsHTMLFormElement::SetAction(const nsAString& aValue)
{
return SetAttr(kNameSpaceID_None, nsGkAtoms::action, aValue, PR_TRUE);
}
NS_IMETHODIMP
nsHTMLFormElement::Submit()
{
@ -707,7 +688,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...
@ -744,10 +729,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);
}
}
}
@ -756,13 +748,13 @@ nsHTMLFormElement::BuildSubmission(nsFormSubmission** aFormSubmission,
//
// Get the submission object
//
rv = GetSubmissionFromForm(this, aFormSubmission);
rv = GetSubmissionFromForm(this, originatingElement, aFormSubmission);
NS_ENSURE_SUBMIT_SUCCESS(rv);
//
// Dump the data into the submission object
//
rv = WalkFormElements(*aFormSubmission, originatingElement);
rv = WalkFormElements(*aFormSubmission);
NS_ENSURE_SUBMIT_SUCCESS(rv);
return NS_OK;
@ -772,11 +764,13 @@ nsresult
nsHTMLFormElement::SubmitSubmission(nsFormSubmission* aFormSubmission)
{
nsresult rv;
nsIContent* originatingElement = aFormSubmission->GetOriginatingElement();
//
// Get the action and target
//
nsCOMPtr<nsIURI> actionURI;
rv = GetActionURL(getter_AddRefs(actionURI));
rv = GetActionURL(getter_AddRefs(actionURI), originatingElement);
NS_ENSURE_SUBMIT_SUCCESS(rv);
if (!actionURI) {
@ -810,8 +804,18 @@ nsHTMLFormElement::SubmitSubmission(nsFormSubmission* aFormSubmission)
mIsSubmitting = PR_FALSE;
}
// The target is the originating element formtarget attribute if the element
// is a submit control and has such an attribute.
// Otherwise, the target is the form owner's target attribute,
// if it has such an attribute.
// Finally, if one of the child nodes of the head element is a base element
// with a target attribute, then the value of the target attribute of the
// first such base element; or, if there is no such element, the empty string.
nsAutoString target;
if (!GetAttr(kNameSpaceID_None, nsGkAtoms::target, target)) {
if (!(originatingElement && originatingElement->GetAttr(kNameSpaceID_None,
nsGkAtoms::formtarget,
target)) &&
!GetAttr(kNameSpaceID_None, nsGkAtoms::target, target)) {
GetBaseTarget(target);
}
@ -947,8 +951,7 @@ nsHTMLFormElement::NotifySubmitObservers(nsIURI* aActionURL,
nsresult
nsHTMLFormElement::WalkFormElements(nsFormSubmission* aFormSubmission,
nsIContent* aSubmitElement)
nsHTMLFormElement::WalkFormElements(nsFormSubmission* aFormSubmission)
{
nsTArray<nsGenericHTMLFormElement*> sortedControls;
nsresult rv = mControls->GetSortedControls(sortedControls);
@ -960,7 +963,7 @@ nsHTMLFormElement::WalkFormElements(nsFormSubmission* aFormSubmission,
PRUint32 len = sortedControls.Length();
for (PRUint32 i = 0; i < len; ++i) {
// Tell the control to submit its name/value pairs to the submission
sortedControls[i]->SubmitNamesValues(aFormSubmission, aSubmitElement);
sortedControls[i]->SubmitNamesValues(aFormSubmission);
}
return NS_OK;
@ -1291,7 +1294,7 @@ nsHTMLFormElement::DoResolveName(const nsAString& aName,
}
void
nsHTMLFormElement::OnSubmitClickBegin()
nsHTMLFormElement::OnSubmitClickBegin(nsIContent* aOriginatingElement)
{
mDeferSubmission = PR_TRUE;
@ -1301,7 +1304,7 @@ nsHTMLFormElement::OnSubmitClickBegin()
nsCOMPtr<nsIURI> actionURI;
nsresult rv;
rv = GetActionURL(getter_AddRefs(actionURI));
rv = GetActionURL(getter_AddRefs(actionURI), aOriginatingElement);
if (NS_FAILED(rv) || !actionURI)
return;
@ -1335,7 +1338,8 @@ nsHTMLFormElement::FlushPendingSubmission()
}
nsresult
nsHTMLFormElement::GetActionURL(nsIURI** aActionURL)
nsHTMLFormElement::GetActionURL(nsIURI** aActionURL,
nsIContent* aOriginatingElement)
{
nsresult rv = NS_OK;
@ -1344,8 +1348,23 @@ nsHTMLFormElement::GetActionURL(nsIURI** aActionURL)
//
// Grab the URL string
//
// If the originating element is a submit control and has the formaction
// attribute specified, it should be used. Otherwise, the action attribute
// from the form element should be used.
//
nsAutoString action;
GetAction(action);
nsCOMPtr<nsIFormControl> formControl = do_QueryInterface(aOriginatingElement);
if (formControl && formControl->IsSubmitControl() &&
aOriginatingElement->GetAttr(kNameSpaceID_None, nsGkAtoms::formaction,
action)) {
// Avoid resolving action="" to the base uri, bug 297761.
if (!action.IsEmpty()) {
static_cast<nsGenericHTMLElement*>(aOriginatingElement)->
GetURIAttr(nsGkAtoms::formaction, nsnull, action);
}
} else {
GetMozActionUri(action);
}
//
// Form the full action URL
@ -1488,7 +1507,7 @@ nsHTMLFormElement::GetFormData(nsIDOMFormData** aFormData)
{
nsRefPtr<nsFormData> fd = new nsFormData();
nsresult rv = WalkFormElements(fd, nsnull);
nsresult rv = WalkFormElements(fd);
NS_ENSURE_SUCCESS(rv, rv);
*aFormData = fd.forget().get();

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

@ -241,7 +241,7 @@ public:
* submission. In that case the form will defer the submission until the
* script handler returns and the return value is known.
*/
void OnSubmitClickBegin();
void OnSubmitClickBegin(nsIContent* aOriginatingElement);
void OnSubmitClickEnd();
virtual nsXPCClassInfo* GetClassInfo();
@ -304,10 +304,8 @@ protected:
* their data pumped into the FormSubmitter.
*
* @param aFormSubmission the form submission object
* @param aSubmitElement the element that was clicked on (nsnull if none)
*/
nsresult WalkFormElements(nsFormSubmission* aFormSubmission,
nsIContent* aSubmitElement);
nsresult WalkFormElements(nsFormSubmission* aFormSubmission);
/**
* Notify any submit observers of the submit.
@ -328,8 +326,9 @@ protected:
* Get the full URL to submit to. Do not submit if the returned URL is null.
*
* @param aActionURL the full, unadulterated URL you'll be submitting to [OUT]
* @param aOriginatingElement the originating element of the form submission [IN]
*/
nsresult GetActionURL(nsIURI** aActionURL);
nsresult GetActionURL(nsIURI** aActionURL, nsIContent* aOriginatingElement);
public:
/**

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

@ -283,8 +283,8 @@ MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
// 100% on all corners
nsCSSCornerSizes& corners = aData->mMarginData->mBorderRadius;
NS_FOR_CSS_HALF_CORNERS(hc) {
nsCSSValue& dimen = corners.GetHalfCorner(hc);
NS_FOR_CSS_FULL_CORNERS(c) {
nsCSSValue& dimen = corners.GetCorner(c);
if (dimen.GetUnit() == eCSSUnit_Null) {
dimen.SetPercentValue(1.0f);
}

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

@ -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"
@ -69,6 +70,7 @@
#include "nsIPrivateDOMEvent.h"
#include "nsIEditor.h"
#include "nsGUIEvent.h"
#include "nsIIOService.h"
#include "nsPresState.h"
#include "nsLayoutErrors.h"
@ -107,9 +109,17 @@
#include "mozAutoDocUpdate.h"
#include "nsHTMLFormElement.h"
#include "nsContentCreatorFunctions.h"
#include "nsCharSeparatedTokenizer.h"
#include "nsContentUtils.h"
#include "nsTextEditRules.h"
// JS headers are needed for the pattern attribute.
#include "jsapi.h" // for js_SaveAndClearRegExpStatics
// and js_RestoreRegExpStatics
#include "jsregexp.h" // for js::AutoValueRooter
#include "jscntxt.h"
#include "nsHTMLInputElement.h"
// XXX align=left, hspace, vspace, border? other nav4 attrs
@ -133,6 +143,7 @@ static PRInt32 gSelectTextFieldOnFocus;
static const nsAttrValue::EnumTable kInputTypeTable[] = {
{ "button", NS_FORM_INPUT_BUTTON },
{ "checkbox", NS_FORM_INPUT_CHECKBOX },
{ "email", NS_FORM_INPUT_EMAIL },
{ "file", NS_FORM_INPUT_FILE },
{ "hidden", NS_FORM_INPUT_HIDDEN },
{ "reset", NS_FORM_INPUT_RESET },
@ -143,11 +154,12 @@ static const nsAttrValue::EnumTable kInputTypeTable[] = {
{ "submit", NS_FORM_INPUT_SUBMIT },
{ "tel", NS_FORM_INPUT_TEL },
{ "text", NS_FORM_INPUT_TEXT },
{ "url", NS_FORM_INPUT_URL },
{ 0 }
};
// Default type is 'text'.
static const nsAttrValue::EnumTable* kInputDefaultType = &kInputTypeTable[11];
static const nsAttrValue::EnumTable* kInputDefaultType = &kInputTypeTable[12];
#define NS_INPUT_ELEMENT_STATE_IID \
{ /* dc3b3d14-23e2-4479-b513-7b369343e3a0 */ \
@ -298,6 +310,8 @@ NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsHTMLInputElement)
nsGenericHTMLFormElement)
NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLInputElement)
// nsConstraintValidation
NS_IMPL_NSCONSTRAINTVALIDATION(nsHTMLInputElement)
// nsIDOMNode
@ -317,10 +331,12 @@ nsHTMLInputElement::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const
NS_ENSURE_SUCCESS(rv, rv);
switch (mType) {
case NS_FORM_INPUT_EMAIL:
case NS_FORM_INPUT_SEARCH:
case NS_FORM_INPUT_TEXT:
case NS_FORM_INPUT_PASSWORD:
case NS_FORM_INPUT_TEL:
case NS_FORM_INPUT_URL:
if (GET_BOOLBIT(mBitField, BF_VALUE_CHANGED)) {
// We don't have our default value anymore. Set our value on
// the clone.
@ -450,10 +466,12 @@ nsHTMLInputElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
// If we are changing type from File/Text/Tel/Passwd to other input types
// we need save the mValue into value attribute
if (mInputData.mValue &&
mType != NS_FORM_INPUT_EMAIL &&
mType != NS_FORM_INPUT_TEXT &&
mType != NS_FORM_INPUT_SEARCH &&
mType != NS_FORM_INPUT_PASSWORD &&
mType != NS_FORM_INPUT_TEL &&
mType != NS_FORM_INPUT_URL &&
mType != NS_FORM_INPUT_FILE) {
SetAttr(kNameSpaceID_None, nsGkAtoms::value,
NS_ConvertUTF8toUTF16(mInputData.mValue), PR_FALSE);
@ -491,7 +509,9 @@ nsHTMLInputElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
NS_EVENT_STATE_LOADING |
NS_EVENT_STATE_INDETERMINATE |
NS_EVENT_STATE_MOZ_READONLY |
NS_EVENT_STATE_MOZ_READWRITE);
NS_EVENT_STATE_MOZ_READWRITE |
NS_EVENT_STATE_REQUIRED |
NS_EVENT_STATE_OPTIONAL);
}
}
@ -532,15 +552,23 @@ NS_IMPL_STRING_ATTR(nsHTMLInputElement, Alt, alt)
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)
NS_IMPL_STRING_ATTR(nsHTMLInputElement, Name, name)
NS_IMPL_BOOL_ATTR(nsHTMLInputElement, ReadOnly, readonly)
NS_IMPL_BOOL_ATTR(nsHTMLInputElement, Required, required)
NS_IMPL_URI_ATTR(nsHTMLInputElement, Src, src)
NS_IMPL_INT_ATTR_DEFAULT_VALUE(nsHTMLInputElement, TabIndex, tabindex, 0)
NS_IMPL_STRING_ATTR(nsHTMLInputElement, UseMap, usemap)
//NS_IMPL_STRING_ATTR(nsHTMLInputElement, Value, value)
//NS_IMPL_INT_ATTR_DEFAULT_VALUE(nsHTMLInputElement, Size, size, 0)
NS_IMPL_STRING_ATTR(nsHTMLInputElement, Pattern, pattern)
NS_IMPL_STRING_ATTR(nsHTMLInputElement, Placeholder, placeholder)
NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLInputElement, Type, type,
kInputDefaultType->tag)
@ -1082,17 +1110,7 @@ nsHTMLInputElement::RadioSetChecked(PRBool aNotify)
//
// Find the selected radio button so we can deselect it
//
nsCOMPtr<nsIDOMHTMLInputElement> currentlySelected;
nsCOMPtr<nsIRadioGroupContainer> container = GetRadioGroupContainer();
// This is ONLY INITIALIZED IF container EXISTS
nsAutoString name;
PRBool nameExists = PR_FALSE;
if (container) {
nameExists = GetNameIfExists(name);
if (nameExists) {
container->GetCurrentRadioButton(name, getter_AddRefs(currentlySelected));
}
}
nsCOMPtr<nsIDOMHTMLInputElement> currentlySelected = GetSelectedRadioButton();
//
// Deselect the currently selected radio button
@ -1115,7 +1133,9 @@ nsHTMLInputElement::RadioSetChecked(PRBool aNotify)
// Let the group know that we are now the One True Radio Button
//
NS_ENSURE_SUCCESS(rv, rv);
if (container && nameExists) {
nsCOMPtr<nsIRadioGroupContainer> container = GetRadioGroupContainer();
nsAutoString name;
if (container && GetNameIfExists(name)) {
rv = container->SetCurrentRadioButton(name, this);
}
@ -1137,6 +1157,25 @@ nsHTMLInputElement::GetRadioGroupContainer()
return retval;
}
already_AddRefed<nsIDOMHTMLInputElement>
nsHTMLInputElement::GetSelectedRadioButton()
{
nsIDOMHTMLInputElement* selected;
nsCOMPtr<nsIRadioGroupContainer> container = GetRadioGroupContainer();
if (!container) {
return nsnull;
}
nsAutoString name;
if (!GetNameIfExists(name)) {
return nsnull;
}
container->GetCurrentRadioButton(name, &selected);
return selected;
}
nsresult
nsHTMLInputElement::MaybeSubmitForm(nsPresContext* aPresContext)
{
@ -1500,16 +1539,8 @@ nsHTMLInputElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
case NS_FORM_INPUT_RADIO:
{
nsCOMPtr<nsIRadioGroupContainer> container = GetRadioGroupContainer();
if (container) {
nsAutoString name;
if (GetNameIfExists(name)) {
nsCOMPtr<nsIDOMHTMLInputElement> selectedRadioButton;
container->GetCurrentRadioButton(name,
getter_AddRefs(selectedRadioButton));
aVisitor.mItemData = selectedRadioButton;
}
}
nsCOMPtr<nsIDOMHTMLInputElement> selectedRadioButton = GetSelectedRadioButton();
aVisitor.mItemData = selectedRadioButton;
originalCheckedValue = GetChecked();
if (!originalCheckedValue) {
@ -1525,7 +1556,7 @@ nsHTMLInputElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
// tell the form that we are about to enter a click handler.
// that means that if there are scripted submissions, the
// latest one will be deferred until after the exit point of the handler.
mForm->OnSubmitClickBegin();
mForm->OnSubmitClickBegin(this);
}
break;
@ -1831,9 +1862,11 @@ nsHTMLInputElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
(keyEvent->keyCode == NS_VK_RETURN ||
keyEvent->keyCode == NS_VK_ENTER) &&
(mType == NS_FORM_INPUT_TEXT ||
mType == NS_FORM_INPUT_EMAIL ||
mType == NS_FORM_INPUT_SEARCH ||
mType == NS_FORM_INPUT_PASSWORD ||
mType == NS_FORM_INPUT_TEL ||
mType == NS_FORM_INPUT_URL ||
mType == NS_FORM_INPUT_FILE)) {
PRBool isButton = PR_FALSE;
@ -2045,11 +2078,20 @@ nsHTMLInputElement::SanitizeValue(nsAString& aValue)
case NS_FORM_INPUT_SEARCH:
case NS_FORM_INPUT_TEL:
case NS_FORM_INPUT_PASSWORD:
case NS_FORM_INPUT_EMAIL:
{
PRUnichar crlf[] = { PRUnichar('\r'), PRUnichar('\n'), 0 };
aValue.StripChars(crlf);
}
break;
case NS_FORM_INPUT_URL:
{
PRUnichar crlf[] = { PRUnichar('\r'), PRUnichar('\n'), 0 };
aValue.StripChars(crlf);
aValue = nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(aValue);
}
break;
}
}
@ -2108,6 +2150,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,
@ -2384,8 +2432,10 @@ nsHTMLInputElement::SetDefaultValueAsValue()
}
case NS_FORM_INPUT_SEARCH:
case NS_FORM_INPUT_PASSWORD:
case NS_FORM_INPUT_EMAIL:
case NS_FORM_INPUT_TEXT:
case NS_FORM_INPUT_TEL:
case NS_FORM_INPUT_URL:
{
nsAutoString resetVal;
GetDefaultValue(resetVal);
@ -2420,8 +2470,10 @@ nsHTMLInputElement::Reset()
break;
case NS_FORM_INPUT_SEARCH:
case NS_FORM_INPUT_PASSWORD:
case NS_FORM_INPUT_EMAIL:
case NS_FORM_INPUT_TEXT:
case NS_FORM_INPUT_TEL:
case NS_FORM_INPUT_URL:
SetValueChanged(PR_FALSE);
break;
default:
@ -2432,8 +2484,7 @@ nsHTMLInputElement::Reset()
}
NS_IMETHODIMP
nsHTMLInputElement::SubmitNamesValues(nsFormSubmission* aFormSubmission,
nsIContent* aSubmitElement)
nsHTMLInputElement::SubmitNamesValues(nsFormSubmission* aFormSubmission)
{
nsresult rv = NS_OK;
@ -2447,7 +2498,7 @@ nsHTMLInputElement::SubmitNamesValues(nsFormSubmission* aFormSubmission,
if (disabled || mType == NS_FORM_INPUT_RESET ||
mType == NS_FORM_INPUT_BUTTON ||
((mType == NS_FORM_INPUT_SUBMIT || mType == NS_FORM_INPUT_IMAGE) &&
aSubmitElement != this) ||
aFormSubmission->GetOriginatingElement() != this) ||
((mType == NS_FORM_INPUT_RADIO || mType == NS_FORM_INPUT_CHECKBOX) &&
!GetChecked())) {
return NS_OK;
@ -2586,9 +2637,11 @@ nsHTMLInputElement::SaveState()
// Never save passwords in session history
case NS_FORM_INPUT_PASSWORD:
break;
case NS_FORM_INPUT_EMAIL:
case NS_FORM_INPUT_SEARCH:
case NS_FORM_INPUT_TEXT:
case NS_FORM_INPUT_TEL:
case NS_FORM_INPUT_URL:
case NS_FORM_INPUT_HIDDEN:
{
if (GET_BOOLBIT(mBitField, BF_VALUE_CHANGED)) {
@ -2701,6 +2754,12 @@ nsHTMLInputElement::IntrinsicState() const
state |= nsImageLoadingContent::ImageState();
}
if (DoesRequiredApply() && HasAttr(kNameSpaceID_None, nsGkAtoms::required)) {
state |= NS_EVENT_STATE_REQUIRED;
} else {
state |= NS_EVENT_STATE_OPTIONAL;
}
return state;
}
@ -2724,9 +2783,11 @@ nsHTMLInputElement::RestoreState(nsPresState* aState)
break;
}
case NS_FORM_INPUT_EMAIL:
case NS_FORM_INPUT_SEARCH:
case NS_FORM_INPUT_TEXT:
case NS_FORM_INPUT_TEL:
case NS_FORM_INPUT_URL:
case NS_FORM_INPUT_HIDDEN:
{
SetValueInternal(inputState->GetValue(), PR_FALSE, PR_TRUE);
@ -2956,6 +3017,468 @@ nsHTMLInputElement::VisitGroup(nsIRadioVisitor* aVisitor, PRBool aFlushContent)
return rv;
}
nsHTMLInputElement::ValueModeType
nsHTMLInputElement::GetValueMode() const
{
switch (mType)
{
case NS_FORM_INPUT_HIDDEN:
case NS_FORM_INPUT_SUBMIT:
case NS_FORM_INPUT_BUTTON:
case NS_FORM_INPUT_RESET:
case NS_FORM_INPUT_IMAGE:
return VALUE_MODE_DEFAULT;
case NS_FORM_INPUT_CHECKBOX:
case NS_FORM_INPUT_RADIO:
return VALUE_MODE_DEFAULT_ON;
case NS_FORM_INPUT_FILE:
return VALUE_MODE_FILENAME;
#ifdef DEBUG
case NS_FORM_INPUT_TEXT:
case NS_FORM_INPUT_PASSWORD:
case NS_FORM_INPUT_SEARCH:
case NS_FORM_INPUT_TEL:
case NS_FORM_INPUT_EMAIL:
case NS_FORM_INPUT_URL:
return VALUE_MODE_VALUE;
default:
NS_NOTYETIMPLEMENTED("Unexpected input type in GetValueMode()");
return VALUE_MODE_VALUE;
#else // DEBUG
default:
return VALUE_MODE_VALUE;
#endif // DEBUG
}
}
PRBool
nsHTMLInputElement::IsMutable() const
{
return !HasAttr(kNameSpaceID_None, nsGkAtoms::disabled) &&
GetCurrentDoc() &&
!(DoesReadOnlyApply() &&
HasAttr(kNameSpaceID_None, nsGkAtoms::readonly));
}
PRBool
nsHTMLInputElement::DoesReadOnlyApply() const
{
switch (mType)
{
case NS_FORM_INPUT_HIDDEN:
case NS_FORM_INPUT_BUTTON:
case NS_FORM_INPUT_IMAGE:
case NS_FORM_INPUT_RESET:
case NS_FORM_INPUT_SUBMIT:
case NS_FORM_INPUT_RADIO:
case NS_FORM_INPUT_FILE:
case NS_FORM_INPUT_CHECKBOX:
// TODO:
// case NS_FORM_INPUT_COLOR:
// case NS_FORM_INPUT_RANGE:
return PR_FALSE;
#ifdef DEBUG
case NS_FORM_INPUT_TEXT:
case NS_FORM_INPUT_PASSWORD:
case NS_FORM_INPUT_SEARCH:
case NS_FORM_INPUT_TEL:
case NS_FORM_INPUT_EMAIL:
case NS_FORM_INPUT_URL:
return PR_TRUE;
default:
NS_NOTYETIMPLEMENTED("Unexpected input type in DoesReadOnlyApply()");
return PR_TRUE;
#else // DEBUG
default:
return PR_TRUE;
#endif // DEBUG
}
}
PRBool
nsHTMLInputElement::DoesRequiredApply() const
{
switch (mType)
{
case NS_FORM_INPUT_HIDDEN:
case NS_FORM_INPUT_BUTTON:
case NS_FORM_INPUT_IMAGE:
case NS_FORM_INPUT_RESET:
case NS_FORM_INPUT_SUBMIT:
// TODO:
// case NS_FORM_INPUT_COLOR:
// case NS_FORM_INPUT_RANGE:
return PR_FALSE;
#ifdef DEBUG
case NS_FORM_INPUT_RADIO:
case NS_FORM_INPUT_CHECKBOX:
case NS_FORM_INPUT_FILE:
case NS_FORM_INPUT_TEXT:
case NS_FORM_INPUT_PASSWORD:
case NS_FORM_INPUT_SEARCH:
case NS_FORM_INPUT_TEL:
case NS_FORM_INPUT_EMAIL:
case NS_FORM_INPUT_URL:
return PR_TRUE;
default:
NS_NOTYETIMPLEMENTED("Unexpected input type in DoesRequiredApply()");
return PR_TRUE;
#else // DEBUG
default:
return PR_TRUE;
#endif // DEBUG
}
}
PRBool
nsHTMLInputElement::DoesPatternApply() const
{
return IsSingleLineTextControl(PR_FALSE);
}
// nsConstraintValidation
PRBool
nsHTMLInputElement::IsTooLong()
{
if (!GET_BOOLBIT(mBitField, BF_VALUE_CHANGED)) {
return PR_FALSE;
}
PRInt32 maxLength = -1;
PRInt32 textLength = -1;
GetMaxLength(&maxLength);
GetTextLength(&textLength);
return (maxLength >= 0) && (textLength > maxLength);
}
PRBool
nsHTMLInputElement::IsValueMissing()
{
if (!HasAttr(kNameSpaceID_None, nsGkAtoms::required) ||
!DoesRequiredApply()) {
return PR_FALSE;
}
if (GetValueMode() == VALUE_MODE_VALUE) {
if (!IsMutable()) {
return PR_FALSE;
}
nsAutoString value;
nsresult rv = GetValue(value);
NS_ENSURE_SUCCESS(rv, PR_FALSE);
return value.IsEmpty();
}
if (mType == NS_FORM_INPUT_CHECKBOX) {
return !GetChecked();
}
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) {
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);
} 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
* there is no code to check for a valid URI/IRI according to 3986 and 3987
* RFC's at the moment, see bug 561586.
*
* RFC 3987 (IRI) implementation: bug 42899
*
* HTML5 specifications:
* http://dev.w3.org/html5/spec/infrastructure.html#valid-url
*/
nsCOMPtr<nsIIOService> ioService = do_GetIOService();
nsCOMPtr<nsIURI> uri;
return !NS_SUCCEEDED(ioService->NewURI(NS_ConvertUTF16toUTF8(value), nsnull,
nsnull, getter_AddRefs(uri)));
}
return PR_FALSE;
}
PRBool
nsHTMLInputElement::HasPatternMismatch()
{
nsAutoString pattern;
if (!DoesPatternApply() || !GetAttr(kNameSpaceID_None, nsGkAtoms::pattern,
pattern)) {
return PR_FALSE;
}
nsAutoString value;
NS_ENSURE_SUCCESS(GetValue(value), PR_FALSE);
if (value.IsEmpty()) {
return PR_FALSE;
}
nsIDocument* doc = GetOwnerDoc();
if (!doc) {
return PR_FALSE;
}
return !IsPatternMatching(value, pattern, doc);
}
PRBool
nsHTMLInputElement::IsBarredFromConstraintValidation()
{
return mType == NS_FORM_INPUT_HIDDEN ||
mType == NS_FORM_INPUT_BUTTON ||
mType == NS_FORM_INPUT_RESET ||
HasAttr(kNameSpaceID_None, nsGkAtoms::readonly);
}
nsresult
nsHTMLInputElement::GetValidationMessage(nsAString& aValidationMessage,
ValidationMessageType aType)
{
nsresult rv = NS_OK;
switch (aType)
{
case VALIDATION_MESSAGE_TOO_LONG:
{
nsXPIDLString message;
PRInt32 maxLength = -1;
PRInt32 textLength = -1;
nsAutoString strMaxLength;
nsAutoString strTextLength;
GetMaxLength(&maxLength);
GetTextLength(&textLength);
strMaxLength.AppendInt(maxLength);
strTextLength.AppendInt(textLength);
const PRUnichar* params[] = { strTextLength.get(), strMaxLength.get() };
rv = nsContentUtils::FormatLocalizedString(nsContentUtils::eDOM_PROPERTIES,
"ElementSuffersFromBeingTooLong",
params, 2, message);
aValidationMessage = message;
break;
}
case VALIDATION_MESSAGE_VALUE_MISSING:
{
nsXPIDLString message;
nsCAutoString key;
switch (mType)
{
case NS_FORM_INPUT_FILE:
key.Assign("FileElementSuffersFromBeingMissing");
break;
case NS_FORM_INPUT_CHECKBOX:
key.Assign("CheckboxElementSuffersFromBeingMissing");
break;
case NS_FORM_INPUT_RADIO:
key.Assign("RadioElementSuffersFromBeingMissing");
break;
default:
key.Assign("TextElementSuffersFromBeingMissing");
}
rv = nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES,
key.get(), message);
aValidationMessage = message;
break;
}
case VALIDATION_MESSAGE_TYPE_MISMATCH:
{
nsXPIDLString message;
nsCAutoString key;
if (mType == NS_FORM_INPUT_EMAIL) {
key.AssignLiteral("ElementSuffersFromInvalidEmail");
} else if (mType == NS_FORM_INPUT_URL) {
key.AssignLiteral("ElementSuffersFromInvalidURL");
} else {
return NS_ERROR_UNEXPECTED;
}
rv = nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES,
key.get(), message);
aValidationMessage = message;
break;
}
case VALIDATION_MESSAGE_PATTERN_MISMATCH:
{
nsXPIDLString message;
nsAutoString title;
GetAttr(kNameSpaceID_None, nsGkAtoms::title, title);
if (title.IsEmpty()) {
rv = nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES,
"ElementSuffersFromPatternMismatch",
message);
} else {
const PRUnichar* params[] = { title.get() };
rv = nsContentUtils::FormatLocalizedString(nsContentUtils::eDOM_PROPERTIES,
"ElementSuffersFromPatternMismatchWithTitle",
params, 1, message);
}
aValidationMessage = message;
break;
}
default:
rv = nsConstraintValidation::GetValidationMessage(aValidationMessage, aType);
}
return rv;
}
//static
PRBool
nsHTMLInputElement::IsValidEmailAddressList(const nsAString& aValue)
{
nsCharSeparatedTokenizerTemplate<nsContentUtils::IsHTMLWhitespace>
tokenizer(aValue, ',');
while (tokenizer.hasMoreTokens()) {
if (!IsValidEmailAddress(tokenizer.nextToken())) {
return PR_FALSE;
}
}
return !tokenizer.lastTokenEndedWithSeparator();
}
//static
PRBool
nsHTMLInputElement::IsValidEmailAddress(const nsAString& aValue)
{
PRUint32 i = 0;
PRUint32 length = aValue.Length();
// If the email address is empty, begins with a '@' or ends with a '.',
// we know it's invalid.
if (length == 0 || aValue[0] == '@' || aValue[length-1] == '.') {
return PR_FALSE;
}
// Parsing the username.
for (; i < length && aValue[i] != '@'; ++i) {
PRUnichar c = aValue[i];
// The username characters have to be in this list to be valid.
if (!(nsCRT::IsAsciiAlpha(c) || nsCRT::IsAsciiDigit(c) ||
c == '.' || c == '!' || c == '#' || c == '$' || c == '%' ||
c == '&' || c == '\''|| c == '*' || c == '+' || c == '-' ||
c == '/' || c == '=' || c == '?' || c == '^' || c == '_' ||
c == '`' || c == '{' || c == '|' || c == '}' || c == '~' )) {
return PR_FALSE;
}
}
// There is no domain name (or it's one-character long),
// that's not a valid email address.
if (++i >= length) {
return PR_FALSE;
}
// The domain name can't begin with a dot.
if (aValue[i] == '.') {
return PR_FALSE;
}
// The domain name must have at least one dot which can't follow another dot,
// can't be the first nor the last domain name character.
PRBool dotFound = PR_FALSE;
// Parsing the domain name.
for (; i < length; ++i) {
PRUnichar c = aValue[i];
if (c == '.') {
dotFound = PR_TRUE;
// A dot can't follow a dot.
if (aValue[i-1] == '.') {
return PR_FALSE;
}
} else if (!(nsCRT::IsAsciiAlpha(c) || nsCRT::IsAsciiDigit(c) ||
c == '-')) {
// The domain characters have to be in this list to be valid.
return PR_FALSE;
}
}
return dotFound;
}
//static
PRBool
nsHTMLInputElement::IsPatternMatching(nsAString& aValue, nsAString& aPattern,
nsIDocument* aDocument)
{
NS_ASSERTION(aDocument, "aDocument should be a valid pointer (not null)");
NS_ENSURE_TRUE(aDocument->GetScriptGlobalObject(), PR_TRUE);
JSContext* ctx = (JSContext*) aDocument->GetScriptGlobalObject()->
GetContext()->GetNativeContext();
NS_ENSURE_TRUE(ctx, PR_TRUE);
JSAutoRequest ar(ctx);
// The pattern has to match the entire value.
aPattern.Insert(NS_LITERAL_STRING("^(?:"), 0);
aPattern.Append(NS_LITERAL_STRING(")$"));
JSObject* re = JS_NewUCRegExpObject(ctx, reinterpret_cast<jschar*>
(aPattern.BeginWriting()),
aPattern.Length(), 0);
NS_ENSURE_TRUE(re, PR_TRUE);
js::AutoObjectRooter re_root(ctx, re);
js::AutoStringRooter tvr(ctx);
js::RegExpStatics statics(ctx);
jsval rval = JSVAL_NULL;
size_t idx = 0;
JSBool res;
js_SaveAndClearRegExpStatics(ctx, &statics, &tvr);
res = JS_ExecuteRegExp(ctx, re, reinterpret_cast<jschar*>
(aValue.BeginWriting()),
aValue.Length(), &idx, JS_TRUE, &rval);
js_RestoreRegExpStatics(ctx, &statics);
return res == JS_FALSE || rval != JSVAL_NULL;
}
//
// Visitor classes

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

@ -49,6 +49,7 @@
#include "nsTextEditorState.h"
#include "nsCOMPtr.h"
#include "nsConstraintValidation.h"
//
// Accessors for mBitField
@ -80,7 +81,8 @@ class nsHTMLInputElement : public nsGenericHTMLFormElement,
public nsITextControlElement,
public nsIPhonetic,
public nsIDOMNSEditableElement,
public nsIFileControlElement
public nsIFileControlElement,
public nsConstraintValidation
{
public:
nsHTMLInputElement(already_AddRefed<nsINodeInfo> aNodeInfo,
@ -115,8 +117,7 @@ public:
// Overriden nsIFormControl methods
NS_IMETHOD_(PRUint32) GetType() const { return mType; }
NS_IMETHOD Reset();
NS_IMETHOD SubmitNamesValues(nsFormSubmission* aFormSubmission,
nsIContent* aSubmitElement);
NS_IMETHOD SubmitNamesValues(nsFormSubmission* aFormSubmission);
NS_IMETHOD SaveState();
virtual PRBool RestoreState(nsPresState* aState);
virtual PRBool AllowDrop();
@ -186,6 +187,15 @@ public:
*/
virtual already_AddRefed<nsIRadioGroupContainer> GetRadioGroupContainer();
/**
* Helper function returning the currently selected button in the radio group.
* Returning null if the element is not a button or if there is no selectied
* button in the group.
*
* @return the selected button (or null).
*/
already_AddRefed<nsIDOMHTMLInputElement> GetSelectedRadioButton();
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
virtual void UpdateEditableState()
@ -200,11 +210,82 @@ public:
virtual nsXPCClassInfo* GetClassInfo();
// nsConstraintValidation
PRBool IsTooLong();
PRBool IsValueMissing();
PRBool HasTypeMismatch();
PRBool HasPatternMismatch();
PRBool IsBarredFromConstraintValidation();
nsresult GetValidationMessage(nsAString& aValidationMessage,
ValidationMessageType aType);
protected:
// Pull IsSingleLineTextControl into our scope, otherwise it'd be hidden
// by the nsITextControlElement version.
using nsGenericHTMLFormElement::IsSingleLineTextControl;
/**
* The ValueModeType specifies how the value IDL attribute should behave.
*
* See: http://dev.w3.org/html5/spec/forms.html#dom-input-value
*/
enum ValueModeType
{
// On getting, returns the value.
// On setting, sets value.
VALUE_MODE_VALUE,
// On getting, returns the value if present or the empty string.
// On setting, sets the value.
VALUE_MODE_DEFAULT,
// On getting, returns the value if present or "on".
// On setting, sets the value.
VALUE_MODE_DEFAULT_ON,
// On getting, returns "C:\fakepath\" followed by the file name of the
// first file of the selected files if any.
// On setting the empty string, empties the selected files list, otherwise
// throw the INVALID_STATE_ERR exception.
VALUE_MODE_FILENAME
};
/**
* This helper method returns true if aValue is a valid email address.
* This is following the HTML5 specification:
* http://dev.w3.org/html5/spec/forms.html#valid-e-mail-address
*
* @param aValue the email address to check.
* @result whether the given string is a valid email address.
*/
static PRBool IsValidEmailAddress(const nsAString& aValue);
/**
* This helper method returns true if aValue is a valid email address list.
* Email address list is a list of email address separated by comas (,) which
* can be surrounded by space charecters.
* This is following the HTML5 specification:
* http://dev.w3.org/html5/spec/forms.html#valid-e-mail-address-list
*
* @param aValue the email address list to check.
* @result whether the given string is a valid email address list.
*/
static PRBool IsValidEmailAddressList(const nsAString& aValue);
/**
* This helper method returns true if the aPattern pattern matches aValue.
* aPattern should not contain leading and trailing slashes (/).
* The pattern has to match the entire value not just a subset.
* aDocument must be a valid pointer (not null).
*
* This is following the HTML5 specification:
* http://dev.w3.org/html5/spec/forms.html#attr-input-pattern
*
* @param aValue the string to check.
* @param aPattern the string defining the pattern.
* @param aDocument the owner document of the element.
* @result whether the given string is matches the pattern.
*/
static PRBool IsPatternMatching(nsAString& aValue, nsAString& aPattern,
nsIDocument* aDocument);
// Helper method
nsresult SetValueInternal(const nsAString& aValue,
PRBool aUserInput,
@ -322,6 +403,35 @@ protected:
*/
PRBool NeedToInitializeEditorForEvent(nsEventChainPreVisitor& aVisitor) const;
/**
* Get the value mode of the element, depending of the type.
*/
ValueModeType GetValueMode() const;
/**
* Get the mutable state of the element.
* When the element isn't mutable (immutable), the value or checkedness
* should not be changed by the user.
*
* See: http://dev.w3.org/html5/spec/forms.html#concept-input-mutable
*/
PRBool IsMutable() const;
/**
* Returns if the readonly attribute applies for the current type.
*/
PRBool DoesReadOnlyApply() const;
/**
* Returns if the required attribute applies for the current type.
*/
PRBool DoesRequiredApply() const;
/**
* Returns if the pattern attribute applies for the current type.
*/
PRBool DoesPatternApply() const;
void FreeData();
nsTextEditorState *GetEditorState() const;

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

@ -77,8 +77,7 @@ public:
// nsIFormControl
NS_IMETHOD_(PRUint32) GetType() const { return NS_FORM_LABEL; }
NS_IMETHOD Reset();
NS_IMETHOD SubmitNamesValues(nsFormSubmission* aFormSubmission,
nsIContent* aSubmitElement);
NS_IMETHOD SubmitNamesValues(nsFormSubmission* aFormSubmission);
NS_IMETHOD Focus();
@ -346,8 +345,7 @@ nsHTMLLabelElement::Reset()
}
NS_IMETHODIMP
nsHTMLLabelElement::SubmitNamesValues(nsFormSubmission* aFormSubmission,
nsIContent* aSubmitElement)
nsHTMLLabelElement::SubmitNamesValues(nsFormSubmission* aFormSubmission)
{
return NS_OK;
}

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

@ -398,7 +398,7 @@ NS_INTERFACE_MAP_END_INHERITING(nsGenericHTMLElement)
NS_IMPL_URI_ATTR(nsHTMLMediaElement, Src, src)
NS_IMPL_BOOL_ATTR(nsHTMLMediaElement, Controls, controls)
NS_IMPL_BOOL_ATTR(nsHTMLMediaElement, Autoplay, autoplay)
NS_IMPL_BOOL_ATTR(nsHTMLMediaElement, Autobuffer, autobuffer)
NS_IMPL_STRING_ATTR(nsHTMLMediaElement, Preload, preload)
/* readonly attribute nsIDOMHTMLMediaElement mozAutoplayEnabled; */
NS_IMETHODIMP nsHTMLMediaElement::GetMozAutoplayEnabled(PRBool *aAutoplayEnabled)
@ -610,6 +610,13 @@ void nsHTMLMediaElement::SelectResource()
if (NS_SUCCEEDED(rv)) {
LOG(PR_LOG_DEBUG, ("%p Trying load from src=%s", this, NS_ConvertUTF16toUTF8(src).get()));
mIsLoadingFromSrcAttribute = PR_TRUE;
if (mPreloadAction == nsHTMLMediaElement::PRELOAD_NONE) {
// preload:none media, suspend the load here before we make any
// network requests.
SuspendLoad(uri);
return;
}
rv = LoadResource(uri);
if (NS_SUCCEEDED(rv))
return;
@ -647,6 +654,13 @@ void nsHTMLMediaElement::LoadFromSourceChildren()
mNetworkState = nsIDOMHTMLMediaElement::NETWORK_LOADING;
if (mPreloadAction == nsHTMLMediaElement::PRELOAD_NONE) {
// preload:none media, suspend the load here before we make any
// network requests.
SuspendLoad(uri);
return;
}
rv = LoadResource(uri);
if (NS_SUCCEEDED(rv))
return;
@ -656,6 +670,111 @@ void nsHTMLMediaElement::LoadFromSourceChildren()
NS_NOTREACHED("Execution should not reach here!");
}
void nsHTMLMediaElement::SuspendLoad(nsIURI* aURI)
{
mLoadIsSuspended = PR_TRUE;
mPreloadURI = aURI;
mNetworkState = nsIDOMHTMLMediaElement::NETWORK_IDLE;
DispatchAsyncProgressEvent(NS_LITERAL_STRING("suspend"));
ChangeDelayLoadStatus(PR_FALSE);
}
void nsHTMLMediaElement::ResumeLoad(PreloadAction aAction)
{
NS_ASSERTION(mLoadIsSuspended, "Can only resume preload if halted for one");
nsCOMPtr<nsIURI> uri = mPreloadURI;
mLoadIsSuspended = PR_FALSE;
mPreloadURI = nsnull;
mPreloadAction = aAction;
ChangeDelayLoadStatus(PR_TRUE);
mNetworkState = nsIDOMHTMLMediaElement::NETWORK_LOADING;
if (mIsLoadingFromSrcAttribute) {
// We were loading from the element's src attribute.
if (NS_FAILED(LoadResource(uri))) {
NoSupportedMediaSourceError();
}
} else {
// We were loading from a child <source> element. Try to resume the
// load of that child, and if that fails, try the next child.
if (NS_FAILED(LoadResource(uri))) {
LoadFromSourceChildren();
}
}
}
static PRBool IsAutoplayEnabled()
{
return nsContentUtils::GetBoolPref("media.autoplay.enabled");
}
void nsHTMLMediaElement::UpdatePreloadAction()
{
PreloadAction nextAction = PRELOAD_UNDEFINED;
// If autoplay is set, we should always preload data, as we'll need it
// to play.
if (IsAutoplayEnabled() && HasAttr(kNameSpaceID_None, nsGkAtoms::autoplay)) {
nextAction = nsHTMLMediaElement::PRELOAD_ENOUGH;
} else {
// Find the appropriate preload action by looking at the attribute.
const nsAttrValue* val = mAttrsAndChildren.GetAttr(nsGkAtoms::preload,
kNameSpaceID_None);
if (!val) {
// Attribute is not set. The default is to load metadata.
nextAction = nsHTMLMediaElement::PRELOAD_METADATA;
} else if (val->Type() == nsAttrValue::eEnum) {
PreloadAttrValue attr = static_cast<PreloadAttrValue>(val->GetEnumValue());
if (attr == nsHTMLMediaElement::PRELOAD_ATTR_EMPTY ||
attr == nsHTMLMediaElement::PRELOAD_ATTR_AUTO)
{
nextAction = nsHTMLMediaElement::PRELOAD_ENOUGH;
} else if (attr == nsHTMLMediaElement::PRELOAD_ATTR_METADATA) {
nextAction = nsHTMLMediaElement::PRELOAD_METADATA;
} else if (attr == nsHTMLMediaElement::PRELOAD_ATTR_NONE) {
nextAction = nsHTMLMediaElement::PRELOAD_NONE;
}
} else {
// There was a value, but it wasn't an enumerated value.
// Use the suggested "missing value default" of "metadata".
nextAction = nsHTMLMediaElement::PRELOAD_METADATA;
}
}
if ((mBegun || mIsRunningSelectResource) && nextAction < mPreloadAction) {
// We've started a load or are already downloading, and the preload was
// changed to a state where we buffer less. We don't support this case,
// so don't change the preload behaviour.
return;
}
PRBool wasPreloadNone = mPreloadAction == PRELOAD_NONE;
mPreloadAction = nextAction;
if (nextAction == nsHTMLMediaElement::PRELOAD_ENOUGH) {
if (mLoadIsSuspended) {
// Our load was previouly suspended due to the media having preload
// value "none". The preload value has changed to preload:auto, so
// resume the load.
ResumeLoad(PRELOAD_ENOUGH);
} else {
// Preload as much of the video as we can, i.e. don't suspend after
// the first frame.
StopSuspendingAfterFirstFrame();
}
} else if (nextAction == nsHTMLMediaElement::PRELOAD_METADATA) {
// Ensure that the video can be suspended after first frame.
mAllowSuspendAfterFirstFrame = PR_TRUE;
if (mLoadIsSuspended) {
// Our load was previouly suspended due to the media having preload
// value "none". The preload value has changed to preload:metadata, so
// resume the load. We'll pause the load again after we've read the
// metadata.
ResumeLoad(PRELOAD_METADATA);
}
}
return;
}
nsresult nsHTMLMediaElement::LoadResource(nsIURI* aURI)
{
NS_ASSERTION(mDelayingLoadEvent,
@ -994,7 +1113,9 @@ nsHTMLMediaElement::nsHTMLMediaElement(already_AddRefed<nsINodeInfo> aNodeInfo,
mAllowSuspendAfterFirstFrame(PR_TRUE),
mHasPlayedOrSeeked(PR_FALSE),
mHasSelfReference(PR_FALSE),
mShuttingDown(PR_FALSE)
mShuttingDown(PR_FALSE),
mPreloadAction(PRELOAD_UNDEFINED),
mLoadIsSuspended(PR_FALSE)
{
#ifdef PR_LOGGING
if (!gMediaElementLog) {
@ -1059,6 +1180,8 @@ NS_IMETHODIMP nsHTMLMediaElement::Play()
if (mNetworkState == nsIDOMHTMLMediaElement::NETWORK_EMPTY) {
nsresult rv = Load();
NS_ENSURE_SUCCESS(rv, rv);
} else if (mLoadIsSuspended) {
ResumeLoad(PRELOAD_ENOUGH);
} else if (mDecoder) {
if (mDecoder->IsEnded()) {
SetCurrentTime(0);
@ -1099,6 +1222,15 @@ PRBool nsHTMLMediaElement::ParseAttribute(PRInt32 aNamespaceID,
const nsAString& aValue,
nsAttrValue& aResult)
{
// Mappings from 'preload' attribute strings to an enumeration.
static const nsAttrValue::EnumTable kPreloadTable[] = {
{ "", nsHTMLMediaElement::PRELOAD_ATTR_EMPTY },
{ "none", nsHTMLMediaElement::PRELOAD_ATTR_NONE },
{ "metadata", nsHTMLMediaElement::PRELOAD_ATTR_METADATA },
{ "auto", nsHTMLMediaElement::PRELOAD_ATTR_AUTO },
{ 0 }
};
if (aNamespaceID == kNameSpaceID_None) {
if (aAttribute == nsGkAtoms::src) {
static const char* kWhitespace = " \n\r\t\b";
@ -1114,6 +1246,9 @@ PRBool nsHTMLMediaElement::ParseAttribute(PRInt32 aNamespaceID,
else if (ParseImageAttribute(aAttribute, aValue, aResult)) {
return PR_TRUE;
}
else if (aAttribute == nsGkAtoms::preload) {
return aResult.ParseEnumValue(aValue, kPreloadTable, PR_FALSE);
}
}
return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
@ -1127,6 +1262,8 @@ nsresult nsHTMLMediaElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
nsresult rv =
nsGenericHTMLElement::SetAttr(aNameSpaceID, aName, aPrefix, aValue,
aNotify);
if (NS_FAILED(rv))
return rv;
if (aNotify && aNameSpaceID == kNameSpaceID_None) {
if (aName == nsGkAtoms::src) {
if (mLoadWaitStatus == WAITING_FOR_SRC_OR_SOURCE) {
@ -1143,8 +1280,9 @@ nsresult nsHTMLMediaElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
}
// This attribute can affect AddRemoveSelfReference
AddRemoveSelfReference();
} else if (aName == nsGkAtoms::autobuffer) {
StopSuspendingAfterFirstFrame();
UpdatePreloadAction();
} else if (aName == nsGkAtoms::preload) {
UpdatePreloadAction();
}
}
@ -1155,23 +1293,21 @@ nsresult nsHTMLMediaElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttr,
PRBool aNotify)
{
nsresult rv = nsGenericHTMLElement::UnsetAttr(aNameSpaceID, aAttr, aNotify);
if (NS_FAILED(rv))
return rv;
if (aNotify && aNameSpaceID == kNameSpaceID_None) {
if (aAttr == nsGkAtoms::autoplay) {
// This attribute can affect AddRemoveSelfReference
AddRemoveSelfReference();
UpdatePreloadAction();
} else if (aAttr == nsGkAtoms::preload) {
UpdatePreloadAction();
}
// We perhaps should stop loading if 'autobuffer' is being removed,
// and we're buffering only because of 'autobuffer', but why bother?
}
return rv;
}
static PRBool IsAutoplayEnabled()
{
return nsContentUtils::GetBoolPref("media.autoplay.enabled");
}
nsresult nsHTMLMediaElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers)
@ -1180,6 +1316,9 @@ nsresult nsHTMLMediaElement::BindToTree(nsIDocument* aDocument, nsIContent* aPar
mIsBindingToTree = PR_TRUE;
mAutoplayEnabled =
IsAutoplayEnabled() && (!aDocument || !aDocument->IsStaticDocument());
// The preload action depends on the value of the autoplay attribute.
// It's value may have changed, so update it.
UpdatePreloadAction();
}
nsresult rv = nsGenericHTMLElement::BindToTree(aDocument,
aParent,
@ -1641,7 +1780,7 @@ void nsHTMLMediaElement::FirstFrameLoaded(PRBool aResourceFullyLoaded)
if (mDecoder && mAllowSuspendAfterFirstFrame && mPaused &&
!aResourceFullyLoaded &&
!HasAttr(kNameSpaceID_None, nsGkAtoms::autoplay) &&
!HasAttr(kNameSpaceID_None, nsGkAtoms::autobuffer)) {
mPreloadAction == nsHTMLMediaElement::PRELOAD_METADATA) {
mSuspendedAfterFirstFrame = PR_TRUE;
mDecoder->Suspend();
}
@ -1944,6 +2083,7 @@ nsresult nsHTMLMediaElement::DoneAddingChildren(PRBool aHaveNotified)
if (!mIsDoneAddingChildren) {
mIsDoneAddingChildren = PR_TRUE;
UpdatePreloadAction();
if (mNetworkState == nsIDOMHTMLMediaElement::NETWORK_EMPTY) {
QueueSelectResourceTask();
}

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

@ -104,8 +104,7 @@ public:
}
NS_IMETHOD Reset();
NS_IMETHOD SubmitNamesValues(nsFormSubmission *aFormSubmission,
nsIContent *aSubmitElement);
NS_IMETHOD SubmitNamesValues(nsFormSubmission *aFormSubmission);
virtual nsresult DoneAddingChildren(PRBool aHaveNotified);
virtual PRBool IsDoneAddingChildren();
@ -321,8 +320,7 @@ nsHTMLObjectElement::Reset()
}
NS_IMETHODIMP
nsHTMLObjectElement::SubmitNamesValues(nsFormSubmission *aFormSubmission,
nsIContent *aSubmitElement)
nsHTMLObjectElement::SubmitNamesValues(nsFormSubmission *aFormSubmission)
{
nsAutoString name;
if (!GetAttr(kNameSpaceID_None, nsGkAtoms::name, name)) {

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

@ -68,8 +68,7 @@ public:
// nsIFormControl
NS_IMETHOD_(PRUint32) GetType() const { return NS_FORM_OUTPUT; }
NS_IMETHOD Reset();
NS_IMETHOD SubmitNamesValues(nsFormSubmission* aFormSubmission,
nsIContent* aSubmitElement);
NS_IMETHOD SubmitNamesValues(nsFormSubmission* aFormSubmission);
nsresult Clone(nsINodeInfo* aNodeInfo, nsINode** aResult) const;
@ -148,8 +147,7 @@ nsHTMLOutputElement::Reset()
}
NS_IMETHODIMP
nsHTMLOutputElement::SubmitNamesValues(nsFormSubmission* aFormSubmission,
nsIContent* aSubmitElement)
nsHTMLOutputElement::SubmitNamesValues(nsFormSubmission* aFormSubmission)
{
// The output element is not submittable.
return NS_OK;

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

@ -194,6 +194,9 @@ NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLSelectElement)
NS_IMPL_ELEMENT_CLONE(nsHTMLSelectElement)
// nsConstraintValidation
NS_IMPL_NSCONSTRAINTVALIDATION(nsHTMLSelectElement)
NS_IMETHODIMP
nsHTMLSelectElement::GetForm(nsIDOMHTMLFormElement** aForm)
{
@ -1449,6 +1452,12 @@ nsHTMLSelectElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
return nsGenericHTMLFormElement::PreHandleEvent(aVisitor);
}
PRInt32
nsHTMLSelectElement::IntrinsicState() const
{
return NS_EVENT_STATE_OPTIONAL | nsGenericHTMLFormElement::IntrinsicState();
}
// nsIFormControl
NS_IMETHODIMP
@ -1596,8 +1605,7 @@ nsHTMLSelectElement::Reset()
static NS_DEFINE_CID(kFormProcessorCID, NS_FORMPROCESSOR_CID);
NS_IMETHODIMP
nsHTMLSelectElement::SubmitNamesValues(nsFormSubmission* aFormSubmission,
nsIContent* aSubmitElement)
nsHTMLSelectElement::SubmitNamesValues(nsFormSubmission* aFormSubmission)
{
nsresult rv = NS_OK;
@ -1747,7 +1755,6 @@ nsHTMLSelectElement::VerifyOptionsArray()
VerifyOptionsRecurse(this, aIndex, mOptions);
}
#endif
//----------------------------------------------------------------------

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

@ -52,6 +52,7 @@
#include "nsISelectControlFrame.h"
#include "nsContentUtils.h"
#include "nsIHTMLCollection.h"
#include "nsConstraintValidation.h"
// PresState
#include "nsXPCOM.h"
@ -236,7 +237,8 @@ private:
*/
class nsHTMLSelectElement : public nsGenericHTMLFormElement,
public nsIDOMHTMLSelectElement,
public nsISelectElement
public nsISelectElement,
public nsConstraintValidation
{
public:
nsHTMLSelectElement(already_AddRefed<nsINodeInfo> aNodeInfo,
@ -269,11 +271,12 @@ public:
// Overriden nsIFormControl methods
NS_IMETHOD_(PRUint32) GetType() const { return NS_FORM_SELECT; }
NS_IMETHOD Reset();
NS_IMETHOD SubmitNamesValues(nsFormSubmission* aFormSubmission,
nsIContent* aSubmitElement);
NS_IMETHOD SubmitNamesValues(nsFormSubmission* aFormSubmission);
NS_IMETHOD SaveState();
virtual PRBool RestoreState(nsPresState* aState);
PRInt32 IntrinsicState() const;
// nsISelectElement
NS_DECL_NSISELECTELEMENT

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

@ -159,7 +159,6 @@ NS_IMPL_RELEASE_INHERITED(nsHTMLSharedElement, nsGenericElement)
DOMCI_DATA(HTMLParamElement, nsHTMLSharedElement)
DOMCI_DATA(HTMLIsIndexElement, nsHTMLSharedElement)
DOMCI_DATA(HTMLBaseElement, nsHTMLSharedElement)
DOMCI_DATA(HTMLSpacerElement, nsHTMLSharedElement)
DOMCI_DATA(HTMLDirectoryElement, nsHTMLSharedElement)
DOMCI_DATA(HTMLMenuElement, nsHTMLSharedElement)
DOMCI_DATA(HTMLQuoteElement, nsHTMLSharedElement)
@ -178,9 +177,6 @@ nsHTMLSharedElement::GetClassInfoInternal()
if (mNodeInfo->Equals(nsGkAtoms::base)) {
return NS_GetDOMClassInfoInstance(eDOMClassInfo_HTMLBaseElement_id);
}
if (mNodeInfo->Equals(nsGkAtoms::spacer)) {
return NS_GetDOMClassInfoInstance(eDOMClassInfo_HTMLSpacerElement_id);
}
if (mNodeInfo->Equals(nsGkAtoms::dir)) {
return NS_GetDOMClassInfoInstance(eDOMClassInfo_HTMLDirectoryElement_id);
}
@ -278,27 +274,14 @@ nsHTMLSharedElement::ParseAttribute(PRInt32 aNamespaceID,
const nsAString& aValue,
nsAttrValue& aResult)
{
if (aNamespaceID == kNameSpaceID_None) {
if (mNodeInfo->Equals(nsGkAtoms::spacer)) {
if (aAttribute == nsGkAtoms::size) {
return aResult.ParseIntWithBounds(aValue, 0);
}
if (aAttribute == nsGkAtoms::align) {
return ParseAlignValue(aValue, aResult);
}
if (aAttribute == nsGkAtoms::width ||
aAttribute == nsGkAtoms::height) {
return aResult.ParseSpecialIntValue(aValue, PR_TRUE);
}
if (aNamespaceID == kNameSpaceID_None &&
(mNodeInfo->Equals(nsGkAtoms::dir) ||
mNodeInfo->Equals(nsGkAtoms::menu))) {
if (aAttribute == nsGkAtoms::type) {
return aResult.ParseEnumValue(aValue, kListTypeTable, PR_FALSE);
}
else if (mNodeInfo->Equals(nsGkAtoms::dir) ||
mNodeInfo->Equals(nsGkAtoms::menu)) {
if (aAttribute == nsGkAtoms::type) {
return aResult.ParseEnumValue(aValue, kListTypeTable, PR_FALSE);
}
if (aAttribute == nsGkAtoms::start) {
return aResult.ParseIntWithBounds(aValue, 1);
}
if (aAttribute == nsGkAtoms::start) {
return aResult.ParseIntWithBounds(aValue, 1);
}
}
@ -306,98 +289,6 @@ nsHTMLSharedElement::ParseAttribute(PRInt32 aNamespaceID,
aResult);
}
// spacer element code
static void
SpacerMapAttributesIntoRule(const nsMappedAttributes* aAttributes,
nsRuleData* aData)
{
nsGenericHTMLElement::MapImageMarginAttributeInto(aAttributes, aData);
nsGenericHTMLElement::MapImageSizeAttributesInto(aAttributes, aData);
if (aData->mSIDs & (NS_STYLE_INHERIT_BIT(Position) |
NS_STYLE_INHERIT_BIT(Display))) {
PRBool typeIsBlock = PR_FALSE;
const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::type);
if (value && value->Type() == nsAttrValue::eString) {
const nsString& tmp(value->GetStringValue());
if (tmp.LowerCaseEqualsLiteral("line") ||
tmp.LowerCaseEqualsLiteral("vert") ||
tmp.LowerCaseEqualsLiteral("vertical") ||
tmp.LowerCaseEqualsLiteral("block")) {
// This is not strictly 100% compatible: if the spacer is given
// a width of zero then it is basically ignored.
typeIsBlock = PR_TRUE;
}
}
if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Position)) {
if (typeIsBlock) {
// width: value
if (aData->mPositionData->mWidth.GetUnit() == eCSSUnit_Null) {
const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::width);
if (value && value->Type() == nsAttrValue::eInteger) {
aData->mPositionData->
mWidth.SetFloatValue((float)value->GetIntegerValue(),
eCSSUnit_Pixel);
} else if (value && value->Type() == nsAttrValue::ePercent) {
aData->mPositionData->
mWidth.SetPercentValue(value->GetPercentValue());
}
}
// height: value
if (aData->mPositionData->mHeight.GetUnit() == eCSSUnit_Null) {
const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::height);
if (value && value->Type() == nsAttrValue::eInteger) {
aData->mPositionData->
mHeight.SetFloatValue((float)value->GetIntegerValue(),
eCSSUnit_Pixel);
} else if (value && value->Type() == nsAttrValue::ePercent) {
aData->mPositionData->
mHeight.SetPercentValue(value->GetPercentValue());
}
}
} else {
// size: value
if (aData->mPositionData->mWidth.GetUnit() == eCSSUnit_Null) {
const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::size);
if (value && value->Type() == nsAttrValue::eInteger)
aData->mPositionData->
mWidth.SetFloatValue((float)value->GetIntegerValue(),
eCSSUnit_Pixel);
}
}
}
if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Display)) {
const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::align);
if (value && value->Type() == nsAttrValue::eEnum) {
PRInt32 align = value->GetEnumValue();
if (aData->mDisplayData->mFloat.GetUnit() == eCSSUnit_Null) {
if (align == NS_STYLE_TEXT_ALIGN_LEFT)
aData->mDisplayData->mFloat.SetIntValue(NS_STYLE_FLOAT_LEFT,
eCSSUnit_Enumerated);
else if (align == NS_STYLE_TEXT_ALIGN_RIGHT)
aData->mDisplayData->mFloat.SetIntValue(NS_STYLE_FLOAT_RIGHT,
eCSSUnit_Enumerated);
}
}
if (typeIsBlock) {
if (aData->mDisplayData->mDisplay.GetUnit() == eCSSUnit_Null) {
aData->mDisplayData->mDisplay.SetIntValue(NS_STYLE_DISPLAY_BLOCK,
eCSSUnit_Enumerated);
}
}
}
// Any new structs that don't need typeIsBlock should go outside
// the code that calculates it.
}
nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
}
static void
DirectoryMenuMapAttributesIntoRule(const nsMappedAttributes* aAttributes,
nsRuleData* aData)
@ -422,25 +313,6 @@ DirectoryMenuMapAttributesIntoRule(const nsMappedAttributes* aAttributes,
NS_IMETHODIMP_(PRBool)
nsHTMLSharedElement::IsAttributeMapped(const nsIAtom* aAttribute) const
{
if (mNodeInfo->Equals(nsGkAtoms::spacer)) {
static const MappedAttributeEntry attributes[] = {
// XXXldb This is just wrong.
{ &nsGkAtoms::usemap },
{ &nsGkAtoms::ismap },
{ &nsGkAtoms::align },
{ nsnull }
};
static const MappedAttributeEntry* const map[] = {
attributes,
sCommonAttributeMap,
sImageMarginSizeAttributeMap,
sImageBorderAttributeMap,
};
return FindAttributeDependence(aAttribute, map, NS_ARRAY_LENGTH(map));
}
if (mNodeInfo->Equals(nsGkAtoms::dir)) {
static const MappedAttributeEntry attributes[] = {
{ &nsGkAtoms::type },
@ -598,11 +470,7 @@ nsHTMLSharedElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
nsMapRuleToAttributesFunc
nsHTMLSharedElement::GetAttributeMappingFunction() const
{
if (mNodeInfo->Equals(nsGkAtoms::spacer)) {
return &SpacerMapAttributesIntoRule;
}
else if (mNodeInfo->Equals(nsGkAtoms::dir) ||
mNodeInfo->Equals(nsGkAtoms::menu)) {
if (mNodeInfo->Equals(nsGkAtoms::dir) || mNodeInfo->Equals(nsGkAtoms::menu)) {
return &DirectoryMenuMapAttributesIntoRule;
}

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

@ -1061,23 +1061,22 @@ MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
if (aData->mSIDs & NS_STYLE_INHERIT_BIT(TableBorder)) {
const nsStyleDisplay* readDisplay = aData->mStyleContext->GetStyleDisplay();
if (readDisplay->mDisplay != NS_STYLE_DISPLAY_TABLE_CELL) {
// cellspacing
// cellspacing
const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::cellspacing);
if (value && value->Type() == nsAttrValue::eInteger) {
if (aData->mTableData->mBorderSpacing.mXValue.GetUnit() == eCSSUnit_Null)
aData->mTableData->mBorderSpacing.mXValue.SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel);
if (aData->mTableData->mBorderSpacing.mYValue.GetUnit() == eCSSUnit_Null)
aData->mTableData->mBorderSpacing.mYValue.SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel);
if (aData->mTableData->mBorderSpacing.GetUnit() == eCSSUnit_Null)
aData->mTableData->mBorderSpacing.
SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel);
}
else if (value && value->Type() == nsAttrValue::ePercent && eCompatibility_NavQuirks == mode) {
else if (value && value->Type() == nsAttrValue::ePercent &&
eCompatibility_NavQuirks == mode) {
// in quirks mode, treat a % cellspacing value a pixel value.
if (aData->mTableData->mBorderSpacing.mXValue.GetUnit() == eCSSUnit_Null)
aData->mTableData->mBorderSpacing.mXValue.SetFloatValue(100.0f * value->GetPercentValue(), eCSSUnit_Pixel);
if (aData->mTableData->mBorderSpacing.mYValue.GetUnit() == eCSSUnit_Null)
aData->mTableData->mBorderSpacing.mYValue.SetFloatValue(100.0f * value->GetPercentValue(), eCSSUnit_Pixel);
if (aData->mTableData->mBorderSpacing.GetUnit() == eCSSUnit_Null)
aData->mTableData->mBorderSpacing.
SetFloatValue(100.0f * value->GetPercentValue(), eCSSUnit_Pixel);
}
}
}
}
if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Table)) {
const nsStyleDisplay* readDisplay = aData->mStyleContext->GetStyleDisplay();
if (readDisplay->mDisplay != NS_STYLE_DISPLAY_TABLE_CELL) {

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

@ -77,6 +77,7 @@
#include "mozAutoDocUpdate.h"
#include "nsISupportsPrimitives.h"
#include "nsContentCreatorFunctions.h"
#include "nsConstraintValidation.h"
#include "nsTextEditorState.h"
@ -89,7 +90,8 @@ class nsHTMLTextAreaElement : public nsGenericHTMLFormElement,
public nsIDOMNSHTMLTextAreaElement,
public nsITextControlElement,
public nsIDOMNSEditableElement,
public nsStubMutationObserver
public nsStubMutationObserver,
public nsConstraintValidation
{
public:
nsHTMLTextAreaElement(already_AddRefed<nsINodeInfo> aNodeInfo,
@ -123,11 +125,12 @@ public:
// nsIFormControl
NS_IMETHOD_(PRUint32) GetType() const { return NS_FORM_TEXTAREA; }
NS_IMETHOD Reset();
NS_IMETHOD SubmitNamesValues(nsFormSubmission* aFormSubmission,
nsIContent* aSubmitElement);
NS_IMETHOD SubmitNamesValues(nsFormSubmission* aFormSubmission);
NS_IMETHOD SaveState();
virtual PRBool RestoreState(nsPresState* aState);
virtual PRInt32 IntrinsicState() const;
// nsITextControlElemet
NS_IMETHOD SetValueChanged(PRBool aValueChanged);
NS_IMETHOD_(PRBool) IsSingleLineTextControl() const;
@ -196,6 +199,14 @@ public:
nsGenericHTMLFormElement)
virtual nsXPCClassInfo* GetClassInfo();
// nsConstraintValidation
PRBool IsTooLong();
PRBool IsValueMissing();
PRBool IsBarredFromConstraintValidation();
nsresult GetValidationMessage(nsAString& aValidationMessage,
ValidationMessageType aType);
protected:
using nsGenericHTMLFormElement::IsSingleLineTextControl; // get rid of the compiler warning
@ -242,6 +253,11 @@ protected:
virtual nsresult AfterSetAttr(PRInt32 aNamespaceID, nsIAtom *aName,
const nsAString* aValue, PRBool aNotify);
/**
* Get the mutable state of the element.
*/
PRBool IsMutable() const;
};
@ -297,6 +313,9 @@ NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLTextAreaElement)
NS_IMPL_ELEMENT_CLONE(nsHTMLTextAreaElement)
// nsConstraintValidation
NS_IMPL_NSCONSTRAINTVALIDATION(nsHTMLTextAreaElement)
NS_IMETHODIMP
nsHTMLTextAreaElement::GetForm(nsIDOMHTMLFormElement** aForm)
@ -397,6 +416,7 @@ NS_IMPL_BOOL_ATTR(nsHTMLTextAreaElement, Disabled, disabled)
NS_IMPL_NON_NEGATIVE_INT_ATTR(nsHTMLTextAreaElement, MaxLength, maxlength)
NS_IMPL_STRING_ATTR(nsHTMLTextAreaElement, Name, name)
NS_IMPL_BOOL_ATTR(nsHTMLTextAreaElement, ReadOnly, readonly)
NS_IMPL_BOOL_ATTR(nsHTMLTextAreaElement, Required, required)
NS_IMPL_INT_ATTR(nsHTMLTextAreaElement, Rows, rows)
NS_IMPL_INT_ATTR_DEFAULT_VALUE(nsHTMLTextAreaElement, TabIndex, tabindex, 0)
NS_IMPL_STRING_ATTR(nsHTMLTextAreaElement, Wrap, wrap)
@ -837,8 +857,7 @@ nsHTMLTextAreaElement::Reset()
}
NS_IMETHODIMP
nsHTMLTextAreaElement::SubmitNamesValues(nsFormSubmission* aFormSubmission,
nsIContent* aSubmitElement)
nsHTMLTextAreaElement::SubmitNamesValues(nsFormSubmission* aFormSubmission)
{
nsresult rv = NS_OK;
@ -935,7 +954,19 @@ nsHTMLTextAreaElement::RestoreState(nsPresState* aState)
return PR_FALSE;
}
PRInt32
nsHTMLTextAreaElement::IntrinsicState() const
{
PRInt32 state = nsGenericHTMLFormElement::IntrinsicState();
if (HasAttr(kNameSpaceID_None, nsGkAtoms::required)) {
state |= NS_EVENT_STATE_REQUIRED;
} else {
state |= NS_EVENT_STATE_OPTIONAL;
}
return state;
}
nsresult
nsHTMLTextAreaElement::BeforeSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
@ -1032,6 +1063,96 @@ nsHTMLTextAreaElement::CopyInnerTo(nsGenericElement* aDest) const
return NS_OK;
}
PRBool
nsHTMLTextAreaElement::IsMutable() const
{
return (!HasAttr(kNameSpaceID_None, nsGkAtoms::readonly) &&
!HasAttr(kNameSpaceID_None, nsGkAtoms::disabled));
}
// nsConstraintValidation
PRBool
nsHTMLTextAreaElement::IsTooLong()
{
if (!mValueChanged) {
return PR_FALSE;
}
PRInt32 maxLength = -1;
PRInt32 textLength = -1;
GetMaxLength(&maxLength);
GetTextLength(&textLength);
return (maxLength >= 0) && (textLength > maxLength);
}
PRBool
nsHTMLTextAreaElement::IsValueMissing()
{
if (!HasAttr(kNameSpaceID_None, nsGkAtoms::required) || !IsMutable()) {
return PR_FALSE;
}
nsAutoString value;
nsresult rv = GetValue(value);
NS_ENSURE_SUCCESS(rv, PR_FALSE);
return value.IsEmpty();
}
PRBool
nsHTMLTextAreaElement::IsBarredFromConstraintValidation()
{
return HasAttr(kNameSpaceID_None, nsGkAtoms::readonly);
}
nsresult
nsHTMLTextAreaElement::GetValidationMessage(nsAString& aValidationMessage,
ValidationMessageType aType)
{
nsresult rv = NS_OK;
switch (aType)
{
case VALIDATION_MESSAGE_TOO_LONG:
{
nsXPIDLString message;
PRInt32 maxLength = -1;
PRInt32 textLength = -1;
nsAutoString strMaxLength;
nsAutoString strTextLength;
GetMaxLength(&maxLength);
GetTextLength(&textLength);
strMaxLength.AppendInt(maxLength);
strTextLength.AppendInt(textLength);
const PRUnichar* params[] = { strTextLength.get(), strMaxLength.get() };
rv = nsContentUtils::FormatLocalizedString(nsContentUtils::eDOM_PROPERTIES,
"ElementSuffersFromBeingTooLong",
params, 2, message);
aValidationMessage = message;
}
break;
case VALIDATION_MESSAGE_VALUE_MISSING:
{
nsXPIDLString message;
rv = nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES,
"TextElementSuffersFromBeingMissing",
message);
aValidationMessage = message;
}
break;
default:
rv = nsConstraintValidation::GetValidationMessage(aValidationMessage, aType);
}
return rv;
}
NS_IMETHODIMP_(PRBool)
nsHTMLTextAreaElement::IsSingleLineTextControl() const
{

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

@ -191,6 +191,17 @@ _TEST_FILES = \
test_bug573969.html \
test_bug549475.html \
test_bug585508.html \
test_bug345624-1.html \
test_bug345624-2.html \
test_bug561640.html \
test_bug345822.html \
test_bug555559.html \
test_bug344615.html \
test_bug345512.html \
test_bug566064.html \
test_bug566160.html \
test_bug582412-1.html \
test_bug582412-2.html \
$(NULL)
libs:: $(_TEST_FILES)

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

@ -0,0 +1,90 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=344615
-->
<head>
<title>Test for Bug 344615</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=344615">Mozilla Bug 344615</a>
<p id="display"></p>
<div id="content" style="display: none">
<input type='url' id='i' oninvalid='invalidEventHandler(event);'>
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 344615 **/
// More checks are done in test_bug551670.html.
var gInvalid = false;
function invalidEventHandler(e)
{
is(e.type, "invalid", "Invalid event type should be invalid");
gInvalid = true;
}
function checkValidURL(element)
{
gInvalid = false;
ok(!element.validity.typeMismatch,
"Element should not suffer from type mismatch");
ok(element.validity.valid, "Element should be valid");
ok(element.checkValidity(), "Element should be valid");
ok(!gInvalid, "The invalid event should not have been thrown");
is(element.validationMessage, '',
"Validation message should be the empty string");
}
function checkInvalidURL(element)
{
gInvalid = false;
ok(element.validity.typeMismatch,
"Element should suffer from type mismatch");
ok(!element.validity.valid, "Element should not be valid");
ok(!element.checkValidity(), "Element should not be valid");
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");
}
var url = document.getElementById('i');
is(url.type, 'url', "url state should be recognized");
// The empty string should not be considered as invalid.
url.value = '';
checkValidURL(url);
// We are only testing obviously (in)valid URI's because the function used
// to check if an URI is valid is not specific to this functionality.
url.value = 'foo';
checkInvalidURL(url);
url.value = 'http://mozilla.com/';
checkValidURL(url);
url.value = 'http://mozil\nla\r.com/';
checkValidURL(url);
url.value = ' http://mozilla.com/ ';
checkValidURL(url);
url.value = '\r http://mozilla.com/ \n';
checkValidURL(url);
url.value = 'file:///usr/bin/tulip';
checkValidURL(url);
url.value = '../../bar.html';
checkInvalidURL(url);
</script>
</pre>
</body>
</html>

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

@ -0,0 +1,300 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=345512
-->
<head>
<title>Test for Bug 345512</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=345512">Mozilla Bug 345512</a>
<p id="display"></p>
<div id="content" style="display: none">
<input id='i' pattern="tulip" oninvalid="invalidEventHandler(event);">
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 345512 **/
var gInvalid = false;
function invalidEventHandler(e)
{
is(e.type, "invalid", "Invalid event type should be invalid");
gInvalid = true;
}
function checkPatternAttribute(element)
{
ok('pattern' in element, "Element should have the pattern attribute");
is(element.pattern, "tulip",
"pattern IDL attribute value should be 'tulip'");
is(element.getAttribute('pattern'), "tulip",
"pattern content attribute value should be 'tulip'");
element.pattern = "foo";
is(element.pattern, "foo",
"pattern IDL attribute value should be 'foo'");
is(element.getAttribute('pattern'), "foo",
"pattern content attribute value should be 'foo'");
element.removeAttribute('pattern');
ok(!element.pattern,
"Element pattern attribute shouldn't be specified");
is(element.getAttribute('pattern'), null,
"Element pattern attribute shouldn't be specified");
element.setAttribute("pattern", "bar");
is(element.pattern, "bar",
"pattern IDL attribute value should be 'bar'");
is(element.getAttribute('pattern'), "bar",
"pattern content attribute value should be 'bar'");
}
function completeValidityCheck(element, alwaysValid)
{
if (element.type == 'file') {
// Need privileges to set a filename with .value.
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
}
// Check when pattern matches.
if (element.type == 'email') {
element.pattern = ".*@bar.com";
element.value = "foo@bar.com";
} else if (element.type == 'url') {
element.pattern = "http://.*\\.com$";
element.value = "http://mozilla.com";
} else {
element.pattern = "foo";
element.value = "foo";
}
checkValidPattern(element, true);
// Check when pattern does not match.
if (element.type == 'email') {
element.pattern = ".*@bar.com";
element.value = "foo@foo.com";
} else if (element.type == 'url') {
element.pattern = "http://.*\\.com$";
element.value = "http://mozilla.org";
} else {
element.pattern = "foo";
element.value = "bar";
}
if (!alwaysValid) {
checkInvalidPattern(element, true);
} else {
checkValidPattern(element, true);
}
}
function checkValidPattern(element, completeCheck)
{
if (completeCheck) {
gInvalid = false;
ok(!element.validity.patternMismatch,
"Element should not suffer from pattern mismatch");
ok(element.validity.valid, "Element should be valid");
ok(element.checkValidity(), "Element should be valid");
ok(!gInvalid, "Invalid event shouldn't have been thrown");
is(element.validationMessage, '',
"Validation message should be the empty string");
} else {
ok(!element.validity.patternMismatch,
"Element should not suffer from pattern mismatch");
}
}
function checkInvalidPattern(element, completeCheck)
{
if (completeCheck) {
gInvalid = false;
ok(element.validity.patternMismatch,
"Element should suffer from pattern mismatch");
ok(!element.validity.valid, "Element should not be valid");
ok(!element.checkValidity(), "Element should not be valid");
ok(gInvalid, "Invalid event should have been thrown");
is(element.validationMessage,
"The field value is not in the requested format.",
"Validation message is not valid");
} else {
ok(element.validity.patternMismatch,
"Element should suffer from pattern mismatch");
}
}
function checkPatternValidity(element)
{
element.pattern = "foo";
element.value = '';
checkValidPattern(element);
element.value = "foo";
checkValidPattern(element);
element.value = "bar";
checkInvalidPattern(element);
element.value = "foobar";
checkInvalidPattern(element);
element.value = "foofoo";
checkInvalidPattern(element);
element.pattern = "foo\"bar";
element.value = "foo\"bar";
checkValidPattern(element);
element.value = 'foo"bar';
checkValidPattern(element);
element.pattern = "foo'bar";
element.value = "foo\'bar";
checkValidPattern(element);
element.pattern = "foo\\(bar";
element.value = "foo(bar";
checkValidPattern(element);
element.value = "foo";
checkInvalidPattern(element);
element.pattern = "foo\\)bar";
element.value = "foo)bar";
checkValidPattern(element);
element.value = "foo";
checkInvalidPattern(element);
// We need '\\\\' because '\\' will produce '\\' and we want to escape the '\'
// for the regexp.
element.pattern = "foo\\\\bar";
element.value = "foo\\bar";
checkValidPattern(element);
// The same way, we want to escape the ' in the pattern.
element.pattern = "foo\\'bar";
element.value = "foo'bar";
checkValidPattern(element);
// Check for 'i' flag disabled. Should be case sensitive.
element.value = "Foo";
checkInvalidPattern(element);
// We can't check for the 'g' flag because we only test, we don't execute.
// We can't check for the 'm' flag because .value shouldn't contain line breaks.
// We should check the pattern attribute do not pollute |RegExp.lastParen|.
is(RegExp.lastParen, "", "RegExp.lastParen should be the empty string");
element.pattern = "(foo)";
element.value = "foo";
checkValidPattern(element);
is(RegExp.lastParen, "", "RegExp.lastParen should be the empty string");
// That may sound weird but the empty string is a valid pattern value.
element.pattern = "";
element.value = "";
checkValidPattern(element);
element.value = "foo";
checkInvalidPattern(element);
// Checking some complex patterns. As we are using js regexp mechanism, these
// tests doesn't aim to test the regexp mechanism.
element.pattern = "\\d{2}\\s\\d{2}\\s\\d{4}"
element.value = "01 01 2010"
checkValidPattern(element);
element.value = "01/01/2010"
checkInvalidPattern(element);
element.pattern = "[0-9a-zA-Z]([-.\\w]*[0-9a-zA-Z_+])*@([0-9a-zA-Z][-\\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,9}";
element.value = "foo@bar.com";
checkValidPattern(element);
element.value = "...@bar.com";
checkInvalidPattern(element);
element.pattern = "^(?:\\w{3,})$";
element.value = "foo";
checkValidPattern(element);
element.value = "f";
checkInvalidPattern(element);
// If @title is specified, it should be added in the validation message.
if (element.type == 'email') {
element.pattern = "foo@bar.com"
element.value = "bar@foo.com";
} else if (element.type == 'url') {
element.pattern = "http://mozilla.com";
element.value = "http://mozilla.org";
} else {
element.pattern = "foo";
element.value = "bar";
}
element.title = "This is an explanation of the regexp.";
is(element.validationMessage,
"The field value is not in the requested format. " + element.title,
"Validation message is not valid");
element.title = "";
is(element.validationMessage,
"The field value is not in the requested format.",
"Validation message is not valid");
element.pattern = "foo";
if (element.type == 'email') {
element.value = "bar@foo.com";
} else if (element.type == 'url') {
element.value = "http://mozilla.org";
} else {
element.value = "bar";
}
checkInvalidPattern(element);
element.removeAttribute('pattern');
checkValidPattern(element, true);
}
var input = document.getElementById('i');
// All input types should have the pattern attribute.
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');
// TODO: 'datetime', 'date', 'month', 'week', 'time', 'datetime-local',
// 'number', 'range', ande 'color' do not accept the @pattern too but are
// not implemented yet.
for each (type in validTypes) {
input.type = type;
completeValidityCheck(input, false);
checkPatternValidity(input);
}
for each (type in invalidTypes) {
input.type = type;
completeValidityCheck(input, true);
}
</script>
</pre>
</body>
</html>

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

@ -0,0 +1,242 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=345624
-->
<head>
<title>Test for Bug 345624</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=345624">Mozilla Bug 345624</a>
<p id="display"></p>
<div id="content" style="display: none">
<fieldset id='f'></fieldset>
<input id='i' oninvalid="invalidEventHandler(event);">
<button id='b' oninvalid="invalidEventHandler(event);"></button>
<select id='s' oninvalid="invalidEventHandler(event);"></select>
<textarea id='t' oninvalid="invalidEventHandler(event);"></textarea>
<keygen id='k'></keygen>
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 345624 **/
var gInvalid = false;
function invalidEventHandler(aEvent)
{
function checkInvalidEvent(aEvent)
{
is(aEvent.type, "invalid", "Invalid event type should be invalid");
ok(!aEvent.bubbles, "Invalid event should not bubble");
ok(aEvent.cancelable, "Invalid event should be cancelable");
}
checkInvalidEvent(aEvent);
gInvalid = true;
}
function checkConstraintValidationAPIExist(element)
{
ok('willValidate' in element, "willValidate is not available in the DOM");
ok('validationMessage' in element, "validationMessage is not available in the DOM");
ok('validity' in element, "validity is not available in the DOM");
if ('validity' in element) {
validity = element.validity;
ok('valueMissing' in validity, "validity.valueMissing is not available in the DOM");
ok('typeMismatch' in validity, "validity.typeMismatch is not available in the DOM");
ok('patternMismatch' in validity, "validity.patternMismatch is not available in the DOM");
ok('tooLong' in validity, "validity.tooLong is not available in the DOM");
ok('rangeUnderflow' in validity, "validity.rangeUnderflow is not available in the DOM");
ok('rangeOverflow' in validity, "validity.rangeOverflow is not available in the DOM");
ok('stepMismatch' in validity, "validity.stepMismatch is not available in the DOM");
ok('customError' in validity, "validity.customError is not available in the DOM");
ok('valid' in validity, "validity.valid is not available in the DOM");
}
}
function checkConstraintValidationAPIDefaultValues(element)
{
// Not checking willValidate because the default value depends of the element
is(element.validationMessage, "", "validationMessage default value should be empty string");
ok(!element.validity.valueMissing, "The element should not suffer from a constraint validation");
ok(!element.validity.typeMismatch, "The element should not suffer from a constraint validation");
ok(!element.validity.patternMismatch, "The element should not suffer from a constraint validation");
ok(!element.validity.tooLong, "The element should not suffer from a constraint validation");
ok(!element.validity.rangeUnderflow, "The element should not suffer from a constraint validation");
ok(!element.validity.rangeOverflow, "The element should not suffer from a constraint validation");
ok(!element.validity.stepMismatch, "The element should not suffer from a constraint validation");
ok(!element.validity.customError, "The element should not suffer from a constraint validation");
ok(element.validity.valid, "The element should be valid by default");
ok(element.checkValidity(), "The element should be valid by default");
}
function checkSpecificWillValidate()
{
// fieldset, keygen (TODO) and select elements
ok(!document.getElementById('f').willValidate, "Fielset 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");
// input element
i = document.getElementById('i');
i.type = "hidden";
ok(!i.willValidate, "Hidden state input should be barred from constraint validation");
i.type = "reset";
ok(!i.willValidate, "Reset button state input should be barred from constraint validation");
i.type = "button";
ok(!i.willValidate, "Button state input should be barred from constraint validation");
i.type = "";
i.readOnly = 'true';
ok(!i.willValidate, "Readonly input should be barred from constraint validation");
i.removeAttribute('readOnly');
ok(i.willValidate, "Default input element should not be barred from constraint validation");
// button element
b = document.getElementById('b');
b.type = "reset";
ok(!b.willValidate, "Reset state button should be barred from constraint validation");
b.type = "button";
ok(!b.willValidate, "Button state button should be barred from constraint validation");
b.type = "";
ok(b.willValidate, "Default button element should not be barred from constraint validation");
// textarea element
t = document.getElementById('t');
t.readOnly = true;
ok(!t.willValidate, "Readonly textarea should be barred from constraint validation");
t.removeAttribute('readOnly');
ok(t.willValidate, "Default textarea element should not be barred from constraint validation");
// TODO: output elements are always barred from constraint validation.
// TODO: PROGRESS
// TODO: METER
}
function checkCommonWillValidate(element)
{
// Not checking the default value because it has been check previously
element.disabled = true;
ok(!element.willValidate, "Disabled element should be barred from constraint validation");
element.removeAttribute('disabled');
// TODO: If an element has a datalist element ancestor, it is barred from constraint validation.
}
function checkCustomError(element)
{
element.setCustomValidity("message");
is(element.validationMessage, "message", "When the element has a custom validity message, validation message should return it");
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");
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");
}
function checkCheckValidity(element)
{
element.setCustomValidity("message");
ok(!element.checkValidity(), "checkValidity() should return false when the element is not valid");
ok(gInvalid, "Invalid event should have been handled");
gInvalid = false;
element.setCustomValidity("");
ok(element.checkValidity(), "Element should be valid");
ok(!gInvalid, "Invalid event should not have been handled");
}
function checkValidityStateObjectAliveWithoutElement(element)
{
// We are creating a temporary element and getting it's ValidityState object.
// Then, we make sure it is removed by the garbage collector and we check the
// ValidityState default values (it should not crash).
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var v = document.createElement(element).validity;
window.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
getInterface(Components.interfaces.nsIDOMWindowUtils).garbageCollect();
ok(!v.valueMissing,
"When the element is not alive, it shouldn't suffer from constraint validation");
ok(!v.typeMismatch,
"When the element is not alive, it shouldn't suffer from constraint validation");
ok(!v.patternMismatch,
"When the element is not alive, it shouldn't suffer from constraint validation");
ok(!v.tooLong,
"When the element is not alive, it shouldn't suffer from constraint validation");
ok(!v.rangeUnderflow,
"When the element is not alive, it shouldn't suffer from constraint validation");
ok(!v.rangeOverflow,
"When the element is not alive, it shouldn't suffer from constraint validation");
ok(!v.stepMismatch,
"When the element is not alive, it shouldn't suffer from constraint validation");
ok(!v.customError,
"When the element is not alive, it shouldn't suffer from constraint validation");
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'));
/* 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'));
checkSpecificWillValidate();
// Not checking fieldset, output and keygen
// because they are always barred from constraint validation.
checkCommonWillValidate(document.getElementById('i'));
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'));
// Not checking fieldset, output and keygen
// because they are always barred from constraint validation.
checkCheckValidity(document.getElementById('i'));
checkCheckValidity(document.getElementById('b'));
checkCheckValidity(document.getElementById('s'));
checkCheckValidity(document.getElementById('t'));
/* TODO: add "output" and "keygen" elements */
checkValidityStateObjectAliveWithoutElement("fieldset");
checkValidityStateObjectAliveWithoutElement("input");
checkValidityStateObjectAliveWithoutElement("button");
checkValidityStateObjectAliveWithoutElement("select");
checkValidityStateObjectAliveWithoutElement("textarea");
</script>
</pre>
</body>
</html>

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

@ -0,0 +1,67 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=345624
-->
<head>
<title>Test for Bug 345624</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=345624">Mozilla Bug 345624</a>
<p id="display"></p>
<div id="content" style="display: none">
<input id='i'>
<textarea id='t'></textarea>
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 345624 **/
/**
* This test is checking only tooLong related features
* related to constraint validation.
*/
function checkTooLongValidity(element)
{
element.value = "foo";
ok(!element.validity.tooLong,
"Element should not be too long when maxlength is not set");
element.maxLength = 3;
ok(!element.validity.tooLong,
"Element should not be to long when maxlength = value length");
element.maxLength = 5;
ok(!element.validity.tooLong,
"Element should not be too long when maxlength > value length");
ok(element.validity.valid, "Element should be valid");
element.maxLength = 2;
ok(element.validity.tooLong,
"Element should be too long when maxlength < value length");
ok(!element.validity.valid,
"Element should not be valid when it is too long");
is(element.validationMessage,
"The text is too long. It is 3 characters long and the limit is 2.",
"The validation message text is not correct");
ok(!element.checkValidity(), "The element should not be valid");
element.setCustomValidity("custom message");
is(element.validationMessage, "custom message",
"Custom message should be shown instead of too long one");
}
checkTooLongValidity(document.getElementById('i'));
checkTooLongValidity(document.getElementById('t'));
</script>
</pre>
</body>
</html>

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

@ -0,0 +1,322 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=345822
-->
<head>
<title>Test for Bug 345822</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=345822">Mozilla Bug 345822</a>
<p id="display"></p>
<div id="content" style="display: none">
<form>
<input name="input" id='i'>
<input name="input" id='r' type='radio'>
<textarea name="textarea" id='t'></textarea>
</form>
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 345822 **/
function checkRequiredAttribute(element)
{
ok('required' in element, "Element should have the required attribute");
ok(!element.required, "Element required attribute should be disabled");
is(element.getAttribute('required'), null,
"Element required attribute should be disabled");
element.required = true;
ok(element.required, "Element required attribute should be enabled");
isnot(element.getAttribute('required'), null,
"Element required attribute should be enabled");
element.removeAttribute('required');
element.setAttribute('required', '');
ok(element.required, "Element required attribute should be enabled");
isnot(element.getAttribute('required'), null,
"Element required attribute should be enabled");
element.removeAttribute('required');
ok(!element.required, "Element required attribute should be disabled");
is(element.getAttribute('required'), null,
"Element required attribute should be disabled");
}
function checkNotSufferingFromBeingMissing(element)
{
ok(!element.validity.valueMissing,
"Element should not suffer from value missing");
ok(element.validity.valid, "Element should be valid");
ok(element.checkValidity(), "Element should be valid");
is(element.validationMessage, "",
"Validation message should be the empty string");
}
function checkSufferingFromBeingMissing(element)
{
ok(element.validity.valueMissing, "Element should suffer from value missing");
ok(!element.validity.valid, "Element should not be valid");
ok(!element.checkValidity(), "Element should not be valid");
if (element.type == 'checkbox')
{
is(element.validationMessage,
"This checkbox is mandatory, you have to check it.",
"Validation message is wrong");
}
else if (element.type == 'radio')
{
is(element.validationMessage,
"You have to select one of these options.",
"Validation message is wrong");
}
else if (element.type == 'file')
{
is(element.validationMessage,
"You have to select a file.",
"Validation message is wrong");
}
else // text fields
{
is(element.validationMessage,
"This field is mandatory, you have to fill it.",
"Validation message is wrong");
}
}
function checkTextareaRequiredValidity(element)
{
element.value = '';
element.required = false;
checkNotSufferingFromBeingMissing(element);
element.required = true;
checkSufferingFromBeingMissing(element);
element.readOnly = true;
checkNotSufferingFromBeingMissing(element);
element.readOnly = false;
checkSufferingFromBeingMissing(element);
element.value = 'foo';
checkNotSufferingFromBeingMissing(element);
element.value = '';
checkSufferingFromBeingMissing(element);
element.required = false;
checkNotSufferingFromBeingMissing(element);
}
function checkInputRequiredNotApply(element)
{
element.value = '';
element.required = false;
checkNotSufferingFromBeingMissing(element);
element.required = true;
checkNotSufferingFromBeingMissing(element);
element.required = false;
}
function checkInputRequiredValidity(element)
{
element.value = '';
element.required = false;
checkNotSufferingFromBeingMissing(element);
element.required = true;
checkSufferingFromBeingMissing(element);
element.readOnly = true;
checkNotSufferingFromBeingMissing(element);
element.readOnly = false;
checkSufferingFromBeingMissing(element);
if (element.type == 'email') {
element.value = 'foo@bar.com';
} else if (element.type == 'url') {
element.value = 'http://mozilla.org/';
} else {
element.value = 'foo';
}
checkNotSufferingFromBeingMissing(element);
element.value = '';
checkSufferingFromBeingMissing(element);
element.required = false;
checkNotSufferingFromBeingMissing(element);
}
function checkInputRequiredValidityForCheckbox(element)
{
element.checked = false;
element.required = false;
checkNotSufferingFromBeingMissing(element);
element.required = true;
checkSufferingFromBeingMissing(element);
element.checked = true;
checkNotSufferingFromBeingMissing(element);
element.checked = false;
checkSufferingFromBeingMissing(element);
element.required = false;
checkNotSufferingFromBeingMissing(element);
}
function checkInputRequiredValidityForRadio(element)
{
element.checked = false;
element.required = false;
checkNotSufferingFromBeingMissing(element);
element.required = true;
checkSufferingFromBeingMissing(element);
element.checked = true;
checkNotSufferingFromBeingMissing(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';
element2.type = 'radio';
element2.checked = false;
element2.required = false;
element.checked = false;
element.required = true;
checkSufferingFromBeingMissing(element);
element2.checked = true;
checkNotSufferingFromBeingMissing(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.disabled = true;
checkNotSufferingFromBeingMissing(element);
// If a radio button is not required but another radio button is required in
// the same group, the not required radio button should not suffer from value
// missing.
element2.disabled = false;
element2.checked = false;
element.required = false;
element2.required = true;
checkNotSufferingFromBeingMissing(element);
checkSufferingFromBeingMissing(element2);
}
function checkInputRequiredValidityForFile(element)
{
function createFileWithData(fileName, fileData) {
var dirSvc = Components.classes["@mozilla.org/file/directory_service;1"]
.getService(Components.interfaces.nsIProperties);
var testFile = dirSvc.get("ProfD", Components.interfaces.nsIFile);
testFile.append(fileName);
var outStream = Components.
classes["@mozilla.org/network/file-output-stream;1"].
createInstance(Components.interfaces.nsIFileOutputStream);
outStream.init(testFile, 0x02 | 0x08 | 0x20, // write, create, truncate
0666, 0);
outStream.write(fileData, fileData.length);
outStream.close();
return testFile;
}
// Need privileges to set a filename with .value.
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var file = createFileWithData("345822_file", "file content");
element.value = "";
element.required = false;
checkNotSufferingFromBeingMissing(element);
element.required = true;
checkSufferingFromBeingMissing(element);
element.value = file.path;
checkNotSufferingFromBeingMissing(element);
element.value = "";
checkSufferingFromBeingMissing(element);
element.required = false;
checkNotSufferingFromBeingMissing(element);
file.remove(false);
}
var textarea = document.getElementById('t');
var input = document.getElementById('i');
checkRequiredAttribute(textarea);
checkTextareaRequiredValidity(textarea);
// Every input element should have the required attribute.
checkRequiredAttribute(input);
// The required attribute behavior depend of the input type.
// First of all, 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);
// 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);
</script>
</pre>
</body>
</html>

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

@ -105,7 +105,6 @@ objectIfaces2.push("nsIImageLoadingContent");
ol
param
q
spacer
ul
wbr
head
@ -210,7 +209,6 @@ HTML_TAG("script", "Script", [], [ "nsIScriptLoaderObserver" ]);
HTML_TAG("section", "") // HTMLElement
HTML_TAG("select", "Select");
HTML_TAG("small", ""); // HTMLElement
HTML_TAG("spacer", "Spacer");
HTML_TAG("span", "Span");
HTML_TAG("strike", ""); // HTMLElement
HTML_TAG("strong", ""); // HTMLElement

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

@ -25,6 +25,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=392567
var dataUrl = "http://mochi.test:8888/tests/content/html/content/test/bug392567.jar";
var jarUrl = "jar:" + dataUrl + "!/index.html";
var httpUrl = location.href.replace(/\.html.*/, "_404");
var previousDir = location.href.replace(/test\/[^\/]*$/, "");
var form = document.forms.testForm;
var frame = frames.testFrame;
@ -32,14 +33,17 @@ document.getElementById("testFrame").onload = processTestResult;
// List of tests to run, each test consists of form action URL and expected result URL
var tests = [
[jarUrl, jarUrl + "?$PARAMS"],
[jarUrl + "?jarTest1=jarTest2", jarUrl + "?$PARAMS"],
[jarUrl + "?jarTest3=jarTest4#jarTest5", jarUrl + "?$PARAMS#jarTest5"],
["data:text/html,<html></html>", "data:text/html,<html></html>?$PARAMS"],
["data:text/html,<html>How%20about%20this?</html>", "data:text/html,<html>How%20about%20this?$PARAMS"],
[httpUrl, httpUrl + "?$PARAMS"],
[httpUrl + "?httpTest1=httpTest2", httpUrl + "?$PARAMS"],
[httpUrl + "?httpTest3=httpTest4#httpTest5", httpUrl + "?$PARAMS#httpTest5"]
[jarUrl, jarUrl + "?$PARAMS", null],
[jarUrl + "?jarTest1=jarTest2", jarUrl + "?$PARAMS", null],
[jarUrl + "?jarTest3=jarTest4#jarTest5", jarUrl + "?$PARAMS#jarTest5", null],
["data:text/html,<html></html>", "data:text/html,<html></html>?$PARAMS", null],
["data:text/html,<html>How%20about%20this?</html>", "data:text/html,<html>How%20about%20this?$PARAMS", null],
[httpUrl, httpUrl + "?$PARAMS", null],
[httpUrl + "?httpTest1=httpTest2", httpUrl + "?$PARAMS", null ],
[httpUrl + "?httpTest3=httpTest4#httpTest5", httpUrl + "?$PARAMS#httpTest5", null],
["", jarUrl + "?key=value0", null],
[" ", jarUrl + "?key=value0", document.location],
["../", previousDir + "?$PARAMS", previousDir],
];
var currentTest = -1;
@ -54,7 +58,11 @@ function runNextTest() {
return;
}
form.action = tests[currentTest][0];
form.setAttribute("action", tests[currentTest][0]);
is(form.action, tests[currentTest][0],
"action IDL attribute should reflect the action content attribute");
is(form.mozActionUri, tests[currentTest][2] ? tests[currentTest][2] : tests[currentTest][0],
"mozActionUri IDL attribute should resolve the action URI");
form.key.value = "value" + currentTest;
form.submit();
}

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

@ -26,12 +26,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=549475
var inputTypes =
[
"text", "password", "search", "telephone", "hidden", "checkbox", "radio",
"submit", "image", "reset", "button",
"submit", "image", "reset", "button", "email", "url"
];
var todoTypes =
[
"email", "url", "number", "range", "color",
"number", "range", "color",
"date", "month", "week", "time", "datetime", "datetime-local",
];
@ -48,15 +48,10 @@ function sanitizeValue(aType, aValue)
case "password":
case "search":
case "telephone":
//case "email":
return aValue.replace(/[\n\r]/g, "");
case "email":
// TODO: uncomment the previous email case when email is implemented.
return "";
return aValue.replace(/[\n\r]/g, "");
case "url":
// TODO: uncomment the next line when url is implemented.
//return aValue.replace(/[\n\r]/g, "").replace(/^\s+|\s+$/g, ""');
return "";
return aValue.replace(/[\n\r]/g, "").replace(/^\s+|\s+$/g, "");
case "date":
case "month":
case "week":
@ -87,6 +82,7 @@ function checkSanitizing(element)
"foo\n\rbar",
" foo ",
" foo\n\r bar ",
"\r\n foobar \n\r",
];
for each (value in testData) {

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

@ -84,6 +84,7 @@ checkType(document.getElementById('b1'), document.getElementById('b2'), 'submit'
// input types
checkType(document.getElementById('i1'), document.getElementById('i2'), 'text', 'button', wrongType);
checkType(document.getElementById('i1'), document.getElementById('i2'), 'text', 'checkbox', wrongType);
checkType(document.getElementById('i1'), document.getElementById('i2'), 'text', 'email', wrongType);
checkType(document.getElementById('i1'), document.getElementById('i2'), 'text', 'file', wrongType);
checkType(document.getElementById('i1'), document.getElementById('i2'), 'text', 'hidden', wrongType);
checkType(document.getElementById('i1'), document.getElementById('i2'), 'text', 'reset', wrongType);
@ -93,6 +94,7 @@ checkType(document.getElementById('i1'), document.getElementById('i2'), 'text',
checkType(document.getElementById('i1'), document.getElementById('i2'), 'text', 'submit', wrongType);
checkType(document.getElementById('i1'), document.getElementById('i2'), 'text', 'tel', wrongType);
checkType(document.getElementById('i1'), document.getElementById('i2'), 'text', 'search', wrongType);
checkType(document.getElementById('i1'), document.getElementById('i2'), 'text', 'url', wrongType);
</script>
</pre>

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

@ -0,0 +1,232 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=555559
-->
<head>
<title>Test for Bug 555559</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=555559">Mozilla Bug 555559</a>
<p id="display"></p>
<div id="content" style="display: none">
<form>
<input type='email' name='email' id='i' oninvalid="invalidEventHandler(event);">
<form>
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 555559 **/
// More checks are done in test_bug551670.html.
var gInvalid = false;
function invalidEventHandler(e)
{
is(e.type, "invalid", "Invalid event type should be invalid");
gInvalid = true;
}
function checkValidEmailAddress(element)
{
gInvalid = false;
ok(!element.validity.typeMismatch,
"Element should not suffer from type mismatch");
ok(element.validity.valid, "Element should be valid");
ok(element.checkValidity(), "Element should be valid");
ok(!gInvalid, "The invalid event should not have been thrown");
is(element.validationMessage, '',
"Validation message should be the empty string");
}
function checkInvalidEmailAddress(element)
{
gInvalid = false;
ok(element.validity.typeMismatch,
"Element should suffer from type mismatch");
ok(!element.validity.valid, "Element should not be valid");
ok(!element.checkValidity(), "Element should not be valid");
ok(gInvalid, "The invalid event should have been thrown");
is(element.validationMessage, "The entered email address is not valid.",
"Validation message is not valid");
}
var email = document.forms[0].elements[0];
is(email.type, 'email', "email state should be recognized");
// This is not really a valid email address
// but it should not be considered as invalid.
email.value = '';
checkValidEmailAddress(email);
email.value = 'foo@bar.com';
checkValidEmailAddress(email);
email.value = ' foo@bar.com';
checkInvalidEmailAddress(email);
email.value = 'foo@bar.com ';
checkInvalidEmailAddress(email);
email.value = 'tulip';
checkInvalidEmailAddress(email);
// Some checks on the user part of the address.
email.value = '@bar.com';
checkInvalidEmailAddress(email);
var legalCharacters = "abcdefghijklmnopqrstuvwxyz";
legalCharacters += "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
legalCharacters += "0123456789";
legalCharacters += "!#$%&'*+-/=?^_`{|}~.";
for each (c in legalCharacters)
{
email.value = c + '@bar.com';
checkValidEmailAddress(email);
}
email.value = legalCharacters + '@bar.com';
checkValidEmailAddress(email);
// Checking stripped characters.
email.value = 'f\noo@bar.com';
checkValidEmailAddress(email);
email.value = 'f\roo@bar.com';
checkValidEmailAddress(email);
// Testing some illegal characters.
var illegalCharacters = "()<>[]:;@\, \t";
for each (c in illegalCharacters)
{
email.value = c + '@bar.com';
checkInvalidEmailAddress(email);
}
// Some checks on the domain part of the address.
email.value = 'foo@bar';
checkInvalidEmailAddress(email);
email.value = 'foo@b';
checkInvalidEmailAddress(email);
email.value = 'foo@';
checkInvalidEmailAddress(email);
email.value = 'foo@bar.';
checkInvalidEmailAddress(email);
email.value = 'foo@foo.bar';
checkValidEmailAddress(email);
email.value = 'foo@foo..bar';
checkInvalidEmailAddress(email);
email.value = 'foo@.bar';
checkInvalidEmailAddress(email);
email.value = 'foo@tulip.foo.bar';
checkValidEmailAddress(email);
email.value = 'foo@tulip.foo-bar';
checkValidEmailAddress(email);
email.value = 'foo@1.2';
checkValidEmailAddress(email);
email.value = 'foo@127.0.0.1';
checkValidEmailAddress(email);
email.value = 'foo@1.2.3.';
checkInvalidEmailAddress(email);
// Checking stripped characters.
email.value = 'foo@b\nar.com';
checkValidEmailAddress(email);
email.value = 'foo@b\rar.com';
checkValidEmailAddress(email);
// Testing some illegal characters.
illegalCharacters = "()<>[]:;@\,!#$%&'*+/=?^_`{|}~ \t";
for each (c in illegalCharacters)
{
email.value = 'foo@foo.bar' + c;
checkInvalidEmailAddress(email);
}
// Testing multiple: we are not going to re-test email validity, just multiple.
email.multiple = true;
email.value = 'foo@bar.com, foo@bar.com';
checkValidEmailAddress(email);
email.value = 'foo@bar.com,foo@bar.com';
checkValidEmailAddress(email);
email.value = 'foo@bar.com,foo@bar.com,foo@bar.com';
checkValidEmailAddress(email);
email.value = ' foo@bar.com , foo@bar.com ';
checkValidEmailAddress(email);
email.value = '\tfoo@bar.com\t,\tfoo@bar.com\t';
checkValidEmailAddress(email);
email.value = '\rfoo@bar.com\r,\rfoo@bar.com\r';
checkValidEmailAddress(email);
email.value = '\nfoo@bar.com\n,\nfoo@bar.com\n';
checkValidEmailAddress(email);
email.value = '\ffoo@bar.com\f,\ffoo@bar.com\f';
checkValidEmailAddress(email);
email.value = '\t foo@bar.com\r,\nfoo@bar.com\f';
checkValidEmailAddress(email);
email.value = 'foo@b,ar.com,foo@bar.com';
checkInvalidEmailAddress(email);
email.value = 'foo@bar.com,foo@bar.com,';
checkInvalidEmailAddress(email);
email.value = ' foo@bar.com , foo@bar.com , ';
checkInvalidEmailAddress(email);
email.value = ',foo@bar.com,foo@bar.com';
checkInvalidEmailAddress(email);
email.value = ',foo@bar.com,foo@bar.com';
checkInvalidEmailAddress(email);
email.value = 'foo@bar.com,,,foo@bar.com';
checkInvalidEmailAddress(email);
email.value = 'foo@bar.com;foo@bar.com';
checkInvalidEmailAddress(email);
email.value = '<foo@bar.com>, <foo@bar.com>';
checkInvalidEmailAddress(email);
email.value = 'foo@bar, foo@bar.com';
checkInvalidEmailAddress(email);
email.value = 'foo@bar.com, foo';
checkInvalidEmailAddress(email);
email.value = 'foo, foo@bar.com';
checkInvalidEmailAddress(email);
</script>
</pre>
</body>
</html>

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