LCOV - code coverage report
Current view: directory - content/html/content/src - nsHTMLInputElement.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 1762 188 10.7 %
Date: 2012-06-02 Functions: 222 45 20.3 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is Mozilla Communicator client code.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  * Netscape Communications Corporation.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *   Pierre Phaneuf <pp@ludusdesign.com>
      24                 :  *   Geoff Lankow <geoff@darktrojan.net>
      25                 :  *
      26                 :  * Alternatively, the contents of this file may be used under the terms of
      27                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      28                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      29                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      30                 :  * of those above. If you wish to allow use of your version of this file only
      31                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      32                 :  * use your version of this file under the terms of the MPL, indicate your
      33                 :  * decision by deleting the provisions above and replace them with the notice
      34                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      35                 :  * the provisions above, a recipient may use your version of this file under
      36                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      37                 :  *
      38                 :  * ***** END LICENSE BLOCK ***** */
      39                 : 
      40                 : #include "mozilla/Util.h"
      41                 : 
      42                 : #include "nsHTMLInputElement.h"
      43                 : 
      44                 : #include "nsIDOMHTMLInputElement.h"
      45                 : #include "nsITextControlElement.h"
      46                 : #include "nsIDOMNSEditableElement.h"
      47                 : #include "nsIRadioVisitor.h"
      48                 : #include "nsIPhonetic.h"
      49                 : 
      50                 : #include "nsIControllers.h"
      51                 : #include "nsFocusManager.h"
      52                 : #include "nsPIDOMWindow.h"
      53                 : #include "nsContentCID.h"
      54                 : #include "nsIComponentManager.h"
      55                 : #include "nsIDOMHTMLFormElement.h"
      56                 : #include "nsGkAtoms.h"
      57                 : #include "nsStyleConsts.h"
      58                 : #include "nsPresContext.h"
      59                 : #include "nsMappedAttributes.h"
      60                 : #include "nsIFormControl.h"
      61                 : #include "nsIForm.h"
      62                 : #include "nsFormSubmission.h"
      63                 : #include "nsFormSubmissionConstants.h"
      64                 : #include "nsIDocument.h"
      65                 : #include "nsIPresShell.h"
      66                 : #include "nsIFormControlFrame.h"
      67                 : #include "nsITextControlFrame.h"
      68                 : #include "nsIFrame.h"
      69                 : #include "nsEventStates.h"
      70                 : #include "nsIServiceManager.h"
      71                 : #include "nsIScriptSecurityManager.h"
      72                 : #include "nsDOMError.h"
      73                 : #include "nsIPrivateDOMEvent.h"
      74                 : #include "nsIEditor.h"
      75                 : #include "nsGUIEvent.h"
      76                 : #include "nsIIOService.h"
      77                 : #include "nsDocument.h"
      78                 : #include "nsAttrValueOrString.h"
      79                 : 
      80                 : #include "nsPresState.h"
      81                 : #include "nsLayoutErrors.h"
      82                 : #include "nsIDOMEvent.h"
      83                 : #include "nsIDOMNSEvent.h"
      84                 : #include "nsIDOMNodeList.h"
      85                 : #include "nsIDOMHTMLCollection.h"
      86                 : #include "nsLinebreakConverter.h" //to strip out carriage returns
      87                 : #include "nsReadableUtils.h"
      88                 : #include "nsUnicharUtils.h"
      89                 : #include "nsEventDispatcher.h"
      90                 : #include "nsLayoutUtils.h"
      91                 : 
      92                 : #include "nsIDOMMutationEvent.h"
      93                 : #include "nsIDOMEventTarget.h"
      94                 : #include "nsMutationEvent.h"
      95                 : #include "nsEventListenerManager.h"
      96                 : 
      97                 : #include "nsRuleData.h"
      98                 : 
      99                 : // input type=radio
     100                 : #include "nsIRadioGroupContainer.h"
     101                 : 
     102                 : // input type=file
     103                 : #include "nsILocalFile.h"
     104                 : #include "nsNetUtil.h"
     105                 : #include "nsDOMFile.h"
     106                 : #include "nsIFilePicker.h"
     107                 : #include "nsDirectoryServiceDefs.h"
     108                 : #include "nsIContentPrefService.h"
     109                 : #include "nsIObserverService.h"
     110                 : #include "nsIPopupWindowManager.h"
     111                 : #include "nsGlobalWindow.h"
     112                 : 
     113                 : // input type=image
     114                 : #include "nsImageLoadingContent.h"
     115                 : 
     116                 : #include "mozAutoDocUpdate.h"
     117                 : #include "nsContentCreatorFunctions.h"
     118                 : #include "nsContentUtils.h"
     119                 : #include "nsRadioVisitor.h"
     120                 : 
     121                 : #include "mozilla/LookAndFeel.h"
     122                 : #include "mozilla/Util.h" // DebugOnly
     123                 : 
     124                 : #include "nsIIDNService.h"
     125                 : 
     126                 : using namespace mozilla;
     127                 : using namespace mozilla::dom;
     128                 : 
     129                 : // XXX align=left, hspace, vspace, border? other nav4 attrs
     130                 : 
     131                 : static NS_DEFINE_CID(kXULControllersCID,  NS_XULCONTROLLERS_CID);
     132                 : 
     133                 : // First bits are needed for the control type.
     134                 : #define NS_OUTER_ACTIVATE_EVENT   (1 << 9)
     135                 : #define NS_ORIGINAL_CHECKED_VALUE (1 << 10)
     136                 : #define NS_NO_CONTENT_DISPATCH    (1 << 11)
     137                 : #define NS_ORIGINAL_INDETERMINATE_VALUE (1 << 12)
     138                 : #define NS_CONTROL_TYPE(bits)  ((bits) & ~( \
     139                 :   NS_OUTER_ACTIVATE_EVENT | NS_ORIGINAL_CHECKED_VALUE | NS_NO_CONTENT_DISPATCH | \
     140                 :   NS_ORIGINAL_INDETERMINATE_VALUE))
     141                 : 
     142                 : // whether textfields should be selected once focused:
     143                 : //  -1: no, 1: yes, 0: uninitialized
     144                 : static PRInt32 gSelectTextFieldOnFocus;
     145                 : UploadLastDir* nsHTMLInputElement::gUploadLastDir;
     146                 : 
     147                 : static const nsAttrValue::EnumTable kInputTypeTable[] = {
     148                 :   { "button", NS_FORM_INPUT_BUTTON },
     149                 :   { "checkbox", NS_FORM_INPUT_CHECKBOX },
     150                 :   { "email", NS_FORM_INPUT_EMAIL },
     151                 :   { "file", NS_FORM_INPUT_FILE },
     152                 :   { "hidden", NS_FORM_INPUT_HIDDEN },
     153                 :   { "reset", NS_FORM_INPUT_RESET },
     154                 :   { "image", NS_FORM_INPUT_IMAGE },
     155                 :   { "password", NS_FORM_INPUT_PASSWORD },
     156                 :   { "radio", NS_FORM_INPUT_RADIO },
     157                 :   { "search", NS_FORM_INPUT_SEARCH },
     158                 :   { "submit", NS_FORM_INPUT_SUBMIT },
     159                 :   { "tel", NS_FORM_INPUT_TEL },
     160                 :   { "text", NS_FORM_INPUT_TEXT },
     161                 :   { "url", NS_FORM_INPUT_URL },
     162                 :   { 0 }
     163                 : };
     164                 : 
     165                 : // Default type is 'text'.
     166                 : static const nsAttrValue::EnumTable* kInputDefaultType = &kInputTypeTable[12];
     167                 : 
     168                 : static const PRUint8 NS_INPUT_AUTOCOMPLETE_OFF     = 0;
     169                 : static const PRUint8 NS_INPUT_AUTOCOMPLETE_ON      = 1;
     170                 : static const PRUint8 NS_INPUT_AUTOCOMPLETE_DEFAULT = 2;
     171                 : 
     172                 : static const nsAttrValue::EnumTable kInputAutocompleteTable[] = {
     173                 :   { "", NS_INPUT_AUTOCOMPLETE_DEFAULT },
     174                 :   { "on", NS_INPUT_AUTOCOMPLETE_ON },
     175                 :   { "off", NS_INPUT_AUTOCOMPLETE_OFF },
     176                 :   { 0 }
     177                 : };
     178                 : 
     179                 : // Default autocomplete value is "".
     180                 : static const nsAttrValue::EnumTable* kInputDefaultAutocomplete = &kInputAutocompleteTable[0];
     181                 : 
     182                 : #define NS_INPUT_ELEMENT_STATE_IID                 \
     183                 : { /* dc3b3d14-23e2-4479-b513-7b369343e3a0 */       \
     184                 :   0xdc3b3d14,                                      \
     185                 :   0x23e2,                                          \
     186                 :   0x4479,                                          \
     187                 :   {0xb5, 0x13, 0x7b, 0x36, 0x93, 0x43, 0xe3, 0xa0} \
     188                 : }
     189                 : 
     190                 : class nsHTMLInputElementState MOZ_FINAL : public nsISupports
     191               0 : {
     192                 :   public:
     193                 :     NS_DECLARE_STATIC_IID_ACCESSOR(NS_INPUT_ELEMENT_STATE_IID)
     194                 :     NS_DECL_ISUPPORTS
     195                 : 
     196               0 :     bool IsCheckedSet() {
     197               0 :       return mCheckedSet;
     198                 :     }
     199                 : 
     200               0 :     bool GetChecked() {
     201               0 :       return mChecked;
     202                 :     }
     203                 : 
     204               0 :     void SetChecked(bool aChecked) {
     205               0 :       mChecked = aChecked;
     206               0 :       mCheckedSet = true;
     207               0 :     }
     208                 : 
     209               0 :     const nsString& GetValue() {
     210               0 :       return mValue;
     211                 :     }
     212                 : 
     213               0 :     void SetValue(const nsAString &aValue) {
     214               0 :       mValue = aValue;
     215               0 :     }
     216                 : 
     217               0 :     const nsCOMArray<nsIDOMFile>& GetFiles() {
     218               0 :       return mFiles;
     219                 :     }
     220                 : 
     221               0 :     void SetFiles(const nsCOMArray<nsIDOMFile> &aFiles) {
     222               0 :       mFiles.Clear();
     223               0 :       mFiles.AppendObjects(aFiles);
     224               0 :     }
     225                 : 
     226               0 :     nsHTMLInputElementState()
     227                 :       : mValue()
     228                 :       , mChecked(false)
     229               0 :       , mCheckedSet(false)
     230               0 :     {};
     231                 :  
     232                 :   protected:
     233                 :     nsString mValue;
     234                 :     nsCOMArray<nsIDOMFile> mFiles;
     235                 :     bool mChecked;
     236                 :     bool mCheckedSet;
     237                 : };
     238                 : 
     239               0 : NS_IMPL_ISUPPORTS1(nsHTMLInputElementState, nsHTMLInputElementState)
     240                 : NS_DEFINE_STATIC_IID_ACCESSOR(nsHTMLInputElementState, NS_INPUT_ELEMENT_STATE_IID)
     241                 : 
     242               0 : class AsyncClickHandler : public nsRunnable {
     243                 : public:
     244               0 :   AsyncClickHandler(nsHTMLInputElement* aInput)
     245               0 :    : mInput(aInput) {
     246                 :     
     247               0 :     nsPIDOMWindow* win = aInput->OwnerDoc()->GetWindow();
     248               0 :     if (win) {
     249               0 :       mPopupControlState = win->GetPopupControlState();
     250                 :     }
     251               0 :   };
     252                 : 
     253                 :   NS_IMETHOD Run();
     254                 : 
     255                 : protected:
     256                 :   nsRefPtr<nsHTMLInputElement> mInput;
     257                 :   PopupControlState mPopupControlState;
     258                 : };
     259                 : 
     260                 : NS_IMETHODIMP
     261               0 : AsyncClickHandler::Run()
     262                 : {
     263                 :   // Get parent nsPIDOMWindow object.
     264               0 :   nsCOMPtr<nsIDocument> doc = mInput->OwnerDoc();
     265                 : 
     266               0 :   nsPIDOMWindow* win = doc->GetWindow();
     267               0 :   if (!win) {
     268               0 :     return NS_ERROR_FAILURE;
     269                 :   }
     270                 : 
     271                 :   // Check if page is allowed to open the popup
     272               0 :   if (mPopupControlState > openControlled) {
     273                 :     nsCOMPtr<nsIPopupWindowManager> pm =
     274               0 :       do_GetService(NS_POPUPWINDOWMANAGER_CONTRACTID);
     275                 : 
     276               0 :     if (!pm) {
     277               0 :       return NS_OK;
     278                 :     }
     279                 : 
     280                 :     PRUint32 permission;
     281               0 :     pm->TestPermission(doc->GetDocumentURI(), &permission);
     282               0 :     if (permission == nsIPopupWindowManager::DENY_POPUP) {
     283               0 :       nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(doc);
     284               0 :       nsGlobalWindow::FirePopupBlockedEvent(domDoc, win, nsnull, EmptyString(), EmptyString());
     285               0 :       return NS_OK;
     286                 :     }
     287                 :   }
     288                 : 
     289                 :   // Get Loc title
     290               0 :   nsXPIDLString title;
     291                 :   nsContentUtils::GetLocalizedString(nsContentUtils::eFORMS_PROPERTIES,
     292               0 :                                      "FileUpload", title);
     293                 : 
     294               0 :   nsCOMPtr<nsIFilePicker> filePicker = do_CreateInstance("@mozilla.org/filepicker;1");
     295               0 :   if (!filePicker)
     296               0 :     return NS_ERROR_FAILURE;
     297                 : 
     298               0 :   bool multi = mInput->HasAttr(kNameSpaceID_None, nsGkAtoms::multiple);
     299                 : 
     300               0 :   nsresult rv = filePicker->Init(win, title,
     301                 :                                  multi
     302                 :                                   ? static_cast<PRInt16>(nsIFilePicker::modeOpenMultiple)
     303               0 :                                   : static_cast<PRInt16>(nsIFilePicker::modeOpen));
     304               0 :   NS_ENSURE_SUCCESS(rv, rv);
     305                 : 
     306               0 :   if (mInput->HasAttr(kNameSpaceID_None, nsGkAtoms::accept)) {
     307               0 :     PRInt32 filters = mInput->GetFilterFromAccept();
     308                 : 
     309               0 :     if (filters) {
     310                 :       // We add |filterAll| to be sure the user always has a sane fallback.
     311               0 :       filePicker->AppendFilters(filters | nsIFilePicker::filterAll);
     312                 : 
     313                 :       // If the accept attribute asked for a filter, we need to make it default.
     314                 :       // |filterAll| will always use index=0 so we need to set index=1 as the
     315                 :       // current filter.
     316               0 :       filePicker->SetFilterIndex(1);
     317                 :     } else {
     318               0 :       filePicker->AppendFilters(nsIFilePicker::filterAll);
     319                 :     }
     320                 :   } else {
     321               0 :     filePicker->AppendFilters(nsIFilePicker::filterAll);
     322                 :   }
     323                 : 
     324                 :   // Set default directry and filename
     325               0 :   nsAutoString defaultName;
     326                 : 
     327               0 :   const nsCOMArray<nsIDOMFile>& oldFiles = mInput->GetFiles();
     328                 : 
     329               0 :   if (oldFiles.Count()) {
     330               0 :     nsString path;
     331                 : 
     332               0 :     oldFiles[0]->GetMozFullPathInternal(path);
     333                 : 
     334               0 :     nsCOMPtr<nsILocalFile> localFile;
     335               0 :     rv = NS_NewLocalFile(path, false, getter_AddRefs(localFile));
     336                 : 
     337               0 :     if (NS_SUCCEEDED(rv)) {
     338               0 :       nsCOMPtr<nsIFile> parentFile;
     339               0 :       rv = localFile->GetParent(getter_AddRefs(parentFile));
     340               0 :       if (NS_SUCCEEDED(rv)) {
     341               0 :         nsCOMPtr<nsILocalFile> parentLocalFile = do_QueryInterface(parentFile, &rv);
     342               0 :         if (parentLocalFile) {
     343               0 :           filePicker->SetDisplayDirectory(parentLocalFile);
     344                 :         }
     345                 :       }
     346                 :     }
     347                 : 
     348                 :     // Unfortunately nsIFilePicker doesn't allow multiple files to be
     349                 :     // default-selected, so only select something by default if exactly
     350                 :     // one file was selected before.
     351               0 :     if (oldFiles.Count() == 1) {
     352               0 :       nsAutoString leafName;
     353               0 :       oldFiles[0]->GetName(leafName);
     354               0 :       if (!leafName.IsEmpty()) {
     355               0 :         filePicker->SetDefaultString(leafName);
     356                 :       }
     357                 :     }
     358                 :   } else {
     359                 :     // Attempt to retrieve the last used directory from the content pref service
     360               0 :     nsCOMPtr<nsILocalFile> localFile;
     361                 :     nsHTMLInputElement::gUploadLastDir->FetchLastUsedDirectory(doc->GetDocumentURI(),
     362               0 :                                                                getter_AddRefs(localFile));
     363               0 :     if (!localFile) {
     364                 :       // Default to "desktop" directory for each platform
     365               0 :       nsCOMPtr<nsIFile> homeDir;
     366               0 :       NS_GetSpecialDirectory(NS_OS_DESKTOP_DIR, getter_AddRefs(homeDir));
     367               0 :       localFile = do_QueryInterface(homeDir);
     368                 :     }
     369               0 :     filePicker->SetDisplayDirectory(localFile);
     370                 :   }
     371                 : 
     372                 :   // Open dialog
     373                 :   PRInt16 mode;
     374               0 :   rv = filePicker->Show(&mode);
     375               0 :   NS_ENSURE_SUCCESS(rv, rv);
     376               0 :   if (mode == nsIFilePicker::returnCancel) {
     377               0 :     return NS_OK;
     378                 :   }
     379                 : 
     380                 :   // Collect new selected filenames
     381               0 :   nsCOMArray<nsIDOMFile> newFiles;
     382               0 :   if (multi) {
     383               0 :     nsCOMPtr<nsISimpleEnumerator> iter;
     384               0 :     rv = filePicker->GetFiles(getter_AddRefs(iter));
     385               0 :     NS_ENSURE_SUCCESS(rv, rv);
     386                 : 
     387               0 :     nsCOMPtr<nsISupports> tmp;
     388               0 :     bool prefSaved = false;
     389               0 :     bool loop = true;
     390               0 :     while (NS_SUCCEEDED(iter->HasMoreElements(&loop)) && loop) {
     391               0 :       iter->GetNext(getter_AddRefs(tmp));
     392               0 :       nsCOMPtr<nsILocalFile> localFile = do_QueryInterface(tmp);
     393               0 :       if (localFile) {
     394               0 :         nsString unicodePath;
     395               0 :         rv = localFile->GetPath(unicodePath);
     396               0 :         if (!unicodePath.IsEmpty()) {
     397                 :           nsCOMPtr<nsIDOMFile> domFile =
     398               0 :             do_QueryObject(new nsDOMFileFile(localFile));
     399               0 :           newFiles.AppendObject(domFile);
     400                 :         }
     401               0 :         if (!prefSaved) {
     402                 :           // Store the last used directory using the content pref service
     403                 :           nsHTMLInputElement::gUploadLastDir->StoreLastUsedDirectory(doc->GetDocumentURI(),
     404               0 :                                                                      localFile);
     405               0 :           prefSaved = true;
     406                 :         }
     407                 :       }
     408                 :     }
     409                 :   }
     410                 :   else {
     411               0 :     nsCOMPtr<nsILocalFile> localFile;
     412               0 :     rv = filePicker->GetFile(getter_AddRefs(localFile));
     413               0 :     if (localFile) {
     414               0 :       nsString unicodePath;
     415               0 :       rv = localFile->GetPath(unicodePath);
     416               0 :       if (!unicodePath.IsEmpty()) {
     417                 :         nsCOMPtr<nsIDOMFile> domFile=
     418               0 :           do_QueryObject(new nsDOMFileFile(localFile));
     419               0 :         newFiles.AppendObject(domFile);
     420                 :       }
     421                 :       // Store the last used directory using the content pref service
     422                 :       nsHTMLInputElement::gUploadLastDir->StoreLastUsedDirectory(doc->GetDocumentURI(),
     423               0 :                                                                  localFile);
     424                 :     }
     425                 :   }
     426                 : 
     427                 :   // Set new selected files
     428               0 :   if (newFiles.Count()) {
     429                 :     // The text control frame (if there is one) isn't going to send a change
     430                 :     // event because it will think this is done by a script.
     431                 :     // So, we can safely send one by ourself.
     432               0 :     mInput->SetFiles(newFiles, true);
     433               0 :     nsContentUtils::DispatchTrustedEvent(mInput->OwnerDoc(),
     434               0 :                                          static_cast<nsIDOMHTMLInputElement*>(mInput.get()),
     435               0 :                                          NS_LITERAL_STRING("change"), true,
     436               0 :                                          false);
     437                 :   }
     438                 : 
     439               0 :   return NS_OK;
     440                 : }
     441                 : 
     442                 : #define CPS_PREF_NAME NS_LITERAL_STRING("browser.upload.lastDir")
     443                 : 
     444               6 : NS_IMPL_ISUPPORTS2(UploadLastDir, nsIObserver, nsISupportsWeakReference)
     445                 : 
     446                 : void
     447               1 : nsHTMLInputElement::InitUploadLastDir() {
     448               1 :   gUploadLastDir = new UploadLastDir();
     449               1 :   NS_ADDREF(gUploadLastDir);
     450                 : 
     451                 :   nsCOMPtr<nsIObserverService> observerService =
     452               2 :     mozilla::services::GetObserverService();
     453               1 :   if (observerService && gUploadLastDir) {
     454               1 :     observerService->AddObserver(gUploadLastDir, "browser:purge-session-history", true);
     455                 :   }
     456               1 : }
     457                 : 
     458                 : void 
     459            1403 : nsHTMLInputElement::DestroyUploadLastDir() {
     460            1403 :   NS_IF_RELEASE(gUploadLastDir);
     461            1403 : }
     462                 : 
     463                 : nsresult
     464               0 : UploadLastDir::FetchLastUsedDirectory(nsIURI* aURI, nsILocalFile** aFile)
     465                 : {
     466               0 :   NS_PRECONDITION(aURI, "aURI is null");
     467               0 :   NS_PRECONDITION(aFile, "aFile is null");
     468                 :   // Attempt to get the CPS, if it's not present we'll just return
     469                 :   nsCOMPtr<nsIContentPrefService> contentPrefService =
     470               0 :     do_GetService(NS_CONTENT_PREF_SERVICE_CONTRACTID);
     471               0 :   if (!contentPrefService)
     472               0 :     return NS_ERROR_NOT_AVAILABLE;
     473               0 :   nsCOMPtr<nsIWritableVariant> uri = do_CreateInstance(NS_VARIANT_CONTRACTID);
     474               0 :   if (!uri)
     475               0 :     return NS_ERROR_OUT_OF_MEMORY;
     476               0 :   uri->SetAsISupports(aURI);
     477                 : 
     478                 :   // Get the last used directory, if it is stored
     479                 :   bool hasPref;
     480               0 :   if (NS_SUCCEEDED(contentPrefService->HasPref(uri, CPS_PREF_NAME, &hasPref)) && hasPref) {
     481               0 :     nsCOMPtr<nsIVariant> pref;
     482               0 :     contentPrefService->GetPref(uri, CPS_PREF_NAME, nsnull, getter_AddRefs(pref));
     483               0 :     nsString prefStr;
     484               0 :     pref->GetAsAString(prefStr);
     485                 : 
     486               0 :     nsCOMPtr<nsILocalFile> localFile = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID);
     487               0 :     if (!localFile)
     488               0 :       return NS_ERROR_OUT_OF_MEMORY;
     489               0 :     localFile->InitWithPath(prefStr);
     490               0 :     localFile.forget(aFile);
     491                 :   }
     492               0 :   return NS_OK;
     493                 : }
     494                 : 
     495                 : nsresult
     496               0 : UploadLastDir::StoreLastUsedDirectory(nsIURI* aURI, nsILocalFile* aFile)
     497                 : {
     498               0 :   NS_PRECONDITION(aURI, "aURI is null");
     499               0 :   NS_PRECONDITION(aFile, "aFile is null");
     500               0 :   nsCOMPtr<nsIFile> parentFile;
     501               0 :   aFile->GetParent(getter_AddRefs(parentFile));
     502               0 :   if (!parentFile) {
     503               0 :     return NS_OK;
     504                 :   }
     505               0 :   nsCOMPtr<nsILocalFile> localFile = do_QueryInterface(parentFile);
     506                 : 
     507                 :   // Attempt to get the CPS, if it's not present we'll just return
     508                 :   nsCOMPtr<nsIContentPrefService> contentPrefService =
     509               0 :     do_GetService(NS_CONTENT_PREF_SERVICE_CONTRACTID);
     510               0 :   if (!contentPrefService)
     511               0 :     return NS_ERROR_NOT_AVAILABLE;
     512               0 :   nsCOMPtr<nsIWritableVariant> uri = do_CreateInstance(NS_VARIANT_CONTRACTID);
     513               0 :   if (!uri)
     514               0 :     return NS_ERROR_OUT_OF_MEMORY;
     515               0 :   uri->SetAsISupports(aURI);
     516                 :  
     517                 :   // Find the parent of aFile, and store it
     518               0 :   nsString unicodePath;
     519               0 :   parentFile->GetPath(unicodePath);
     520               0 :   if (unicodePath.IsEmpty()) // nothing to do
     521               0 :     return NS_OK;
     522               0 :   nsCOMPtr<nsIWritableVariant> prefValue = do_CreateInstance(NS_VARIANT_CONTRACTID);
     523               0 :   if (!prefValue)
     524               0 :     return NS_ERROR_OUT_OF_MEMORY;
     525               0 :   prefValue->SetAsAString(unicodePath);
     526               0 :   return contentPrefService->SetPref(uri, CPS_PREF_NAME, prefValue);
     527                 : }
     528                 : 
     529                 : NS_IMETHODIMP
     530               0 : UploadLastDir::Observe(nsISupports *aSubject, char const *aTopic, PRUnichar const *aData)
     531                 : {
     532               0 :   if (strcmp(aTopic, "browser:purge-session-history") == 0) {
     533                 :     nsCOMPtr<nsIContentPrefService> contentPrefService =
     534               0 :       do_GetService(NS_CONTENT_PREF_SERVICE_CONTRACTID);
     535               0 :     if (contentPrefService)
     536               0 :       contentPrefService->RemovePrefsByName(CPS_PREF_NAME);
     537                 :   }
     538               0 :   return NS_OK;
     539                 : }
     540                 : 
     541                 : #ifdef ACCESSIBILITY
     542                 : //Helper method
     543                 : static nsresult FireEventForAccessibility(nsIDOMHTMLInputElement* aTarget,
     544                 :                                           nsPresContext* aPresContext,
     545                 :                                           const nsAString& aEventType);
     546                 : #endif
     547                 : 
     548                 : //
     549                 : // construction, destruction
     550                 : //
     551                 : 
     552               2 : NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(Input)
     553                 : 
     554               1 : nsHTMLInputElement::nsHTMLInputElement(already_AddRefed<nsINodeInfo> aNodeInfo,
     555                 :                                        FromParser aFromParser)
     556                 :   : nsGenericHTMLFormElement(aNodeInfo)
     557                 :   , mType(kInputDefaultType->value)
     558                 :   , mDisabledChanged(false)
     559                 :   , mValueChanged(false)
     560                 :   , mCheckedChanged(false)
     561                 :   , mChecked(false)
     562                 :   , mHandlingSelectEvent(false)
     563                 :   , mShouldInitChecked(false)
     564                 :   , mParserCreating(aFromParser != NOT_FROM_PARSER)
     565                 :   , mInInternalActivate(false)
     566                 :   , mCheckedIsToggled(false)
     567                 :   , mIndeterminate(false)
     568                 :   , mInhibitRestoration(aFromParser & FROM_PARSER_FRAGMENT)
     569                 :   , mCanShowValidUI(true)
     570               1 :   , mCanShowInvalidUI(true)
     571                 : {
     572               1 :   mInputData.mState = new nsTextEditorState(this);
     573               1 :   NS_ADDREF(mInputData.mState);
     574                 :   
     575               1 :   if (!gUploadLastDir)
     576               1 :     nsHTMLInputElement::InitUploadLastDir();
     577                 : 
     578                 :   // Set up our default state.  By default we're enabled (since we're
     579                 :   // a control type that can be disabled but not actually disabled
     580                 :   // right now), optional, and valid.  We are NOT readwrite by default
     581                 :   // until someone calls UpdateEditableState on us, apparently!  Also
     582                 :   // by default we don't have to show validity UI and so forth.
     583                 :   AddStatesSilently(NS_EVENT_STATE_ENABLED |
     584                 :                     NS_EVENT_STATE_OPTIONAL |
     585               1 :                     NS_EVENT_STATE_VALID);
     586               1 : }
     587                 : 
     588               3 : nsHTMLInputElement::~nsHTMLInputElement()
     589                 : {
     590               1 :   if (mFileList) {
     591               0 :     mFileList->Disconnect();
     592                 :   }
     593               1 :   DestroyImageLoadingContent();
     594               1 :   FreeData();
     595               4 : }
     596                 : 
     597                 : void
     598               1 : nsHTMLInputElement::FreeData()
     599                 : {
     600               1 :   if (!IsSingleLineTextControl(false)) {
     601               0 :     nsMemory::Free(mInputData.mValue);
     602               0 :     mInputData.mValue = nsnull;
     603                 :   } else {
     604               1 :     UnbindFromFrame(nsnull);
     605               1 :     NS_IF_RELEASE(mInputData.mState);
     606                 :   }
     607               1 : }
     608                 : 
     609                 : nsTextEditorState*
     610               2 : nsHTMLInputElement::GetEditorState() const
     611                 : {
     612               2 :   if (!IsSingleLineTextControl(false)) {
     613               0 :     return nsnull;
     614                 :   }
     615                 : 
     616               2 :   NS_ASSERTION(mInputData.mState,
     617                 :     "Single line text controls need to have a state associated with them");
     618                 : 
     619               2 :   return mInputData.mState;
     620                 : }
     621                 : 
     622                 : 
     623                 : // nsISupports
     624                 : 
     625            1464 : NS_IMPL_CYCLE_COLLECTION_CLASS(nsHTMLInputElement)
     626               1 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsHTMLInputElement,
     627                 :                                                   nsGenericHTMLFormElement)
     628               1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mControllers)
     629               1 :   if (tmp->IsSingleLineTextControl(false)) {
     630               1 :     NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_MEMBER(mInputData.mState, nsTextEditorState)
     631                 :   }
     632               1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mFiles)
     633               1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFileList)
     634               1 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
     635                 : 
     636               1 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsHTMLInputElement,
     637                 :                                                   nsGenericHTMLFormElement)
     638               1 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mControllers)
     639               1 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mFiles)
     640               1 :   if (tmp->mFileList) {
     641               0 :     tmp->mFileList->Disconnect();
     642               0 :     tmp->mFileList = nsnull;
     643                 :   }
     644                 :   //XXX should unlink more?
     645               1 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
     646                 :                                                               
     647              19 : NS_IMPL_ADDREF_INHERITED(nsHTMLInputElement, nsGenericElement) 
     648              19 : NS_IMPL_RELEASE_INHERITED(nsHTMLInputElement, nsGenericElement) 
     649                 : 
     650                 : 
     651               1 : DOMCI_NODE_DATA(HTMLInputElement, nsHTMLInputElement)
     652                 : 
     653                 : // QueryInterface implementation for nsHTMLInputElement
     654              39 : NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsHTMLInputElement)
     655              24 :   NS_HTML_CONTENT_INTERFACE_TABLE8(nsHTMLInputElement,
     656                 :                                    nsIDOMHTMLInputElement,
     657                 :                                    nsITextControlElement,
     658                 :                                    nsIPhonetic,
     659                 :                                    imgIDecoderObserver,
     660                 :                                    nsIImageLoadingContent,
     661                 :                                    imgIContainerObserver,
     662                 :                                    nsIDOMNSEditableElement,
     663                 :                                    nsIConstraintValidation)
     664              23 :   NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLInputElement,
     665                 :                                                nsGenericHTMLFormElement)
     666               0 : NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLInputElement)
     667                 : 
     668                 : // nsIConstraintValidation
     669               0 : NS_IMPL_NSICONSTRAINTVALIDATION_EXCEPT_SETCUSTOMVALIDITY(nsHTMLInputElement)
     670                 : 
     671                 : // nsIDOMNode
     672                 : 
     673                 : nsresult
     674               0 : nsHTMLInputElement::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const
     675                 : {
     676               0 :   *aResult = nsnull;
     677                 : 
     678               0 :   nsCOMPtr<nsINodeInfo> ni = aNodeInfo;
     679                 :   nsRefPtr<nsHTMLInputElement> it =
     680               0 :     new nsHTMLInputElement(ni.forget(), NOT_FROM_PARSER);
     681                 : 
     682               0 :   nsresult rv = CopyInnerTo(it);
     683               0 :   NS_ENSURE_SUCCESS(rv, rv);
     684                 : 
     685               0 :   switch (mType) {
     686                 :     case NS_FORM_INPUT_EMAIL:
     687                 :     case NS_FORM_INPUT_SEARCH:
     688                 :     case NS_FORM_INPUT_TEXT:
     689                 :     case NS_FORM_INPUT_PASSWORD:
     690                 :     case NS_FORM_INPUT_TEL:
     691                 :     case NS_FORM_INPUT_URL:
     692               0 :       if (mValueChanged) {
     693                 :         // We don't have our default value anymore.  Set our value on
     694                 :         // the clone.
     695               0 :         nsAutoString value;
     696               0 :         GetValueInternal(value);
     697                 :         // SetValueInternal handles setting the VALUE_CHANGED bit for us
     698               0 :         it->SetValueInternal(value, false, true);
     699                 :       }
     700               0 :       break;
     701                 :     case NS_FORM_INPUT_FILE:
     702               0 :       if (it->OwnerDoc()->IsStaticDocument()) {
     703                 :         // We're going to be used in print preview.  Since the doc is static
     704                 :         // we can just grab the pretty string and use it as wallpaper
     705               0 :         GetDisplayFileName(it->mStaticDocFileList);
     706                 :       } else {
     707               0 :         it->mFiles.Clear();
     708               0 :         it->mFiles.AppendObjects(mFiles);
     709                 :       }
     710               0 :       break;
     711                 :     case NS_FORM_INPUT_RADIO:
     712                 :     case NS_FORM_INPUT_CHECKBOX:
     713               0 :       if (mCheckedChanged) {
     714                 :         // We no longer have our original checked state.  Set our
     715                 :         // checked state on the clone.
     716               0 :         it->DoSetChecked(mChecked, false, true);
     717                 :       }
     718               0 :       break;
     719                 :     case NS_FORM_INPUT_IMAGE:
     720               0 :       if (it->OwnerDoc()->IsStaticDocument()) {
     721               0 :         CreateStaticImageClone(it);
     722                 :       }
     723               0 :       break;
     724                 :     default:
     725               0 :       break;
     726                 :   }
     727                 : 
     728               0 :   it.forget(aResult);
     729               0 :   return NS_OK;
     730                 : }
     731                 : 
     732                 : nsresult
     733               0 : nsHTMLInputElement::BeforeSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
     734                 :                                   const nsAttrValueOrString* aValue,
     735                 :                                   bool aNotify)
     736                 : {
     737               0 :   if (aNameSpaceID == kNameSpaceID_None) {
     738                 :     //
     739                 :     // When name or type changes, radio should be removed from radio group.
     740                 :     // (type changes are handled in the form itself currently)
     741                 :     // If the parser is not done creating the radio, we also should not do it.
     742                 :     //
     743               0 :     if ((aName == nsGkAtoms::name ||
     744               0 :          (aName == nsGkAtoms::type && !mForm)) &&
     745                 :         mType == NS_FORM_INPUT_RADIO &&
     746               0 :         (mForm || !mParserCreating)) {
     747               0 :       WillRemoveFromRadioGroup();
     748               0 :     } else if (aNotify && aName == nsGkAtoms::src &&
     749                 :                mType == NS_FORM_INPUT_IMAGE) {
     750               0 :       if (aValue) {
     751               0 :         LoadImage(aValue->String(), true, aNotify);
     752                 :       } else {
     753                 :         // Null value means the attr got unset; drop the image
     754               0 :         CancelImageRequests(aNotify);
     755                 :       }
     756               0 :     } else if (aNotify && aName == nsGkAtoms::disabled) {
     757               0 :       mDisabledChanged = true;
     758                 :     }
     759                 :   }
     760                 : 
     761                 :   return nsGenericHTMLFormElement::BeforeSetAttr(aNameSpaceID, aName,
     762               0 :                                                  aValue, aNotify);
     763                 : }
     764                 : 
     765                 : nsresult
     766               0 : nsHTMLInputElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
     767                 :                                  const nsAttrValue* aValue, bool aNotify)
     768                 : {
     769               0 :   if (aNameSpaceID == kNameSpaceID_None) {
     770                 :     //
     771                 :     // When name or type changes, radio should be added to radio group.
     772                 :     // (type changes are handled in the form itself currently)
     773                 :     // If the parser is not done creating the radio, we also should not do it.
     774                 :     //
     775               0 :     if ((aName == nsGkAtoms::name ||
     776               0 :          (aName == nsGkAtoms::type && !mForm)) &&
     777                 :         mType == NS_FORM_INPUT_RADIO &&
     778               0 :         (mForm || !mParserCreating)) {
     779               0 :       AddedToRadioGroup();
     780               0 :       UpdateValueMissingValidityStateForRadio(false);
     781                 :     }
     782                 : 
     783                 :     // If @value is changed and BF_VALUE_CHANGED is false, @value is the value
     784                 :     // of the element so, if the value of the element is different than @value,
     785                 :     // we have to re-set it. This is only the case when GetValueMode() returns
     786                 :     // VALUE_MODE_VALUE.
     787               0 :     if (aName == nsGkAtoms::value &&
     788               0 :         !mValueChanged && GetValueMode() == VALUE_MODE_VALUE) {
     789               0 :       SetDefaultValueAsValue();
     790                 :     }
     791                 : 
     792                 :     //
     793                 :     // Checked must be set no matter what type of control it is, since
     794                 :     // mChecked must reflect the new value
     795               0 :     if (aName == nsGkAtoms::checked && !mCheckedChanged) {
     796                 :       // Delay setting checked if the parser is creating this element (wait
     797                 :       // until everything is set)
     798               0 :       if (mParserCreating) {
     799               0 :         mShouldInitChecked = true;
     800                 :       } else {
     801               0 :         DoSetChecked(DefaultChecked(), true, true);
     802               0 :         SetCheckedChanged(false);
     803                 :       }
     804                 :     }
     805                 : 
     806               0 :     if (aName == nsGkAtoms::type) {
     807               0 :       if (!aValue) {
     808                 :         // We're now a text input.  Note that we have to handle this manually,
     809                 :         // since removing an attribute (which is what happened, since aValue is
     810                 :         // null) doesn't call ParseAttribute.
     811               0 :         HandleTypeChange(kInputDefaultType->value);
     812                 :       }
     813                 : 
     814               0 :       UpdateBarredFromConstraintValidation();
     815                 : 
     816               0 :       if (mType != NS_FORM_INPUT_IMAGE) {
     817                 :         // We're no longer an image input.  Cancel our image requests, if we have
     818                 :         // any.  Note that doing this when we already weren't an image is ok --
     819                 :         // just does nothing.
     820               0 :         CancelImageRequests(aNotify);
     821               0 :       } else if (aNotify) {
     822                 :         // We just got switched to be an image input; we should see
     823                 :         // whether we have an image to load;
     824               0 :         nsAutoString src;
     825               0 :         if (GetAttr(kNameSpaceID_None, nsGkAtoms::src, src)) {
     826               0 :           LoadImage(src, false, aNotify);
     827                 :         }
     828                 :       }
     829                 :     }
     830                 : 
     831               0 :     if (mType == NS_FORM_INPUT_RADIO && aName == nsGkAtoms::required) {
     832               0 :       nsCOMPtr<nsIRadioGroupContainer> container = GetRadioGroupContainer();
     833                 : 
     834               0 :       if (container) {
     835               0 :         nsAutoString name;
     836               0 :         GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
     837               0 :         container->RadioRequiredChanged(name, this);
     838                 :       }
     839                 :     }
     840                 : 
     841               0 :     if (aName == nsGkAtoms::required || aName == nsGkAtoms::disabled ||
     842                 :         aName == nsGkAtoms::readonly) {
     843               0 :       UpdateValueMissingValidityState();
     844                 : 
     845                 :       // This *has* to be called *after* validity has changed.
     846               0 :       if (aName == nsGkAtoms::readonly || aName == nsGkAtoms::disabled) {
     847               0 :         UpdateBarredFromConstraintValidation();
     848                 :       }
     849               0 :     } else if (MaxLengthApplies() && aName == nsGkAtoms::maxlength) {
     850               0 :       UpdateTooLongValidityState();
     851               0 :     } else if (aName == nsGkAtoms::pattern) {
     852               0 :       UpdatePatternMismatchValidityState();
     853               0 :     } else if (aName == nsGkAtoms::multiple) {
     854               0 :       UpdateTypeMismatchValidityState();
     855                 :     }
     856                 : 
     857               0 :     UpdateEditableState(aNotify);
     858               0 :     UpdateState(aNotify);
     859                 :   }
     860                 : 
     861                 :   return nsGenericHTMLFormElement::AfterSetAttr(aNameSpaceID, aName,
     862               0 :                                                 aValue, aNotify);
     863                 : }
     864                 : 
     865                 : // nsIDOMHTMLInputElement
     866                 : 
     867                 : NS_IMETHODIMP
     868               0 : nsHTMLInputElement::GetForm(nsIDOMHTMLFormElement** aForm)
     869                 : {
     870               0 :   return nsGenericHTMLFormElement::GetForm(aForm);
     871                 : }
     872                 : 
     873               1 : NS_IMPL_STRING_ATTR(nsHTMLInputElement, DefaultValue, value)
     874               0 : NS_IMPL_BOOL_ATTR(nsHTMLInputElement, DefaultChecked, checked)
     875               0 : NS_IMPL_STRING_ATTR(nsHTMLInputElement, Accept, accept)
     876               0 : NS_IMPL_STRING_ATTR(nsHTMLInputElement, Align, align)
     877               0 : NS_IMPL_STRING_ATTR(nsHTMLInputElement, Alt, alt)
     878               0 : NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLInputElement, Autocomplete, autocomplete,
     879                 :                                 kInputDefaultAutocomplete->tag)
     880               0 : NS_IMPL_BOOL_ATTR(nsHTMLInputElement, Autofocus, autofocus)
     881                 : //NS_IMPL_BOOL_ATTR(nsHTMLInputElement, Checked, checked)
     882               0 : NS_IMPL_BOOL_ATTR(nsHTMLInputElement, Disabled, disabled)
     883               0 : NS_IMPL_ACTION_ATTR(nsHTMLInputElement, FormAction, formaction)
     884               0 : NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLInputElement, FormEnctype, formenctype,
     885                 :                                 kFormDefaultEnctype->tag)
     886               0 : NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLInputElement, FormMethod, formmethod,
     887                 :                                 kFormDefaultMethod->tag)
     888               0 : NS_IMPL_BOOL_ATTR(nsHTMLInputElement, FormNoValidate, formnovalidate)
     889               0 : NS_IMPL_STRING_ATTR(nsHTMLInputElement, FormTarget, formtarget)
     890               0 : NS_IMPL_BOOL_ATTR(nsHTMLInputElement, Multiple, multiple)
     891               0 : NS_IMPL_NON_NEGATIVE_INT_ATTR(nsHTMLInputElement, MaxLength, maxlength)
     892               0 : NS_IMPL_STRING_ATTR(nsHTMLInputElement, Name, name)
     893               0 : NS_IMPL_BOOL_ATTR(nsHTMLInputElement, ReadOnly, readonly)
     894               0 : NS_IMPL_BOOL_ATTR(nsHTMLInputElement, Required, required)
     895               0 : NS_IMPL_URI_ATTR(nsHTMLInputElement, Src, src)
     896               0 : NS_IMPL_INT_ATTR(nsHTMLInputElement, TabIndex, tabindex)
     897               0 : NS_IMPL_STRING_ATTR(nsHTMLInputElement, UseMap, usemap)
     898                 : //NS_IMPL_STRING_ATTR(nsHTMLInputElement, Value, value)
     899               0 : NS_IMPL_UINT_ATTR_NON_ZERO_DEFAULT_VALUE(nsHTMLInputElement, Size, size, DEFAULT_COLS)
     900               0 : NS_IMPL_STRING_ATTR(nsHTMLInputElement, Pattern, pattern)
     901               0 : NS_IMPL_STRING_ATTR(nsHTMLInputElement, Placeholder, placeholder)
     902               0 : NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLInputElement, Type, type,
     903                 :                                 kInputDefaultType->tag)
     904                 : 
     905                 : NS_IMETHODIMP
     906               0 : nsHTMLInputElement::GetIndeterminate(bool* aValue)
     907                 : {
     908               0 :   *aValue = mIndeterminate;
     909               0 :   return NS_OK;
     910                 : }
     911                 : 
     912                 : nsresult
     913               0 : nsHTMLInputElement::SetIndeterminateInternal(bool aValue,
     914                 :                                              bool aShouldInvalidate)
     915                 : {
     916               0 :   mIndeterminate = aValue;
     917                 : 
     918               0 :   if (aShouldInvalidate) {
     919                 :     // Repaint the frame
     920               0 :     nsIFrame* frame = GetPrimaryFrame();
     921               0 :     if (frame)
     922               0 :       frame->InvalidateFrameSubtree();
     923                 :   }
     924                 : 
     925               0 :   UpdateState(true);
     926                 : 
     927               0 :   return NS_OK;
     928                 : }
     929                 : 
     930                 : NS_IMETHODIMP
     931               0 : nsHTMLInputElement::SetIndeterminate(bool aValue)
     932                 : {
     933               0 :   return SetIndeterminateInternal(aValue, true);
     934                 : }
     935                 : 
     936                 : NS_IMETHODIMP
     937               1 : nsHTMLInputElement::GetValue(nsAString& aValue)
     938                 : {
     939               1 :   return GetValueInternal(aValue);
     940                 : }
     941                 : 
     942                 : nsresult
     943               1 : nsHTMLInputElement::GetValueInternal(nsAString& aValue) const
     944                 : {
     945               1 :   switch (GetValueMode()) {
     946                 :     case VALUE_MODE_VALUE:
     947               1 :       mInputData.mState->GetValue(aValue, true);
     948               1 :       return NS_OK;
     949                 : 
     950                 :     case VALUE_MODE_FILENAME:
     951               0 :       if (nsContentUtils::CallerHasUniversalXPConnect()) {
     952               0 :         if (mFiles.Count()) {
     953               0 :           return mFiles[0]->GetMozFullPath(aValue);
     954                 :         }
     955                 :         else {
     956               0 :           aValue.Truncate();
     957                 :         }
     958                 :       } else {
     959                 :         // Just return the leaf name
     960               0 :         if (mFiles.Count() == 0 || NS_FAILED(mFiles[0]->GetName(aValue))) {
     961               0 :           aValue.Truncate();
     962                 :         }
     963                 :       }
     964                 : 
     965               0 :       return NS_OK;
     966                 : 
     967                 :     case VALUE_MODE_DEFAULT:
     968                 :       // Treat defaultValue as value.
     969               0 :       GetAttr(kNameSpaceID_None, nsGkAtoms::value, aValue);
     970               0 :       return NS_OK;
     971                 : 
     972                 :     case VALUE_MODE_DEFAULT_ON:
     973                 :       // Treat default value as value and returns "on" if no value.
     974               0 :       if (!GetAttr(kNameSpaceID_None, nsGkAtoms::value, aValue)) {
     975               0 :         aValue.AssignLiteral("on");
     976                 :       }
     977               0 :       return NS_OK;
     978                 :   }
     979                 : 
     980                 :   // This return statement is required for some compilers.
     981                 :   return NS_OK;
     982                 : }
     983                 : 
     984                 : bool
     985               0 : nsHTMLInputElement::IsValueEmpty() const
     986                 : {
     987               0 :   nsAutoString value;
     988               0 :   GetValueInternal(value);
     989                 : 
     990               0 :   return value.IsEmpty();
     991                 : }
     992                 : 
     993                 : NS_IMETHODIMP 
     994               0 : nsHTMLInputElement::SetValue(const nsAString& aValue)
     995                 : {
     996                 :   // check security.  Note that setting the value to the empty string is always
     997                 :   // OK and gives pages a way to clear a file input if necessary.
     998               0 :   if (mType == NS_FORM_INPUT_FILE) {
     999               0 :     if (!aValue.IsEmpty()) {
    1000               0 :       if (!nsContentUtils::CallerHasUniversalXPConnect()) {
    1001                 :         // setting the value of a "FILE" input widget requires the
    1002                 :         // UniversalXPConnect privilege
    1003               0 :         return NS_ERROR_DOM_SECURITY_ERR;
    1004                 :       }
    1005               0 :       const PRUnichar *name = PromiseFlatString(aValue).get();
    1006               0 :       return MozSetFileNameArray(&name, 1);
    1007                 :     }
    1008                 :     else {
    1009               0 :       ClearFiles(true);
    1010                 :     }
    1011                 :   }
    1012                 :   else {
    1013               0 :     SetValueInternal(aValue, false, true);
    1014                 :   }
    1015                 : 
    1016               0 :   return NS_OK;
    1017                 : }
    1018                 : 
    1019                 : NS_IMETHODIMP
    1020               0 : nsHTMLInputElement::GetList(nsIDOMHTMLElement** aValue)
    1021                 : {
    1022               0 :   *aValue = nsnull;
    1023                 : 
    1024               0 :   nsAutoString dataListId;
    1025               0 :   GetAttr(kNameSpaceID_None, nsGkAtoms::list, dataListId);
    1026               0 :   if (dataListId.IsEmpty()) {
    1027               0 :     return NS_OK;
    1028                 :   }
    1029                 : 
    1030               0 :   nsIDocument* doc = GetCurrentDoc();
    1031               0 :   if (!doc) {
    1032               0 :     return NS_OK;
    1033                 :   }
    1034                 : 
    1035               0 :   Element* element = doc->GetElementById(dataListId);
    1036               0 :   if (!element || !element->IsHTML(nsGkAtoms::datalist)) {
    1037               0 :     return NS_OK;
    1038                 :   }
    1039                 : 
    1040               0 :   CallQueryInterface(element, aValue);
    1041               0 :   return NS_OK;
    1042                 : }
    1043                 : 
    1044                 : NS_IMETHODIMP 
    1045               0 : nsHTMLInputElement::MozGetFileNameArray(PRUint32 *aLength, PRUnichar ***aFileNames)
    1046                 : {
    1047               0 :   if (!nsContentUtils::CallerHasUniversalXPConnect()) {
    1048                 :     // Since this function returns full paths it's important that normal pages
    1049                 :     // can't call it.
    1050               0 :     return NS_ERROR_DOM_SECURITY_ERR;
    1051                 :   }
    1052                 : 
    1053               0 :   *aLength = mFiles.Count();
    1054                 :   PRUnichar **ret =
    1055               0 :     static_cast<PRUnichar **>(NS_Alloc(mFiles.Count() * sizeof(PRUnichar*)));
    1056               0 :   if (!ret) {
    1057               0 :     return NS_ERROR_OUT_OF_MEMORY;
    1058                 :   }
    1059                 : 
    1060               0 :   for (PRInt32 i = 0; i < mFiles.Count(); i++) {
    1061               0 :     nsString str;
    1062               0 :     mFiles[i]->GetMozFullPathInternal(str);
    1063               0 :     ret[i] = NS_strdup(str.get());
    1064                 :   }
    1065                 : 
    1066               0 :   *aFileNames = ret;
    1067                 : 
    1068               0 :   return NS_OK;
    1069                 : }
    1070                 : 
    1071                 : NS_IMETHODIMP 
    1072               0 : nsHTMLInputElement::MozSetFileNameArray(const PRUnichar **aFileNames, PRUint32 aLength)
    1073                 : {
    1074               0 :   if (!nsContentUtils::CallerHasUniversalXPConnect()) {
    1075                 :     // setting the value of a "FILE" input widget requires the
    1076                 :     // UniversalXPConnect privilege
    1077               0 :     return NS_ERROR_DOM_SECURITY_ERR;
    1078                 :   }
    1079                 : 
    1080               0 :   nsCOMArray<nsIDOMFile> files;
    1081               0 :   for (PRUint32 i = 0; i < aLength; ++i) {
    1082               0 :     nsCOMPtr<nsIFile> file;
    1083               0 :     if (StringBeginsWith(nsDependentString(aFileNames[i]),
    1084               0 :                          NS_LITERAL_STRING("file:"),
    1085               0 :                          nsASCIICaseInsensitiveStringComparator())) {
    1086                 :       // Converts the URL string into the corresponding nsIFile if possible
    1087                 :       // A local file will be created if the URL string begins with file://
    1088               0 :       NS_GetFileFromURLSpec(NS_ConvertUTF16toUTF8(aFileNames[i]),
    1089               0 :                             getter_AddRefs(file));
    1090                 :     }
    1091                 : 
    1092               0 :     if (!file) {
    1093                 :       // this is no "file://", try as local file
    1094               0 :       nsCOMPtr<nsILocalFile> localFile;
    1095               0 :       NS_NewLocalFile(nsDependentString(aFileNames[i]),
    1096               0 :                       false, getter_AddRefs(localFile));
    1097               0 :       file = do_QueryInterface(localFile);
    1098                 :     }
    1099                 : 
    1100               0 :     if (file) {
    1101               0 :       nsCOMPtr<nsIDOMFile> domFile = new nsDOMFileFile(file);
    1102               0 :       files.AppendObject(domFile);
    1103                 :     } else {
    1104               0 :       continue; // Not much we can do if the file doesn't exist
    1105                 :     }
    1106                 : 
    1107                 :   }
    1108                 : 
    1109               0 :   SetFiles(files, true);
    1110                 : 
    1111               0 :   return NS_OK;
    1112                 : }
    1113                 : 
    1114                 : NS_IMETHODIMP
    1115               0 : nsHTMLInputElement::MozIsTextField(bool aExcludePassword, bool* aResult)
    1116                 : {
    1117               0 :   *aResult = IsSingleLineTextControl(aExcludePassword);
    1118                 : 
    1119               0 :   return NS_OK;
    1120                 : }
    1121                 : 
    1122                 : NS_IMETHODIMP 
    1123               0 : nsHTMLInputElement::SetUserInput(const nsAString& aValue)
    1124                 : {
    1125               0 :   if (!nsContentUtils::IsCallerTrustedForWrite()) {
    1126               0 :     return NS_ERROR_DOM_SECURITY_ERR;
    1127                 :   }
    1128                 : 
    1129               0 :   if (mType == NS_FORM_INPUT_FILE)
    1130                 :   {
    1131               0 :     const PRUnichar* name = PromiseFlatString(aValue).get();
    1132               0 :     return MozSetFileNameArray(&name, 1);
    1133                 :   } else {
    1134               0 :     SetValueInternal(aValue, true, true);
    1135                 :   }
    1136                 : 
    1137                 :   return nsContentUtils::DispatchTrustedEvent(OwnerDoc(),
    1138                 :                                               static_cast<nsIDOMHTMLInputElement*>(this),
    1139               0 :                                               NS_LITERAL_STRING("input"), true,
    1140               0 :                                               true);
    1141                 : }
    1142                 : 
    1143                 : NS_IMETHODIMP_(nsIEditor*)
    1144               0 : nsHTMLInputElement::GetTextEditor()
    1145                 : {
    1146               0 :   nsTextEditorState *state = GetEditorState();
    1147               0 :   if (state) {
    1148               0 :     return state->GetEditor();
    1149                 :   }
    1150               0 :   return nsnull;
    1151                 : }
    1152                 : 
    1153                 : NS_IMETHODIMP_(nsISelectionController*)
    1154               0 : nsHTMLInputElement::GetSelectionController()
    1155                 : {
    1156               0 :   nsTextEditorState *state = GetEditorState();
    1157               0 :   if (state) {
    1158               0 :     return state->GetSelectionController();
    1159                 :   }
    1160               0 :   return nsnull;
    1161                 : }
    1162                 : 
    1163                 : nsFrameSelection*
    1164               0 : nsHTMLInputElement::GetConstFrameSelection()
    1165                 : {
    1166               0 :   nsTextEditorState *state = GetEditorState();
    1167               0 :   if (state) {
    1168               0 :     return state->GetConstFrameSelection();
    1169                 :   }
    1170               0 :   return nsnull;
    1171                 : }
    1172                 : 
    1173                 : NS_IMETHODIMP
    1174               0 : nsHTMLInputElement::BindToFrame(nsTextControlFrame* aFrame)
    1175                 : {
    1176               0 :   nsTextEditorState *state = GetEditorState();
    1177               0 :   if (state) {
    1178               0 :     return state->BindToFrame(aFrame);
    1179                 :   }
    1180               0 :   return NS_ERROR_FAILURE;
    1181                 : }
    1182                 : 
    1183                 : NS_IMETHODIMP_(void)
    1184               1 : nsHTMLInputElement::UnbindFromFrame(nsTextControlFrame* aFrame)
    1185                 : {
    1186               1 :   nsTextEditorState *state = GetEditorState();
    1187               1 :   if (state && aFrame) {
    1188               0 :     state->UnbindFromFrame(aFrame);
    1189                 :   }
    1190               1 : }
    1191                 : 
    1192                 : NS_IMETHODIMP
    1193               0 : nsHTMLInputElement::CreateEditor()
    1194                 : {
    1195               0 :   nsTextEditorState *state = GetEditorState();
    1196               0 :   if (state) {
    1197               0 :     return state->PrepareEditor();
    1198                 :   }
    1199               0 :   return NS_ERROR_FAILURE;
    1200                 : }
    1201                 : 
    1202                 : NS_IMETHODIMP_(nsIContent*)
    1203               0 : nsHTMLInputElement::GetRootEditorNode()
    1204                 : {
    1205               0 :   nsTextEditorState *state = GetEditorState();
    1206               0 :   if (state) {
    1207               0 :     return state->GetRootNode();
    1208                 :   }
    1209               0 :   return nsnull;
    1210                 : }
    1211                 : 
    1212                 : NS_IMETHODIMP_(nsIContent*)
    1213               0 : nsHTMLInputElement::CreatePlaceholderNode()
    1214                 : {
    1215               0 :   nsTextEditorState *state = GetEditorState();
    1216               0 :   if (state) {
    1217               0 :     NS_ENSURE_SUCCESS(state->CreatePlaceholderNode(), nsnull);
    1218               0 :     return state->GetPlaceholderNode();
    1219                 :   }
    1220               0 :   return nsnull;
    1221                 : }
    1222                 : 
    1223                 : NS_IMETHODIMP_(nsIContent*)
    1224               0 : nsHTMLInputElement::GetPlaceholderNode()
    1225                 : {
    1226               0 :   nsTextEditorState *state = GetEditorState();
    1227               0 :   if (state) {
    1228               0 :     return state->GetPlaceholderNode();
    1229                 :   }
    1230               0 :   return nsnull;
    1231                 : }
    1232                 : 
    1233                 : NS_IMETHODIMP_(void)
    1234               0 : nsHTMLInputElement::UpdatePlaceholderText(bool aNotify)
    1235                 : {
    1236               0 :   nsTextEditorState *state = GetEditorState();
    1237               0 :   if (state) {
    1238               0 :     state->UpdatePlaceholderText(aNotify);
    1239                 :   }
    1240               0 : }
    1241                 : 
    1242                 : NS_IMETHODIMP_(void)
    1243               0 : nsHTMLInputElement::SetPlaceholderClass(bool aVisible, bool aNotify)
    1244                 : {
    1245               0 :   nsTextEditorState *state = GetEditorState();
    1246               0 :   if (state) {
    1247               0 :     state->SetPlaceholderClass(aVisible, aNotify);
    1248                 :   }
    1249               0 : }
    1250                 : 
    1251                 : void
    1252               0 : nsHTMLInputElement::GetDisplayFileName(nsAString& aValue) const
    1253                 : {
    1254               0 :   if (OwnerDoc()->IsStaticDocument()) {
    1255               0 :     aValue = mStaticDocFileList;
    1256               0 :     return;
    1257                 :   }
    1258                 : 
    1259               0 :   aValue.Truncate();
    1260               0 :   for (PRInt32 i = 0; i < mFiles.Count(); ++i) {
    1261               0 :     nsString str;
    1262               0 :     mFiles[i]->GetMozFullPathInternal(str);
    1263               0 :     if (i == 0) {
    1264               0 :       aValue.Append(str);
    1265                 :     }
    1266                 :     else {
    1267               0 :       aValue.Append(NS_LITERAL_STRING(", ") + str);
    1268                 :     }
    1269                 :   }
    1270                 : }
    1271                 : 
    1272                 : void
    1273               0 : nsHTMLInputElement::SetFiles(const nsCOMArray<nsIDOMFile>& aFiles,
    1274                 :                              bool aSetValueChanged)
    1275                 : {
    1276               0 :   mFiles.Clear();
    1277               0 :   mFiles.AppendObjects(aFiles);
    1278                 : 
    1279               0 :   AfterSetFiles(aSetValueChanged);
    1280               0 : }
    1281                 : 
    1282                 : void
    1283               0 : nsHTMLInputElement::SetFiles(nsIDOMFileList* aFiles,
    1284                 :                              bool aSetValueChanged)
    1285                 : {
    1286               0 :   mFiles.Clear();
    1287                 : 
    1288               0 :   if (aFiles) {
    1289                 :     PRUint32 listLength;
    1290               0 :     aFiles->GetLength(&listLength);
    1291               0 :     for (PRUint32 i = 0; i < listLength; i++) {
    1292               0 :       nsCOMPtr<nsIDOMFile> file;
    1293               0 :       aFiles->Item(i, getter_AddRefs(file));
    1294               0 :       mFiles.AppendObject(file);
    1295                 :     }
    1296                 :   }
    1297                 : 
    1298               0 :   AfterSetFiles(aSetValueChanged);
    1299               0 : }
    1300                 : 
    1301                 : void
    1302               0 : nsHTMLInputElement::AfterSetFiles(bool aSetValueChanged)
    1303                 : {
    1304                 :   // No need to flush here, if there's no frame at this point we
    1305                 :   // don't need to force creation of one just to tell it about this
    1306                 :   // new value.  We just want the display to update as needed.
    1307               0 :   nsIFormControlFrame* formControlFrame = GetFormControlFrame(false);
    1308               0 :   if (formControlFrame) {
    1309               0 :     nsAutoString readableValue;
    1310               0 :     GetDisplayFileName(readableValue);
    1311               0 :     formControlFrame->SetFormProperty(nsGkAtoms::value, readableValue);
    1312                 :   }
    1313                 : 
    1314               0 :   UpdateFileList();
    1315                 : 
    1316               0 :   if (aSetValueChanged) {
    1317               0 :     SetValueChanged(true);
    1318                 :   }
    1319                 : 
    1320               0 :   UpdateAllValidityStates(true);
    1321               0 : }
    1322                 : 
    1323                 : const nsCOMArray<nsIDOMFile>&
    1324               0 : nsHTMLInputElement::GetFiles() const
    1325                 : {
    1326               0 :   return mFiles;
    1327                 : }
    1328                 : 
    1329                 : nsresult
    1330               0 : nsHTMLInputElement::UpdateFileList()
    1331                 : {
    1332               0 :   if (mFileList) {
    1333               0 :     mFileList->Clear();
    1334                 : 
    1335               0 :     const nsCOMArray<nsIDOMFile>& files = GetFiles();
    1336               0 :     for (PRInt32 i = 0; i < files.Count(); ++i) {
    1337               0 :       if (!mFileList->Append(files[i])) {
    1338               0 :         return NS_ERROR_FAILURE;
    1339                 :       }
    1340                 :     }
    1341                 :   }
    1342                 : 
    1343               0 :   return NS_OK;
    1344                 : }
    1345                 : 
    1346                 : nsresult
    1347               1 : nsHTMLInputElement::SetValueInternal(const nsAString& aValue,
    1348                 :                                      bool aUserInput,
    1349                 :                                      bool aSetValueChanged)
    1350                 : {
    1351               1 :   NS_PRECONDITION(GetValueMode() != VALUE_MODE_FILENAME,
    1352                 :                   "Don't call SetValueInternal for file inputs");
    1353                 : 
    1354               1 :   switch (GetValueMode()) {
    1355                 :     case VALUE_MODE_VALUE:
    1356                 :     {
    1357                 :       // At the moment, only single line text control have to sanitize their value
    1358                 :       // Because we have to create a new string for that, we should prevent doing
    1359                 :       // it if it's useless.
    1360               2 :       nsAutoString value(aValue);
    1361                 : 
    1362               1 :       if (!mParserCreating) {
    1363               1 :         SanitizeValue(value);
    1364                 :       }
    1365                 : 
    1366               1 :       if (aSetValueChanged) {
    1367               0 :         SetValueChanged(true);
    1368                 :       }
    1369                 : 
    1370               1 :       mInputData.mState->SetValue(value, aUserInput);
    1371                 : 
    1372                 :       // This call might be useless in some situations because if the element is
    1373                 :       // a single line text control, nsTextEditorState::SetValue will call
    1374                 :       // nsHTMLInputElement::OnValueChanged which is going to call UpdateState()
    1375                 :       // if the element is focused. This bug 665547.
    1376               2 :       if (PlaceholderApplies() &&
    1377               1 :           HasAttr(kNameSpaceID_None, nsGkAtoms::placeholder)) {
    1378               0 :         UpdateState(true);
    1379                 :       }
    1380                 : 
    1381               1 :       return NS_OK;
    1382                 :     }
    1383                 : 
    1384                 :     case VALUE_MODE_DEFAULT:
    1385                 :     case VALUE_MODE_DEFAULT_ON:
    1386                 :       // If the value of a hidden input was changed, we mark it changed so that we
    1387                 :       // will know we need to save / restore the value.  Yes, we are overloading
    1388                 :       // the meaning of ValueChanged just a teensy bit to save a measly byte of
    1389                 :       // storage space in nsHTMLInputElement.  Yes, you are free to make a new flag,
    1390                 :       // NEED_TO_SAVE_VALUE, at such time as mBitField becomes a 16-bit value.
    1391               0 :       if (mType == NS_FORM_INPUT_HIDDEN) {
    1392               0 :         SetValueChanged(true);
    1393                 :       }
    1394                 : 
    1395                 :       // Treat value == defaultValue for other input elements.
    1396                 :       return nsGenericHTMLFormElement::SetAttr(kNameSpaceID_None,
    1397                 :                                                nsGkAtoms::value, aValue,
    1398               0 :                                                true);
    1399                 : 
    1400                 :     case VALUE_MODE_FILENAME:
    1401               0 :       return NS_ERROR_UNEXPECTED;
    1402                 :   }
    1403                 : 
    1404                 :   // This return statement is required for some compilers.
    1405                 :   return NS_OK;
    1406                 : }
    1407                 : 
    1408                 : NS_IMETHODIMP
    1409               0 : nsHTMLInputElement::SetValueChanged(bool aValueChanged)
    1410                 : {
    1411               0 :   bool valueChangedBefore = mValueChanged;
    1412                 : 
    1413               0 :   mValueChanged = aValueChanged;
    1414                 : 
    1415               0 :   if (valueChangedBefore != aValueChanged) {
    1416               0 :     UpdateState(true);
    1417                 :   }
    1418                 : 
    1419               0 :   return NS_OK;
    1420                 : }
    1421                 : 
    1422                 : NS_IMETHODIMP 
    1423               0 : nsHTMLInputElement::GetChecked(bool* aChecked)
    1424                 : {
    1425               0 :   *aChecked = mChecked;
    1426               0 :   return NS_OK;
    1427                 : }
    1428                 : 
    1429                 : void
    1430               0 : nsHTMLInputElement::SetCheckedChanged(bool aCheckedChanged)
    1431                 : {
    1432               0 :   DoSetCheckedChanged(aCheckedChanged, true);
    1433               0 : }
    1434                 : 
    1435                 : void
    1436               0 : nsHTMLInputElement::DoSetCheckedChanged(bool aCheckedChanged,
    1437                 :                                         bool aNotify)
    1438                 : {
    1439               0 :   if (mType == NS_FORM_INPUT_RADIO) {
    1440               0 :     if (mCheckedChanged != aCheckedChanged) {
    1441                 :       nsCOMPtr<nsIRadioVisitor> visitor =
    1442               0 :         new nsRadioSetCheckedChangedVisitor(aCheckedChanged);
    1443               0 :       VisitGroup(visitor, aNotify);
    1444                 :     }
    1445                 :   } else {
    1446               0 :     SetCheckedChangedInternal(aCheckedChanged);
    1447                 :   }
    1448               0 : }
    1449                 : 
    1450                 : void
    1451               0 : nsHTMLInputElement::SetCheckedChangedInternal(bool aCheckedChanged)
    1452                 : {
    1453               0 :   bool checkedChangedBefore = mCheckedChanged;
    1454                 : 
    1455               0 :   mCheckedChanged = aCheckedChanged;
    1456                 : 
    1457                 :   // This method can't be called when we are not authorized to notify
    1458                 :   // so we do not need a aNotify parameter.
    1459               0 :   if (checkedChangedBefore != aCheckedChanged) {
    1460               0 :     UpdateState(true);
    1461                 :   }
    1462               0 : }
    1463                 : 
    1464                 : NS_IMETHODIMP
    1465               0 : nsHTMLInputElement::SetChecked(bool aChecked)
    1466                 : {
    1467               0 :   return DoSetChecked(aChecked, true, true);
    1468                 : }
    1469                 : 
    1470                 : nsresult
    1471               0 : nsHTMLInputElement::DoSetChecked(bool aChecked, bool aNotify,
    1472                 :                                  bool aSetValueChanged)
    1473                 : {
    1474                 :   // If the user or JS attempts to set checked, whether it actually changes the
    1475                 :   // value or not, we say the value was changed so that defaultValue don't
    1476                 :   // affect it no more.
    1477               0 :   if (aSetValueChanged) {
    1478               0 :     DoSetCheckedChanged(true, aNotify);
    1479                 :   }
    1480                 : 
    1481                 :   // Don't do anything if we're not changing whether it's checked (it would
    1482                 :   // screw up state actually, especially when you are setting radio button to
    1483                 :   // false)
    1484               0 :   if (mChecked == aChecked) {
    1485               0 :     return NS_OK;
    1486                 :   }
    1487                 : 
    1488                 :   // Set checked
    1489               0 :   if (mType != NS_FORM_INPUT_RADIO) {
    1490               0 :     SetCheckedInternal(aChecked, aNotify);
    1491               0 :     return NS_OK;
    1492                 :   }
    1493                 : 
    1494                 :   // For radio button, we need to do some extra fun stuff
    1495               0 :   if (aChecked) {
    1496               0 :     return RadioSetChecked(aNotify);
    1497                 :   }
    1498                 : 
    1499               0 :   nsIRadioGroupContainer* container = GetRadioGroupContainer();
    1500               0 :   if (container) {
    1501               0 :     nsAutoString name;
    1502               0 :     GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
    1503               0 :     container->SetCurrentRadioButton(name, nsnull);
    1504                 :   }
    1505                 :   // SetCheckedInternal is going to ask all radios to update their
    1506                 :   // validity state. We have to be sure the radio group container knows
    1507                 :   // the currently selected radio.
    1508               0 :   SetCheckedInternal(false, aNotify);
    1509               0 :   return NS_OK;
    1510                 : }
    1511                 : 
    1512                 : nsresult
    1513               0 : nsHTMLInputElement::RadioSetChecked(bool aNotify)
    1514                 : {
    1515                 :   // Find the selected radio button so we can deselect it
    1516               0 :   nsCOMPtr<nsIDOMHTMLInputElement> currentlySelected = GetSelectedRadioButton();
    1517                 : 
    1518                 :   // Deselect the currently selected radio button
    1519               0 :   if (currentlySelected) {
    1520                 :     // Pass true for the aNotify parameter since the currently selected
    1521                 :     // button is already in the document.
    1522               0 :     static_cast<nsHTMLInputElement*>(currentlySelected.get())
    1523               0 :       ->SetCheckedInternal(false, true);
    1524                 :   }
    1525                 : 
    1526                 :   // Let the group know that we are now the One True Radio Button
    1527               0 :   nsresult rv = NS_OK;
    1528               0 :   nsIRadioGroupContainer* container = GetRadioGroupContainer();
    1529               0 :   if (container) {
    1530               0 :     nsAutoString name;
    1531               0 :     GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
    1532               0 :     rv = container->SetCurrentRadioButton(name, this);
    1533                 :   }
    1534                 : 
    1535                 :   // SetCheckedInternal is going to ask all radios to update their
    1536                 :   // validity state. We have to be sure the radio group container knows
    1537                 :   // the currently selected radio.
    1538               0 :   if (NS_SUCCEEDED(rv)) {
    1539               0 :     SetCheckedInternal(true, aNotify);
    1540                 :   }
    1541                 : 
    1542               0 :   return rv;
    1543                 : }
    1544                 : 
    1545                 : nsIRadioGroupContainer*
    1546               0 : nsHTMLInputElement::GetRadioGroupContainer() const
    1547                 : {
    1548               0 :   NS_ASSERTION(mType == NS_FORM_INPUT_RADIO,
    1549                 :                "GetRadioGroupContainer should only be called when type='radio'");
    1550                 : 
    1551               0 :   nsAutoString name;
    1552               0 :   GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
    1553                 : 
    1554               0 :   if (name.IsEmpty()) {
    1555               0 :     return nsnull;
    1556                 :   }
    1557                 : 
    1558               0 :   if (mForm) {
    1559               0 :     return mForm;
    1560                 :   }
    1561                 : 
    1562               0 :   return static_cast<nsDocument*>(GetCurrentDoc());
    1563                 : }
    1564                 : 
    1565                 : already_AddRefed<nsIDOMHTMLInputElement>
    1566               0 : nsHTMLInputElement::GetSelectedRadioButton()
    1567                 : {
    1568               0 :   nsIRadioGroupContainer* container = GetRadioGroupContainer();
    1569               0 :   if (!container) {
    1570               0 :     return nsnull;
    1571                 :   }
    1572                 : 
    1573               0 :   nsAutoString name;
    1574               0 :   GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
    1575                 : 
    1576               0 :   nsCOMPtr<nsIDOMHTMLInputElement> selected;
    1577               0 :   container->GetCurrentRadioButton(name, getter_AddRefs(selected));
    1578               0 :   return selected.forget();
    1579                 : }
    1580                 : 
    1581                 : nsresult
    1582               0 : nsHTMLInputElement::MaybeSubmitForm(nsPresContext* aPresContext)
    1583                 : {
    1584               0 :   if (!mForm) {
    1585                 :     // Nothing to do here.
    1586               0 :     return NS_OK;
    1587                 :   }
    1588                 :   
    1589               0 :   nsCOMPtr<nsIPresShell> shell = aPresContext->GetPresShell();
    1590               0 :   if (!shell) {
    1591               0 :     return NS_OK;
    1592                 :   }
    1593                 : 
    1594                 :   // Get the default submit element
    1595               0 :   nsIFormControl* submitControl = mForm->GetDefaultSubmitElement();
    1596               0 :   if (submitControl) {
    1597               0 :     nsCOMPtr<nsIContent> submitContent = do_QueryInterface(submitControl);
    1598               0 :     NS_ASSERTION(submitContent, "Form control not implementing nsIContent?!");
    1599                 :     // Fire the button's onclick handler and let the button handle
    1600                 :     // submitting the form.
    1601               0 :     nsMouseEvent event(true, NS_MOUSE_CLICK, nsnull, nsMouseEvent::eReal);
    1602               0 :     nsEventStatus status = nsEventStatus_eIgnore;
    1603               0 :     shell->HandleDOMEventWithTarget(submitContent, &event, &status);
    1604               0 :   } else if (mForm->HasSingleTextControl() &&
    1605               0 :              (mForm->HasAttr(kNameSpaceID_None, nsGkAtoms::novalidate) ||
    1606               0 :               mForm->CheckValidFormSubmission())) {
    1607                 :     // TODO: removing this code and have the submit event sent by the form,
    1608                 :     // bug 592124.
    1609                 :     // If there's only one text control, just submit the form
    1610                 :     // Hold strong ref across the event
    1611               0 :     nsRefPtr<nsHTMLFormElement> form = mForm;
    1612               0 :     nsFormEvent event(true, NS_FORM_SUBMIT);
    1613               0 :     nsEventStatus status = nsEventStatus_eIgnore;
    1614               0 :     shell->HandleDOMEventWithTarget(mForm, &event, &status);
    1615                 :   }
    1616                 : 
    1617               0 :   return NS_OK;
    1618                 : }
    1619                 : 
    1620                 : void
    1621               0 : nsHTMLInputElement::SetCheckedInternal(bool aChecked, bool aNotify)
    1622                 : {
    1623                 :   // Set the value
    1624               0 :   mChecked = aChecked;
    1625                 : 
    1626                 :   // Notify the frame
    1627               0 :   if (mType == NS_FORM_INPUT_CHECKBOX || mType == NS_FORM_INPUT_RADIO) {
    1628               0 :     nsIFrame* frame = GetPrimaryFrame();
    1629               0 :     if (frame) {
    1630               0 :       frame->InvalidateFrameSubtree();
    1631                 :     }
    1632                 :   }
    1633                 : 
    1634               0 :   UpdateAllValidityStates(aNotify);
    1635                 : 
    1636                 :   // Notify the document that the CSS :checked pseudoclass for this element
    1637                 :   // has changed state.
    1638               0 :   UpdateState(aNotify);
    1639               0 : }
    1640                 : 
    1641                 : NS_IMETHODIMP
    1642               0 : nsHTMLInputElement::Focus()
    1643                 : {
    1644               0 :   if (mType != NS_FORM_INPUT_FILE) {
    1645               0 :     return nsGenericHTMLElement::Focus();
    1646                 :   }
    1647                 : 
    1648                 :   // For file inputs, focus the button instead.
    1649               0 :   nsIFrame* frame = GetPrimaryFrame();
    1650               0 :   if (frame) {
    1651               0 :     for (nsIFrame* childFrame = frame->GetFirstPrincipalChild();
    1652                 :          childFrame;
    1653                 :          childFrame = childFrame->GetNextSibling()) {
    1654                 :       // See if the child is a button control.
    1655                 :       nsCOMPtr<nsIFormControl> formCtrl =
    1656               0 :         do_QueryInterface(childFrame->GetContent());
    1657               0 :       if (formCtrl && formCtrl->GetType() == NS_FORM_INPUT_BUTTON) {
    1658               0 :         nsCOMPtr<nsIDOMElement> element = do_QueryInterface(formCtrl);
    1659               0 :         nsIFocusManager* fm = nsFocusManager::GetFocusManager();
    1660               0 :         if (fm && element) {
    1661               0 :           fm->SetFocus(element, 0);
    1662                 :         }
    1663                 :         break;
    1664                 :       }
    1665                 :     }
    1666                 :   }
    1667                 : 
    1668               0 :   return NS_OK;
    1669                 : }
    1670                 : 
    1671                 : NS_IMETHODIMP
    1672               0 : nsHTMLInputElement::Select()
    1673                 : {
    1674               0 :   if (!IsSingleLineTextControl(false)) {
    1675               0 :     return NS_OK;
    1676                 :   }
    1677                 : 
    1678                 :   // XXX Bug?  We have to give the input focus before contents can be
    1679                 :   // selected
    1680                 : 
    1681               0 :   FocusTristate state = FocusState();
    1682               0 :   if (state == eUnfocusable) {
    1683               0 :     return NS_OK;
    1684                 :   }
    1685                 : 
    1686               0 :   nsIFocusManager* fm = nsFocusManager::GetFocusManager();
    1687                 : 
    1688               0 :   nsRefPtr<nsPresContext> presContext = GetPresContext();
    1689               0 :   if (state == eInactiveWindow) {
    1690               0 :     if (fm)
    1691               0 :       fm->SetFocus(this, nsIFocusManager::FLAG_NOSCROLL);
    1692               0 :     SelectAll(presContext);
    1693               0 :     return NS_OK;
    1694                 :   }
    1695                 : 
    1696               0 :   if (DispatchSelectEvent(presContext) && fm) {
    1697               0 :     fm->SetFocus(this, nsIFocusManager::FLAG_NOSCROLL);
    1698                 : 
    1699                 :     // ensure that the element is actually focused
    1700               0 :     nsCOMPtr<nsIDOMElement> focusedElement;
    1701               0 :     fm->GetFocusedElement(getter_AddRefs(focusedElement));
    1702               0 :     if (SameCOMIdentity(static_cast<nsIDOMNode *>(this), focusedElement)) {
    1703                 :       // Now Select all the text!
    1704               0 :       SelectAll(presContext);
    1705                 :     }
    1706                 :   }
    1707                 : 
    1708               0 :   return NS_OK;
    1709                 : }
    1710                 : 
    1711                 : bool
    1712               0 : nsHTMLInputElement::DispatchSelectEvent(nsPresContext* aPresContext)
    1713                 : {
    1714               0 :   nsEventStatus status = nsEventStatus_eIgnore;
    1715                 : 
    1716                 :   // If already handling select event, don't dispatch a second.
    1717               0 :   if (!mHandlingSelectEvent) {
    1718               0 :     nsEvent event(nsContentUtils::IsCallerChrome(), NS_FORM_SELECTED);
    1719                 : 
    1720               0 :     mHandlingSelectEvent = true;
    1721                 :     nsEventDispatcher::Dispatch(static_cast<nsIContent*>(this),
    1722               0 :                                 aPresContext, &event, nsnull, &status);
    1723               0 :     mHandlingSelectEvent = false;
    1724                 :   }
    1725                 : 
    1726                 :   // If the DOM event was not canceled (e.g. by a JS event handler
    1727                 :   // returning false)
    1728               0 :   return (status == nsEventStatus_eIgnore);
    1729                 : }
    1730                 :     
    1731                 : void
    1732               0 : nsHTMLInputElement::SelectAll(nsPresContext* aPresContext)
    1733                 : {
    1734               0 :   nsIFormControlFrame* formControlFrame = GetFormControlFrame(true);
    1735                 : 
    1736               0 :   if (formControlFrame) {
    1737               0 :     formControlFrame->SetFormProperty(nsGkAtoms::select, EmptyString());
    1738                 :   }
    1739               0 : }
    1740                 : 
    1741                 : NS_IMETHODIMP
    1742               0 : nsHTMLInputElement::Click()
    1743                 : {
    1744               0 :   if (mType == NS_FORM_INPUT_FILE)
    1745               0 :     FireAsyncClickHandler();
    1746                 : 
    1747               0 :   return nsGenericHTMLElement::Click();
    1748                 : }
    1749                 : 
    1750                 : NS_IMETHODIMP
    1751               0 : nsHTMLInputElement::FireAsyncClickHandler()
    1752                 : {
    1753               0 :   nsCOMPtr<nsIRunnable> event = new AsyncClickHandler(this);
    1754               0 :   return NS_DispatchToMainThread(event);
    1755                 : }
    1756                 : 
    1757                 : bool
    1758               0 : nsHTMLInputElement::NeedToInitializeEditorForEvent(nsEventChainPreVisitor& aVisitor) const
    1759                 : {
    1760                 :   // We only need to initialize the editor for single line input controls because they
    1761                 :   // are lazily initialized.  We don't need to initialize the control for
    1762                 :   // certain types of events, because we know that those events are safe to be
    1763                 :   // handled without the editor being initialized.  These events include:
    1764                 :   // mousein/move/out, and DOM mutation events.
    1765               0 :   if (!IsSingleLineTextControl(false) ||
    1766                 :       aVisitor.mEvent->eventStructType == NS_MUTATION_EVENT) {
    1767               0 :     return false;
    1768                 :   }
    1769                 : 
    1770               0 :   switch (aVisitor.mEvent->message) {
    1771                 :   case NS_MOUSE_MOVE:
    1772                 :   case NS_MOUSE_ENTER:
    1773                 :   case NS_MOUSE_EXIT:
    1774                 :   case NS_MOUSE_ENTER_SYNTH:
    1775                 :   case NS_MOUSE_EXIT_SYNTH:
    1776               0 :     return false;
    1777                 :   default:
    1778               0 :     return true;
    1779                 :   }
    1780                 : }
    1781                 : 
    1782                 : nsresult
    1783               0 : nsHTMLInputElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
    1784                 : {
    1785                 :   // Do not process any DOM events if the element is disabled
    1786               0 :   aVisitor.mCanHandle = false;
    1787               0 :   if (IsElementDisabledForEvents(aVisitor.mEvent->message, GetPrimaryFrame())) {
    1788               0 :     return NS_OK;
    1789                 :   }
    1790                 : 
    1791                 :   // Initialize the editor if needed.
    1792               0 :   if (NeedToInitializeEditorForEvent(aVisitor)) {
    1793               0 :     nsITextControlFrame* textControlFrame = do_QueryFrame(GetPrimaryFrame());
    1794               0 :     if (textControlFrame)
    1795               0 :       textControlFrame->EnsureEditorInitialized();
    1796                 :   }
    1797                 : 
    1798                 :   //FIXME Allow submission etc. also when there is no prescontext, Bug 329509.
    1799               0 :   if (!aVisitor.mPresContext) {
    1800               0 :     return nsGenericHTMLElement::PreHandleEvent(aVisitor);
    1801                 :   }
    1802                 :   //
    1803                 :   // Web pages expect the value of a radio button or checkbox to be set
    1804                 :   // *before* onclick and DOMActivate fire, and they expect that if they set
    1805                 :   // the value explicitly during onclick or DOMActivate it will not be toggled
    1806                 :   // or any such nonsense.
    1807                 :   // In order to support that (bug 57137 and 58460 are examples) we toggle
    1808                 :   // the checked attribute *first*, and then fire onclick.  If the user
    1809                 :   // returns false, we reset the control to the old checked value.  Otherwise,
    1810                 :   // we dispatch DOMActivate.  If DOMActivate is cancelled, we also reset
    1811                 :   // the control to the old checked value.  We need to keep track of whether
    1812                 :   // we've already toggled the state from onclick since the user could
    1813                 :   // explicitly dispatch DOMActivate on the element.
    1814                 :   //
    1815                 :   // This is a compatibility hack.
    1816                 :   //
    1817                 : 
    1818                 :   // Track whether we're in the outermost Dispatch invocation that will
    1819                 :   // cause activation of the input.  That is, if we're a click event, or a
    1820                 :   // DOMActivate that was dispatched directly, this will be set, but if we're
    1821                 :   // a DOMActivate dispatched from click handling, it will not be set.
    1822                 :   bool outerActivateEvent =
    1823                 :     (NS_IS_MOUSE_LEFT_CLICK(aVisitor.mEvent) ||
    1824               0 :      (aVisitor.mEvent->message == NS_UI_ACTIVATE && !mInInternalActivate));
    1825                 : 
    1826               0 :   if (outerActivateEvent) {
    1827               0 :     aVisitor.mItemFlags |= NS_OUTER_ACTIVATE_EVENT;
    1828                 :   }
    1829                 : 
    1830               0 :   bool originalCheckedValue = false;
    1831                 : 
    1832               0 :   if (outerActivateEvent) {
    1833               0 :     mCheckedIsToggled = false;
    1834                 : 
    1835               0 :     switch(mType) {
    1836                 :       case NS_FORM_INPUT_CHECKBOX:
    1837                 :         {
    1838               0 :           if (mIndeterminate) {
    1839                 :             // indeterminate is always set to FALSE when the checkbox is toggled
    1840               0 :             SetIndeterminateInternal(false, false);
    1841               0 :             aVisitor.mItemFlags |= NS_ORIGINAL_INDETERMINATE_VALUE;
    1842                 :           }
    1843                 : 
    1844               0 :           GetChecked(&originalCheckedValue);
    1845               0 :           DoSetChecked(!originalCheckedValue, true, true);
    1846               0 :           mCheckedIsToggled = true;
    1847                 :         }
    1848               0 :         break;
    1849                 : 
    1850                 :       case NS_FORM_INPUT_RADIO:
    1851                 :         {
    1852               0 :           nsCOMPtr<nsIDOMHTMLInputElement> selectedRadioButton = GetSelectedRadioButton();
    1853               0 :           aVisitor.mItemData = selectedRadioButton;
    1854                 : 
    1855               0 :           originalCheckedValue = mChecked;
    1856               0 :           if (!originalCheckedValue) {
    1857               0 :             DoSetChecked(true, true, true);
    1858               0 :             mCheckedIsToggled = true;
    1859                 :           }
    1860                 :         }
    1861               0 :         break;
    1862                 : 
    1863                 :       case NS_FORM_INPUT_SUBMIT:
    1864                 :       case NS_FORM_INPUT_IMAGE:
    1865               0 :         if(mForm) {
    1866                 :           // tell the form that we are about to enter a click handler.
    1867                 :           // that means that if there are scripted submissions, the
    1868                 :           // latest one will be deferred until after the exit point of the handler. 
    1869               0 :           mForm->OnSubmitClickBegin(this);
    1870                 :         }
    1871               0 :         break;
    1872                 : 
    1873                 :       default:
    1874               0 :         break;
    1875                 :     }
    1876                 :   }
    1877                 : 
    1878               0 :   if (originalCheckedValue) {
    1879               0 :     aVisitor.mItemFlags |= NS_ORIGINAL_CHECKED_VALUE;
    1880                 :   }
    1881                 : 
    1882                 :   // If NS_EVENT_FLAG_NO_CONTENT_DISPATCH is set we will not allow content to handle
    1883                 :   // this event.  But to allow middle mouse button paste to work we must allow 
    1884                 :   // middle clicks to go to text fields anyway.
    1885               0 :   if (aVisitor.mEvent->flags & NS_EVENT_FLAG_NO_CONTENT_DISPATCH) {
    1886               0 :     aVisitor.mItemFlags |= NS_NO_CONTENT_DISPATCH;
    1887                 :   }
    1888               0 :   if (IsSingleLineTextControl(false) &&
    1889                 :       aVisitor.mEvent->message == NS_MOUSE_CLICK &&
    1890                 :       aVisitor.mEvent->eventStructType == NS_MOUSE_EVENT &&
    1891                 :       static_cast<nsMouseEvent*>(aVisitor.mEvent)->button ==
    1892                 :         nsMouseEvent::eMiddleButton) {
    1893               0 :     aVisitor.mEvent->flags &= ~NS_EVENT_FLAG_NO_CONTENT_DISPATCH;
    1894                 :   }
    1895                 : 
    1896                 :   // We must cache type because mType may change during JS event (bug 2369)
    1897               0 :   aVisitor.mItemFlags |= mType;
    1898                 : 
    1899                 :   // Fire onchange (if necessary), before we do the blur, bug 357684.
    1900               0 :   if (aVisitor.mEvent->message == NS_BLUR_CONTENT) {
    1901               0 :     nsIFrame* primaryFrame = GetPrimaryFrame();
    1902               0 :     if (primaryFrame) {
    1903               0 :       nsITextControlFrame* textFrame = do_QueryFrame(primaryFrame);
    1904               0 :       if (textFrame) {
    1905               0 :         textFrame->CheckFireOnChange();
    1906                 :       }
    1907                 :     }
    1908                 :   }
    1909                 : 
    1910               0 :   return nsGenericHTMLFormElement::PreHandleEvent(aVisitor);
    1911                 : }
    1912                 : 
    1913                 : static bool
    1914               0 : SelectTextFieldOnFocus()
    1915                 : {
    1916               0 :   if (!gSelectTextFieldOnFocus) {
    1917               0 :     PRInt32 selectTextfieldsOnKeyFocus = -1;
    1918                 :     nsresult rv =
    1919                 :       LookAndFeel::GetInt(LookAndFeel::eIntID_SelectTextfieldsOnKeyFocus,
    1920               0 :                           &selectTextfieldsOnKeyFocus);
    1921               0 :     if (NS_FAILED(rv)) {
    1922               0 :       gSelectTextFieldOnFocus = -1;
    1923                 :     } else {
    1924               0 :       gSelectTextFieldOnFocus = selectTextfieldsOnKeyFocus != 0 ? 1 : -1;
    1925                 :     }
    1926                 :   }
    1927                 : 
    1928               0 :   return gSelectTextFieldOnFocus == 1;
    1929                 : }
    1930                 : 
    1931                 : nsresult
    1932               0 : nsHTMLInputElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
    1933                 : {
    1934               0 :   if (!aVisitor.mPresContext) {
    1935               0 :     return NS_OK;
    1936                 :   }
    1937                 : 
    1938               0 :   if (aVisitor.mEvent->message == NS_FOCUS_CONTENT ||
    1939                 :       aVisitor.mEvent->message == NS_BLUR_CONTENT) {
    1940                 : 
    1941               0 :     UpdateValidityUIBits(aVisitor.mEvent->message == NS_FOCUS_CONTENT);
    1942                 : 
    1943               0 :     UpdateState(true);
    1944                 :   }
    1945                 : 
    1946                 :   // ignore the activate event fired by the "Browse..." button
    1947                 :   // (file input controls fire their own) (bug 500885)
    1948               0 :   if (mType == NS_FORM_INPUT_FILE) {
    1949                 :     nsCOMPtr<nsIContent> maybeButton =
    1950               0 :       do_QueryInterface(aVisitor.mEvent->originalTarget);
    1951               0 :     if (maybeButton &&
    1952               0 :       maybeButton->IsRootOfNativeAnonymousSubtree() &&
    1953               0 :       maybeButton->AttrValueIs(kNameSpaceID_None,
    1954                 :                                nsGkAtoms::type,
    1955                 :                                nsGkAtoms::button,
    1956               0 :                                eCaseMatters)) {
    1957               0 :         return NS_OK;
    1958                 :     }
    1959                 :   }
    1960                 : 
    1961               0 :   nsresult rv = NS_OK;
    1962               0 :   bool outerActivateEvent = !!(aVisitor.mItemFlags & NS_OUTER_ACTIVATE_EVENT);
    1963                 :   bool originalCheckedValue =
    1964               0 :     !!(aVisitor.mItemFlags & NS_ORIGINAL_CHECKED_VALUE);
    1965               0 :   bool noContentDispatch = !!(aVisitor.mItemFlags & NS_NO_CONTENT_DISPATCH);
    1966               0 :   PRUint8 oldType = NS_CONTROL_TYPE(aVisitor.mItemFlags);
    1967                 :   // Ideally we would make the default action for click and space just dispatch
    1968                 :   // DOMActivate, and the default action for DOMActivate flip the checkbox/
    1969                 :   // radio state and fire onchange.  However, for backwards compatibility, we
    1970                 :   // need to flip the state before firing click, and we need to fire click
    1971                 :   // when space is pressed.  So, we just nest the firing of DOMActivate inside
    1972                 :   // the click event handling, and allow cancellation of DOMActivate to cancel
    1973                 :   // the click.
    1974               0 :   if (aVisitor.mEventStatus != nsEventStatus_eConsumeNoDefault &&
    1975               0 :       !IsSingleLineTextControl(true) &&
    1976                 :       NS_IS_MOUSE_LEFT_CLICK(aVisitor.mEvent)) {
    1977               0 :     nsUIEvent actEvent(NS_IS_TRUSTED_EVENT(aVisitor.mEvent), NS_UI_ACTIVATE, 1);
    1978                 : 
    1979               0 :     nsCOMPtr<nsIPresShell> shell = aVisitor.mPresContext->GetPresShell();
    1980               0 :     if (shell) {
    1981               0 :       nsEventStatus status = nsEventStatus_eIgnore;
    1982               0 :       mInInternalActivate = true;
    1983               0 :       rv = shell->HandleDOMEventWithTarget(this, &actEvent, &status);
    1984               0 :       mInInternalActivate = false;
    1985                 : 
    1986                 :       // If activate is cancelled, we must do the same as when click is
    1987                 :       // cancelled (revert the checkbox to its original value).
    1988               0 :       if (status == nsEventStatus_eConsumeNoDefault)
    1989               0 :         aVisitor.mEventStatus = status;
    1990                 :     }
    1991                 :   }
    1992                 : 
    1993               0 :   if (outerActivateEvent) {
    1994               0 :     switch(oldType) {
    1995                 :       case NS_FORM_INPUT_SUBMIT:
    1996                 :       case NS_FORM_INPUT_IMAGE:
    1997               0 :         if(mForm) {
    1998                 :           // tell the form that we are about to exit a click handler
    1999                 :           // so the form knows not to defer subsequent submissions
    2000                 :           // the pending ones that were created during the handler
    2001                 :           // will be flushed or forgoten.
    2002               0 :           mForm->OnSubmitClickEnd();
    2003                 :         }
    2004               0 :         break;
    2005                 :     }
    2006                 :   }
    2007                 : 
    2008                 :   // Reset the flag for other content besides this text field
    2009                 :   aVisitor.mEvent->flags |=
    2010               0 :     noContentDispatch ? NS_EVENT_FLAG_NO_CONTENT_DISPATCH : NS_EVENT_FLAG_NONE;
    2011                 : 
    2012                 :   // now check to see if the event was "cancelled"
    2013               0 :   if (mCheckedIsToggled && outerActivateEvent) {
    2014               0 :     if (aVisitor.mEventStatus == nsEventStatus_eConsumeNoDefault) {
    2015                 :       // if it was cancelled and a radio button, then set the old
    2016                 :       // selected btn to TRUE. if it is a checkbox then set it to its
    2017                 :       // original value
    2018               0 :       if (oldType == NS_FORM_INPUT_RADIO) {
    2019                 :         nsCOMPtr<nsIDOMHTMLInputElement> selectedRadioButton =
    2020               0 :           do_QueryInterface(aVisitor.mItemData);
    2021               0 :         if (selectedRadioButton) {
    2022               0 :           selectedRadioButton->SetChecked(true);
    2023                 :         }
    2024                 :         // If there was no checked radio button or this one is no longer a
    2025                 :         // radio button we must reset it back to false to cancel the action.
    2026                 :         // See how the web of hack grows?
    2027               0 :         if (!selectedRadioButton || mType != NS_FORM_INPUT_RADIO) {
    2028               0 :           DoSetChecked(false, true, true);
    2029                 :         }
    2030               0 :       } else if (oldType == NS_FORM_INPUT_CHECKBOX) {
    2031                 :         bool originalIndeterminateValue =
    2032               0 :           !!(aVisitor.mItemFlags & NS_ORIGINAL_INDETERMINATE_VALUE);
    2033               0 :         SetIndeterminateInternal(originalIndeterminateValue, false);
    2034               0 :         DoSetChecked(originalCheckedValue, true, true);
    2035                 :       }
    2036                 :     } else {
    2037                 :       nsContentUtils::DispatchTrustedEvent(OwnerDoc(),
    2038                 :                                            static_cast<nsIDOMHTMLInputElement*>(this),
    2039               0 :                                            NS_LITERAL_STRING("change"), true,
    2040               0 :                                            false);
    2041                 : #ifdef ACCESSIBILITY
    2042                 :       // Fire an event to notify accessibility
    2043               0 :       if (mType == NS_FORM_INPUT_CHECKBOX) {
    2044                 :         FireEventForAccessibility(this, aVisitor.mPresContext,
    2045               0 :                                   NS_LITERAL_STRING("CheckboxStateChange"));
    2046                 :       } else {
    2047                 :         FireEventForAccessibility(this, aVisitor.mPresContext,
    2048               0 :                                   NS_LITERAL_STRING("RadioStateChange"));
    2049                 :         // Fire event for the previous selected radio.
    2050                 :         nsCOMPtr<nsIDOMHTMLInputElement> previous =
    2051               0 :           do_QueryInterface(aVisitor.mItemData);
    2052               0 :         if(previous) {
    2053                 :           FireEventForAccessibility(previous, aVisitor.mPresContext,
    2054               0 :                                     NS_LITERAL_STRING("RadioStateChange"));
    2055                 :         }
    2056                 :       }
    2057                 : #endif
    2058                 :     }
    2059                 :   }
    2060                 : 
    2061               0 :   if (NS_SUCCEEDED(rv)) {
    2062               0 :     if (nsEventStatus_eIgnore == aVisitor.mEventStatus) {
    2063               0 :       switch (aVisitor.mEvent->message) {
    2064                 : 
    2065                 :         case NS_FOCUS_CONTENT:
    2066                 :         {
    2067                 :           // see if we should select the contents of the textbox. This happens
    2068                 :           // for text and password fields when the field was focused by the
    2069                 :           // keyboard or a navigation, the platform allows it, and it wasn't
    2070                 :           // just because we raised a window.
    2071               0 :           nsIFocusManager* fm = nsFocusManager::GetFocusManager();
    2072               0 :           if (fm && IsSingleLineTextControl(false) &&
    2073               0 :               !(static_cast<nsFocusEvent *>(aVisitor.mEvent))->fromRaise &&
    2074               0 :               SelectTextFieldOnFocus()) {
    2075               0 :             nsIDocument* document = GetCurrentDoc();
    2076               0 :             if (document) {
    2077                 :               PRUint32 lastFocusMethod;
    2078               0 :               fm->GetLastFocusMethod(document->GetWindow(), &lastFocusMethod);
    2079               0 :               if (lastFocusMethod &
    2080                 :                   (nsIFocusManager::FLAG_BYKEY | nsIFocusManager::FLAG_BYMOVEFOCUS)) {
    2081               0 :                 nsRefPtr<nsPresContext> presContext = GetPresContext();
    2082               0 :                 if (DispatchSelectEvent(presContext)) {
    2083               0 :                   SelectAll(presContext);
    2084                 :                 }
    2085                 :               }
    2086                 :             }
    2087                 :           }
    2088               0 :           break;
    2089                 :         }
    2090                 : 
    2091                 :         case NS_KEY_PRESS:
    2092                 :         case NS_KEY_UP:
    2093                 :         {
    2094                 :           // For backwards compat, trigger checks/radios/buttons with
    2095                 :           // space or enter (bug 25300)
    2096               0 :           nsKeyEvent * keyEvent = (nsKeyEvent *)aVisitor.mEvent;
    2097                 : 
    2098               0 :           if ((aVisitor.mEvent->message == NS_KEY_PRESS &&
    2099                 :                keyEvent->keyCode == NS_VK_RETURN) ||
    2100                 :               (aVisitor.mEvent->message == NS_KEY_UP &&
    2101                 :                keyEvent->keyCode == NS_VK_SPACE)) {
    2102               0 :             switch(mType) {
    2103                 :               case NS_FORM_INPUT_CHECKBOX:
    2104                 :               case NS_FORM_INPUT_RADIO:
    2105                 :               {
    2106                 :                 // Checkbox and Radio try to submit on Enter press
    2107               0 :                 if (keyEvent->keyCode != NS_VK_SPACE) {
    2108               0 :                   MaybeSubmitForm(aVisitor.mPresContext);
    2109                 : 
    2110               0 :                   break;  // If we are submitting, do not send click event
    2111                 :                 }
    2112                 :                 // else fall through and treat Space like click...
    2113                 :               }
    2114                 :               case NS_FORM_INPUT_BUTTON:
    2115                 :               case NS_FORM_INPUT_RESET:
    2116                 :               case NS_FORM_INPUT_SUBMIT:
    2117                 :               case NS_FORM_INPUT_IMAGE: // Bug 34418
    2118                 :               {
    2119                 :                 nsMouseEvent event(NS_IS_TRUSTED_EVENT(aVisitor.mEvent),
    2120               0 :                                    NS_MOUSE_CLICK, nsnull, nsMouseEvent::eReal);
    2121               0 :                 event.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_KEYBOARD;
    2122               0 :                 nsEventStatus status = nsEventStatus_eIgnore;
    2123                 : 
    2124                 :                 nsEventDispatcher::Dispatch(static_cast<nsIContent*>(this),
    2125                 :                                             aVisitor.mPresContext, &event,
    2126               0 :                                             nsnull, &status);
    2127               0 :                 aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
    2128                 :               } // case
    2129                 :             } // switch
    2130                 :           }
    2131               0 :           if (aVisitor.mEvent->message == NS_KEY_PRESS &&
    2132               0 :               mType == NS_FORM_INPUT_RADIO && !keyEvent->isAlt &&
    2133               0 :               !keyEvent->isControl && !keyEvent->isMeta) {
    2134               0 :             bool isMovingBack = false;
    2135               0 :             switch (keyEvent->keyCode) {
    2136                 :               case NS_VK_UP: 
    2137                 :               case NS_VK_LEFT:
    2138               0 :                 isMovingBack = true;
    2139                 :                 // FALLTHROUGH
    2140                 :               case NS_VK_DOWN:
    2141                 :               case NS_VK_RIGHT:
    2142                 :               // Arrow key pressed, focus+select prev/next radio button
    2143               0 :               nsIRadioGroupContainer* container = GetRadioGroupContainer();
    2144               0 :               if (container) {
    2145               0 :                 nsAutoString name;
    2146               0 :                 GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
    2147               0 :                 nsCOMPtr<nsIDOMHTMLInputElement> selectedRadioButton;
    2148                 :                 container->GetNextRadioButton(name, isMovingBack, this,
    2149               0 :                                               getter_AddRefs(selectedRadioButton));
    2150                 :                 nsCOMPtr<nsIContent> radioContent =
    2151               0 :                   do_QueryInterface(selectedRadioButton);
    2152               0 :                 if (radioContent) {
    2153               0 :                   rv = selectedRadioButton->Focus();
    2154               0 :                   if (NS_SUCCEEDED(rv)) {
    2155               0 :                     nsEventStatus status = nsEventStatus_eIgnore;
    2156                 :                     nsMouseEvent event(NS_IS_TRUSTED_EVENT(aVisitor.mEvent),
    2157                 :                                        NS_MOUSE_CLICK, nsnull,
    2158               0 :                                        nsMouseEvent::eReal);
    2159               0 :                     event.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_KEYBOARD;
    2160                 :                     rv = nsEventDispatcher::Dispatch(radioContent,
    2161                 :                                                      aVisitor.mPresContext,
    2162               0 :                                                      &event, nsnull, &status);
    2163               0 :                     if (NS_SUCCEEDED(rv)) {
    2164               0 :                       aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
    2165                 :                     }
    2166                 :                   }
    2167                 :                 }
    2168                 :               }
    2169                 :             }
    2170                 :           }
    2171                 : 
    2172                 :           /*
    2173                 :            * For some input types, if the user hits enter, the form is submitted.
    2174                 :            *
    2175                 :            * Bug 99920, bug 109463 and bug 147850:
    2176                 :            * (a) if there is a submit control in the form, click the first
    2177                 :            *     submit control in the form.
    2178                 :            * (b) if there is just one text control in the form, submit by
    2179                 :            *     sending a submit event directly to the form
    2180                 :            * (c) if there is more than one text input and no submit buttons, do
    2181                 :            *     not submit, period.
    2182                 :            */
    2183                 : 
    2184               0 :           if (aVisitor.mEvent->message == NS_KEY_PRESS &&
    2185                 :               (keyEvent->keyCode == NS_VK_RETURN ||
    2186                 :                keyEvent->keyCode == NS_VK_ENTER) &&
    2187               0 :                IsSingleLineTextControl(false, mType)) {
    2188               0 :             nsIFrame* primaryFrame = GetPrimaryFrame();
    2189               0 :             if (primaryFrame) {
    2190               0 :               nsITextControlFrame* textFrame = do_QueryFrame(primaryFrame);
    2191                 : 
    2192                 :               // Fire onChange (if necessary)
    2193               0 :               if (textFrame) {
    2194               0 :                 textFrame->CheckFireOnChange();
    2195                 :               }
    2196                 :             }
    2197                 : 
    2198               0 :             rv = MaybeSubmitForm(aVisitor.mPresContext);
    2199               0 :             NS_ENSURE_SUCCESS(rv, rv);
    2200                 :           }
    2201                 : 
    2202               0 :         } break; // NS_KEY_PRESS || NS_KEY_UP
    2203                 : 
    2204                 :         case NS_MOUSE_BUTTON_DOWN:
    2205                 :         case NS_MOUSE_BUTTON_UP:
    2206                 :         case NS_MOUSE_DOUBLECLICK:
    2207                 :         {
    2208                 :           // cancel all of these events for buttons
    2209                 :           //XXXsmaug Why?
    2210               0 :           if (aVisitor.mEvent->eventStructType == NS_MOUSE_EVENT &&
    2211                 :               (static_cast<nsMouseEvent*>(aVisitor.mEvent)->button ==
    2212                 :                  nsMouseEvent::eMiddleButton ||
    2213                 :                static_cast<nsMouseEvent*>(aVisitor.mEvent)->button ==
    2214                 :                  nsMouseEvent::eRightButton)) {
    2215               0 :             if (mType == NS_FORM_INPUT_BUTTON ||
    2216                 :                 mType == NS_FORM_INPUT_RESET ||
    2217                 :                 mType == NS_FORM_INPUT_SUBMIT) {
    2218               0 :               if (aVisitor.mDOMEvent) {
    2219               0 :                 aVisitor.mDOMEvent->StopPropagation();
    2220                 :               } else {
    2221               0 :                 rv = NS_ERROR_FAILURE;
    2222                 :               }
    2223                 :             }
    2224                 : 
    2225                 :           }
    2226               0 :           break;
    2227                 :         }
    2228                 :         default:
    2229               0 :           break;
    2230                 :       }
    2231                 : 
    2232               0 :       if (outerActivateEvent) {
    2233               0 :         if (mForm && (oldType == NS_FORM_INPUT_SUBMIT ||
    2234                 :                       oldType == NS_FORM_INPUT_IMAGE)) {
    2235               0 :           if (mType != NS_FORM_INPUT_SUBMIT && mType != NS_FORM_INPUT_IMAGE) {
    2236                 :             // If the type has changed to a non-submit type, then we want to
    2237                 :             // flush the stored submission if there is one (as if the submit()
    2238                 :             // was allowed to succeed)
    2239               0 :             mForm->FlushPendingSubmission();
    2240                 :           }
    2241                 :         }
    2242               0 :         switch(mType) {
    2243                 :         case NS_FORM_INPUT_RESET:
    2244                 :         case NS_FORM_INPUT_SUBMIT:
    2245                 :         case NS_FORM_INPUT_IMAGE:
    2246               0 :           if (mForm) {
    2247                 :             nsFormEvent event(true, (mType == NS_FORM_INPUT_RESET) ?
    2248               0 :                               NS_FORM_RESET : NS_FORM_SUBMIT);
    2249               0 :             event.originator      = this;
    2250               0 :             nsEventStatus status  = nsEventStatus_eIgnore;
    2251                 : 
    2252                 :             nsCOMPtr<nsIPresShell> presShell =
    2253               0 :               aVisitor.mPresContext->GetPresShell();
    2254                 : 
    2255                 :             // If |nsIPresShell::Destroy| has been called due to
    2256                 :             // handling the event the pres context will return a null
    2257                 :             // pres shell.  See bug 125624.
    2258                 :             // TODO: removing this code and have the submit event sent by the
    2259                 :             // form, see bug 592124.
    2260               0 :             if (presShell && (event.message != NS_FORM_SUBMIT ||
    2261               0 :                               mForm->HasAttr(kNameSpaceID_None, nsGkAtoms::novalidate) ||
    2262                 :                               // We know the element is a submit control, if this check is moved,
    2263                 :                               // make sure formnovalidate is used only if it's a submit control.
    2264               0 :                               HasAttr(kNameSpaceID_None, nsGkAtoms::formnovalidate) ||
    2265               0 :                               mForm->CheckValidFormSubmission())) {
    2266                 :               // Hold a strong ref while dispatching
    2267               0 :               nsRefPtr<nsHTMLFormElement> form(mForm);
    2268               0 :               presShell->HandleDOMEventWithTarget(mForm, &event, &status);
    2269               0 :               aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
    2270                 :             }
    2271                 :           }
    2272               0 :           break;
    2273                 : 
    2274                 :         default:
    2275               0 :           break;
    2276                 :         } //switch 
    2277                 :       } //click or outer activate event
    2278               0 :     } else if (outerActivateEvent &&
    2279                 :                (oldType == NS_FORM_INPUT_SUBMIT ||
    2280                 :                 oldType == NS_FORM_INPUT_IMAGE) &&
    2281                 :                mForm) {
    2282                 :       // tell the form to flush a possible pending submission.
    2283                 :       // the reason is that the script returned false (the event was
    2284                 :       // not ignored) so if there is a stored submission, it needs to
    2285                 :       // be submitted immediately.
    2286               0 :       mForm->FlushPendingSubmission();
    2287                 :     }
    2288                 :   } // if
    2289                 : 
    2290               0 :   return rv;
    2291                 : }
    2292                 : 
    2293                 : void
    2294               0 : nsHTMLInputElement::MaybeLoadImage()
    2295                 : {
    2296                 :   // Our base URI may have changed; claim that our URI changed, and the
    2297                 :   // nsImageLoadingContent will decide whether a new image load is warranted.
    2298               0 :   nsAutoString uri;
    2299               0 :   if (mType == NS_FORM_INPUT_IMAGE &&
    2300               0 :       GetAttr(kNameSpaceID_None, nsGkAtoms::src, uri) &&
    2301               0 :       (NS_FAILED(LoadImage(uri, false, true)) ||
    2302               0 :        !LoadingEnabled())) {
    2303               0 :     CancelImageRequests(true);
    2304                 :   }
    2305               0 : }
    2306                 : 
    2307                 : nsresult
    2308               1 : nsHTMLInputElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
    2309                 :                                nsIContent* aBindingParent,
    2310                 :                                bool aCompileEventHandlers)
    2311                 : {
    2312                 :   nsresult rv = nsGenericHTMLFormElement::BindToTree(aDocument, aParent,
    2313                 :                                                      aBindingParent,
    2314               1 :                                                      aCompileEventHandlers);
    2315               1 :   NS_ENSURE_SUCCESS(rv, rv);
    2316                 : 
    2317               1 :   if (mType == NS_FORM_INPUT_IMAGE) {
    2318                 :     // Our base URI may have changed; claim that our URI changed, and the
    2319                 :     // nsImageLoadingContent will decide whether a new image load is warranted.
    2320               0 :     if (HasAttr(kNameSpaceID_None, nsGkAtoms::src)) {
    2321                 :       // FIXME: Bug 660963 it would be nice if we could just have
    2322                 :       // ClearBrokenState update our state and do it fast...
    2323               0 :       ClearBrokenState();
    2324               0 :       RemoveStatesSilently(NS_EVENT_STATE_BROKEN);
    2325                 :       nsContentUtils::AddScriptRunner(
    2326               0 :         NS_NewRunnableMethod(this, &nsHTMLInputElement::MaybeLoadImage));
    2327                 :     }
    2328                 :   }
    2329                 : 
    2330                 :   // Add radio to document if we don't have a form already (if we do it's
    2331                 :   // already been added into that group)
    2332               1 :   if (aDocument && !mForm && mType == NS_FORM_INPUT_RADIO) {
    2333               0 :     AddedToRadioGroup();
    2334                 :   }
    2335                 : 
    2336                 :   // An element can't suffer from value missing if it is not in a document.
    2337                 :   // We have to check if we suffer from that as we are now in a document.
    2338               1 :   UpdateValueMissingValidityState();
    2339                 : 
    2340                 :   // If there is a disabled fieldset in the parent chain, the element is now
    2341                 :   // barred from constraint validation and can't suffer from value missing
    2342                 :   // (call done before).
    2343               1 :   UpdateBarredFromConstraintValidation();
    2344                 : 
    2345                 :   // And now make sure our state is up to date
    2346               1 :   UpdateState(false);
    2347                 : 
    2348               1 :   return rv;
    2349                 : }
    2350                 : 
    2351                 : void
    2352               3 : nsHTMLInputElement::UnbindFromTree(bool aDeep, bool aNullParent)
    2353                 : {
    2354                 :   // If we have a form and are unbound from it,
    2355                 :   // nsGenericHTMLFormElement::UnbindFromTree() will unset the form and
    2356                 :   // that takes care of form's WillRemove so we just have to take care
    2357                 :   // of the case where we're removing from the document and we don't
    2358                 :   // have a form
    2359               3 :   if (!mForm && mType == NS_FORM_INPUT_RADIO) {
    2360               0 :     WillRemoveFromRadioGroup();
    2361                 :   }
    2362                 : 
    2363               3 :   nsGenericHTMLFormElement::UnbindFromTree(aDeep, aNullParent);
    2364                 : 
    2365                 :   // GetCurrentDoc is returning nsnull so we can update the value
    2366                 :   // missing validity state to reflect we are no longer into a doc.
    2367               3 :   UpdateValueMissingValidityState();
    2368                 :   // We might be no longer disabled because of parent chain changed.
    2369               3 :   UpdateBarredFromConstraintValidation();
    2370                 : 
    2371                 :   // And now make sure our state is up to date
    2372               3 :   UpdateState(false);
    2373               3 : }
    2374                 : 
    2375                 : void
    2376               0 : nsHTMLInputElement::HandleTypeChange(PRUint8 aNewType)
    2377                 : {
    2378               0 :   ValueModeType aOldValueMode = GetValueMode();
    2379               0 :   nsAutoString aOldValue;
    2380                 : 
    2381               0 :   if (aOldValueMode == VALUE_MODE_VALUE && !mParserCreating) {
    2382               0 :     GetValue(aOldValue);
    2383                 :   }
    2384                 : 
    2385                 :   // Only single line text inputs have a text editor state.
    2386               0 :   bool isNewTypeSingleLine = IsSingleLineTextControl(false, aNewType);
    2387               0 :   bool isCurrentTypeSingleLine = IsSingleLineTextControl(false, mType);
    2388                 : 
    2389               0 :   if (isNewTypeSingleLine && !isCurrentTypeSingleLine) {
    2390               0 :     FreeData();
    2391               0 :     mInputData.mState = new nsTextEditorState(this);
    2392               0 :     NS_ADDREF(mInputData.mState);
    2393               0 :   } else if (isCurrentTypeSingleLine && !isNewTypeSingleLine) {
    2394               0 :     FreeData();
    2395                 :   }
    2396                 : 
    2397               0 :   mType = aNewType;
    2398                 : 
    2399               0 :   if (!mParserCreating) {
    2400                 :     /**
    2401                 :      * The following code is trying to reproduce the algorithm described here:
    2402                 :      * http://www.whatwg.org/specs/web-apps/current-work/complete.html#input-type-change
    2403                 :      */
    2404               0 :     switch (GetValueMode()) {
    2405                 :       case VALUE_MODE_DEFAULT:
    2406                 :       case VALUE_MODE_DEFAULT_ON:
    2407                 :         // If the previous value mode was value, we need to set the value content
    2408                 :         // attribute to the previous value.
    2409                 :         // There is no value sanitizing algorithm for elements in this mode.
    2410               0 :         if (aOldValueMode == VALUE_MODE_VALUE && !aOldValue.IsEmpty()) {
    2411               0 :           SetAttr(kNameSpaceID_None, nsGkAtoms::value, aOldValue, true);
    2412                 :         }
    2413               0 :         break;
    2414                 :       case VALUE_MODE_VALUE:
    2415                 :         // If the previous value mode wasn't value, we have to set the value to
    2416                 :         // the value content attribute.
    2417                 :         // SetValueInternal is going to sanitize the value.
    2418                 :         {
    2419               0 :           nsAutoString value;
    2420               0 :           if (aOldValueMode != VALUE_MODE_VALUE) {
    2421               0 :             GetAttr(kNameSpaceID_None, nsGkAtoms::value, value);
    2422                 :           } else {
    2423                 :             // We get the current value so we can sanitize it.
    2424               0 :             GetValue(value);
    2425                 :           }
    2426               0 :           SetValueInternal(value, false, false);
    2427                 :         }
    2428               0 :         break;
    2429                 :       case VALUE_MODE_FILENAME:
    2430                 :       default:
    2431                 :         // We don't care about the value.
    2432                 :         // There is no value sanitizing algorithm for elements in this mode.
    2433               0 :         break;
    2434                 :     }
    2435                 :   }
    2436                 : 
    2437                 :   // Do not notify, it will be done after if needed.
    2438               0 :   UpdateAllValidityStates(false);
    2439               0 : }
    2440                 : 
    2441                 : void
    2442               2 : nsHTMLInputElement::SanitizeValue(nsAString& aValue)
    2443                 : {
    2444               2 :   NS_ASSERTION(!mParserCreating, "The element parsing should be finished!");
    2445                 : 
    2446               2 :   switch (mType) {
    2447                 :     case NS_FORM_INPUT_TEXT:
    2448                 :     case NS_FORM_INPUT_SEARCH:
    2449                 :     case NS_FORM_INPUT_TEL:
    2450                 :     case NS_FORM_INPUT_PASSWORD:
    2451                 :       {
    2452               2 :         PRUnichar crlf[] = { PRUnichar('\r'), PRUnichar('\n'), 0 };
    2453               2 :         aValue.StripChars(crlf);
    2454                 :       }
    2455               2 :       break;
    2456                 :     case NS_FORM_INPUT_EMAIL:
    2457                 :     case NS_FORM_INPUT_URL:
    2458                 :       {
    2459               0 :         PRUnichar crlf[] = { PRUnichar('\r'), PRUnichar('\n'), 0 };
    2460               0 :         aValue.StripChars(crlf);
    2461                 : 
    2462               0 :         aValue = nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(aValue);
    2463                 :       }
    2464               0 :       break;
    2465                 :   }
    2466               2 : }
    2467                 : 
    2468                 : bool
    2469               0 : nsHTMLInputElement::ParseAttribute(PRInt32 aNamespaceID,
    2470                 :                                    nsIAtom* aAttribute,
    2471                 :                                    const nsAString& aValue,
    2472                 :                                    nsAttrValue& aResult)
    2473                 : {
    2474               0 :   if (aNamespaceID == kNameSpaceID_None) {
    2475               0 :     if (aAttribute == nsGkAtoms::type) {
    2476                 :       // XXX ARG!! This is major evilness. ParseAttribute
    2477                 :       // shouldn't set members. Override SetAttr instead
    2478                 :       PRInt32 newType;
    2479               0 :       bool success = aResult.ParseEnumValue(aValue, kInputTypeTable, false);
    2480               0 :       if (success) {
    2481               0 :         newType = aResult.GetEnumValue();
    2482                 :       } else {
    2483               0 :         newType = kInputDefaultType->value;
    2484                 :       }
    2485                 : 
    2486               0 :       if (newType != mType) {
    2487                 :         // Make sure to do the check for newType being NS_FORM_INPUT_FILE and
    2488                 :         // the corresponding SetValueInternal() call _before_ we set mType.
    2489                 :         // That way the logic in SetValueInternal() will work right (that logic
    2490                 :         // makes assumptions about our frame based on mType, but we won't have
    2491                 :         // had time to recreate frames yet -- that happens later in the
    2492                 :         // SetAttr() process).
    2493               0 :         if (newType == NS_FORM_INPUT_FILE || mType == NS_FORM_INPUT_FILE) {
    2494                 :           // This call isn't strictly needed any more since we'll never
    2495                 :           // confuse values and filenames. However it's there for backwards
    2496                 :           // compat.
    2497               0 :           ClearFiles(false);
    2498                 :         }
    2499                 : 
    2500               0 :         HandleTypeChange(newType);
    2501                 :       }
    2502                 : 
    2503               0 :       return success;
    2504                 :     }
    2505               0 :     if (aAttribute == nsGkAtoms::width) {
    2506               0 :       return aResult.ParseSpecialIntValue(aValue);
    2507                 :     }
    2508               0 :     if (aAttribute == nsGkAtoms::height) {
    2509               0 :       return aResult.ParseSpecialIntValue(aValue);
    2510                 :     }
    2511               0 :     if (aAttribute == nsGkAtoms::maxlength) {
    2512               0 :       return aResult.ParseNonNegativeIntValue(aValue);
    2513                 :     }
    2514               0 :     if (aAttribute == nsGkAtoms::size) {
    2515               0 :       return aResult.ParsePositiveIntValue(aValue);
    2516                 :     }
    2517               0 :     if (aAttribute == nsGkAtoms::border) {
    2518               0 :       return aResult.ParseIntWithBounds(aValue, 0);
    2519                 :     }
    2520               0 :     if (aAttribute == nsGkAtoms::align) {
    2521               0 :       return ParseAlignValue(aValue, aResult);
    2522                 :     }
    2523               0 :     if (aAttribute == nsGkAtoms::formmethod) {
    2524               0 :       return aResult.ParseEnumValue(aValue, kFormMethodTable, false);
    2525                 :     }
    2526               0 :     if (aAttribute == nsGkAtoms::formenctype) {
    2527               0 :       return aResult.ParseEnumValue(aValue, kFormEnctypeTable, false);
    2528                 :     }
    2529               0 :     if (aAttribute == nsGkAtoms::autocomplete) {
    2530               0 :       return aResult.ParseEnumValue(aValue, kInputAutocompleteTable, false);
    2531                 :     }
    2532               0 :     if (ParseImageAttribute(aAttribute, aValue, aResult)) {
    2533                 :       // We have to call |ParseImageAttribute| unconditionally since we
    2534                 :       // don't know if we're going to have a type="image" attribute yet,
    2535                 :       // (or could have it set dynamically in the future).  See bug
    2536                 :       // 214077.
    2537               0 :       return true;
    2538                 :     }
    2539                 :   }
    2540                 : 
    2541                 :   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
    2542               0 :                                               aResult);
    2543                 : }
    2544                 : 
    2545                 : static void
    2546               0 : MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
    2547                 :                       nsRuleData* aData)
    2548                 : {
    2549               0 :   const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::type);
    2550               0 :   if (value && value->Type() == nsAttrValue::eEnum &&
    2551               0 :       value->GetEnumValue() == NS_FORM_INPUT_IMAGE) {
    2552               0 :     nsGenericHTMLFormElement::MapImageBorderAttributeInto(aAttributes, aData);
    2553               0 :     nsGenericHTMLFormElement::MapImageMarginAttributeInto(aAttributes, aData);
    2554               0 :     nsGenericHTMLFormElement::MapImageSizeAttributesInto(aAttributes, aData);
    2555                 :     // Images treat align as "float"
    2556               0 :     nsGenericHTMLFormElement::MapImageAlignAttributeInto(aAttributes, aData);
    2557                 :   } 
    2558                 : 
    2559               0 :   nsGenericHTMLFormElement::MapCommonAttributesInto(aAttributes, aData);
    2560               0 : }
    2561                 : 
    2562                 : nsChangeHint
    2563               0 : nsHTMLInputElement::GetAttributeChangeHint(const nsIAtom* aAttribute,
    2564                 :                                            PRInt32 aModType) const
    2565                 : {
    2566                 :   nsChangeHint retval =
    2567               0 :     nsGenericHTMLFormElement::GetAttributeChangeHint(aAttribute, aModType);
    2568               0 :   if (aAttribute == nsGkAtoms::type) {
    2569               0 :     NS_UpdateHint(retval, NS_STYLE_HINT_FRAMECHANGE);
    2570               0 :   } else if (mType == NS_FORM_INPUT_IMAGE &&
    2571                 :              (aAttribute == nsGkAtoms::alt ||
    2572                 :               aAttribute == nsGkAtoms::value)) {
    2573                 :     // We might need to rebuild our alt text.  Just go ahead and
    2574                 :     // reconstruct our frame.  This should be quite rare..
    2575               0 :     NS_UpdateHint(retval, NS_STYLE_HINT_FRAMECHANGE);
    2576               0 :   } else if (aAttribute == nsGkAtoms::value) {
    2577               0 :     NS_UpdateHint(retval, NS_STYLE_HINT_REFLOW);
    2578               0 :   } else if (aAttribute == nsGkAtoms::size &&
    2579               0 :              IsSingleLineTextControl(false)) {
    2580               0 :     NS_UpdateHint(retval, NS_STYLE_HINT_REFLOW);
    2581               0 :   } else if (PlaceholderApplies() && aAttribute == nsGkAtoms::placeholder) {
    2582               0 :     NS_UpdateHint(retval, NS_STYLE_HINT_FRAMECHANGE);
    2583                 :   }
    2584               0 :   return retval;
    2585                 : }
    2586                 : 
    2587                 : NS_IMETHODIMP_(bool)
    2588               0 : nsHTMLInputElement::IsAttributeMapped(const nsIAtom* aAttribute) const
    2589                 : {
    2590                 :   static const MappedAttributeEntry attributes[] = {
    2591                 :     { &nsGkAtoms::align },
    2592                 :     { &nsGkAtoms::type },
    2593                 :     { nsnull },
    2594                 :   };
    2595                 : 
    2596                 :   static const MappedAttributeEntry* const map[] = {
    2597                 :     attributes,
    2598                 :     sCommonAttributeMap,
    2599                 :     sImageMarginSizeAttributeMap,
    2600                 :     sImageBorderAttributeMap,
    2601                 :   };
    2602                 : 
    2603               0 :   return FindAttributeDependence(aAttribute, map);
    2604                 : }
    2605                 : 
    2606                 : nsMapRuleToAttributesFunc
    2607               0 : nsHTMLInputElement::GetAttributeMappingFunction() const
    2608                 : {
    2609               0 :   return &MapAttributesIntoRule;
    2610                 : }
    2611                 : 
    2612                 : 
    2613                 : // Controllers Methods
    2614                 : 
    2615                 : NS_IMETHODIMP
    2616               0 : nsHTMLInputElement::GetControllers(nsIControllers** aResult)
    2617                 : {
    2618               0 :   NS_ENSURE_ARG_POINTER(aResult);
    2619                 : 
    2620                 :   //XXX: what about type "file"?
    2621               0 :   if (IsSingleLineTextControl(false))
    2622                 :   {
    2623               0 :     if (!mControllers)
    2624                 :     {
    2625                 :       nsresult rv;
    2626               0 :       mControllers = do_CreateInstance(kXULControllersCID, &rv);
    2627               0 :       NS_ENSURE_SUCCESS(rv, rv);
    2628                 : 
    2629                 :       nsCOMPtr<nsIController>
    2630                 :         controller(do_CreateInstance("@mozilla.org/editor/editorcontroller;1",
    2631               0 :                                      &rv));
    2632               0 :       NS_ENSURE_SUCCESS(rv, rv);
    2633                 : 
    2634               0 :       mControllers->AppendController(controller);
    2635                 : 
    2636                 :       controller = do_CreateInstance("@mozilla.org/editor/editingcontroller;1",
    2637               0 :                                      &rv);
    2638               0 :       NS_ENSURE_SUCCESS(rv, rv);
    2639                 : 
    2640               0 :       mControllers->AppendController(controller);
    2641                 :     }
    2642                 :   }
    2643                 : 
    2644               0 :   *aResult = mControllers;
    2645               0 :   NS_IF_ADDREF(*aResult);
    2646                 : 
    2647               0 :   return NS_OK;
    2648                 : }
    2649                 : 
    2650                 : NS_IMETHODIMP
    2651               0 : nsHTMLInputElement::GetTextLength(PRInt32* aTextLength)
    2652                 : {
    2653               0 :   nsAutoString val;
    2654                 : 
    2655               0 :   nsresult rv = GetValue(val);
    2656                 : 
    2657               0 :   *aTextLength = val.Length();
    2658                 : 
    2659               0 :   return rv;
    2660                 : }
    2661                 : 
    2662                 : NS_IMETHODIMP
    2663               0 : nsHTMLInputElement::SetSelectionRange(PRInt32 aSelectionStart,
    2664                 :                                       PRInt32 aSelectionEnd,
    2665                 :                                       const nsAString& aDirection)
    2666                 : {
    2667               0 :   nsresult rv = NS_ERROR_FAILURE;
    2668               0 :   nsIFormControlFrame* formControlFrame = GetFormControlFrame(true);
    2669                 : 
    2670               0 :   if (formControlFrame) {
    2671               0 :     nsITextControlFrame* textControlFrame = do_QueryFrame(formControlFrame);
    2672               0 :     if (textControlFrame) {
    2673                 :       // Default to forward, even if not specified.
    2674                 :       // Note that we don't currently support directionless selections, so
    2675                 :       // "none" is treated like "forward".
    2676               0 :       nsITextControlFrame::SelectionDirection dir = nsITextControlFrame::eForward;
    2677               0 :       if (aDirection.EqualsLiteral("backward")) {
    2678               0 :         dir = nsITextControlFrame::eBackward;
    2679                 :       }
    2680                 : 
    2681               0 :       rv = textControlFrame->SetSelectionRange(aSelectionStart, aSelectionEnd, dir);
    2682               0 :       if (NS_SUCCEEDED(rv)) {
    2683               0 :         rv = textControlFrame->ScrollSelectionIntoView();
    2684                 :       }
    2685                 :     }
    2686                 :   }
    2687                 : 
    2688               0 :   return rv;
    2689                 : }
    2690                 : 
    2691                 : NS_IMETHODIMP
    2692               0 : nsHTMLInputElement::GetSelectionStart(PRInt32* aSelectionStart)
    2693                 : {
    2694               0 :   NS_ENSURE_ARG_POINTER(aSelectionStart);
    2695                 : 
    2696                 :   PRInt32 selEnd;
    2697               0 :   nsresult rv = GetSelectionRange(aSelectionStart, &selEnd);
    2698                 : 
    2699               0 :   if (NS_FAILED(rv)) {
    2700               0 :     nsTextEditorState *state = GetEditorState();
    2701               0 :     if (state && state->IsSelectionCached()) {
    2702               0 :       *aSelectionStart = state->GetSelectionProperties().mStart;
    2703               0 :       return NS_OK;
    2704                 :     }
    2705                 :   }
    2706               0 :   return rv;
    2707                 : }
    2708                 : 
    2709                 : NS_IMETHODIMP
    2710               0 : nsHTMLInputElement::SetSelectionStart(PRInt32 aSelectionStart)
    2711                 : {
    2712               0 :   nsTextEditorState *state = GetEditorState();
    2713               0 :   if (state && state->IsSelectionCached()) {
    2714               0 :     state->GetSelectionProperties().mStart = aSelectionStart;
    2715               0 :     return NS_OK;
    2716                 :   }
    2717                 : 
    2718               0 :   nsAutoString direction;
    2719               0 :   nsresult rv = GetSelectionDirection(direction);
    2720               0 :   NS_ENSURE_SUCCESS(rv, rv);
    2721                 :   PRInt32 start, end;
    2722               0 :   rv = GetSelectionRange(&start, &end);
    2723               0 :   NS_ENSURE_SUCCESS(rv, rv);
    2724               0 :   start = aSelectionStart;
    2725               0 :   if (end < start) {
    2726               0 :     end = start;
    2727                 :   }
    2728               0 :   return SetSelectionRange(start, end, direction);
    2729                 : }
    2730                 : 
    2731                 : NS_IMETHODIMP
    2732               0 : nsHTMLInputElement::GetSelectionEnd(PRInt32* aSelectionEnd)
    2733                 : {
    2734               0 :   NS_ENSURE_ARG_POINTER(aSelectionEnd);
    2735                 : 
    2736                 :   PRInt32 selStart;
    2737               0 :   nsresult rv = GetSelectionRange(&selStart, aSelectionEnd);
    2738                 : 
    2739               0 :   if (NS_FAILED(rv)) {
    2740               0 :     nsTextEditorState *state = GetEditorState();
    2741               0 :     if (state && state->IsSelectionCached()) {
    2742               0 :       *aSelectionEnd = state->GetSelectionProperties().mEnd;
    2743               0 :       return NS_OK;
    2744                 :     }
    2745                 :   }
    2746               0 :   return rv;
    2747                 : }
    2748                 : 
    2749                 : 
    2750                 : NS_IMETHODIMP
    2751               0 : nsHTMLInputElement::SetSelectionEnd(PRInt32 aSelectionEnd)
    2752                 : {
    2753               0 :   nsTextEditorState *state = GetEditorState();
    2754               0 :   if (state && state->IsSelectionCached()) {
    2755               0 :     state->GetSelectionProperties().mEnd = aSelectionEnd;
    2756               0 :     return NS_OK;
    2757                 :   }
    2758                 : 
    2759               0 :   nsAutoString direction;
    2760               0 :   nsresult rv = GetSelectionDirection(direction);
    2761               0 :   NS_ENSURE_SUCCESS(rv, rv);
    2762                 :   PRInt32 start, end;
    2763               0 :   rv = GetSelectionRange(&start, &end);
    2764               0 :   NS_ENSURE_SUCCESS(rv, rv);
    2765               0 :   end = aSelectionEnd;
    2766               0 :   if (start > end) {
    2767               0 :     start = end;
    2768                 :   }
    2769               0 :   return SetSelectionRange(start, end, direction);
    2770                 : }
    2771                 : 
    2772                 : NS_IMETHODIMP
    2773               0 : nsHTMLInputElement::GetFiles(nsIDOMFileList** aFileList)
    2774                 : {
    2775               0 :   *aFileList = nsnull;
    2776                 : 
    2777               0 :   if (mType != NS_FORM_INPUT_FILE) {
    2778               0 :     return NS_OK;
    2779                 :   }
    2780                 : 
    2781               0 :   if (!mFileList) {
    2782               0 :     mFileList = new nsDOMFileList(static_cast<nsIContent*>(this));
    2783               0 :     if (!mFileList) return NS_ERROR_OUT_OF_MEMORY;
    2784                 : 
    2785               0 :     UpdateFileList();
    2786                 :   }
    2787                 : 
    2788               0 :   NS_ADDREF(*aFileList = mFileList);
    2789                 : 
    2790               0 :   return NS_OK;
    2791                 : }
    2792                 : 
    2793                 : nsresult
    2794               0 : nsHTMLInputElement::GetSelectionRange(PRInt32* aSelectionStart,
    2795                 :                                       PRInt32* aSelectionEnd)
    2796                 : {
    2797               0 :   nsresult rv = NS_ERROR_FAILURE;
    2798               0 :   nsIFormControlFrame* formControlFrame = GetFormControlFrame(true);
    2799                 : 
    2800               0 :   if (formControlFrame) {
    2801               0 :     nsITextControlFrame* textControlFrame = do_QueryFrame(formControlFrame);
    2802               0 :     if (textControlFrame)
    2803               0 :       rv = textControlFrame->GetSelectionRange(aSelectionStart, aSelectionEnd);
    2804                 :   }
    2805                 : 
    2806               0 :   return rv;
    2807                 : }
    2808                 : 
    2809                 : static void
    2810               0 : DirectionToName(nsITextControlFrame::SelectionDirection dir, nsAString& aDirection)
    2811                 : {
    2812               0 :   if (dir == nsITextControlFrame::eNone) {
    2813               0 :     aDirection.AssignLiteral("none");
    2814               0 :   } else if (dir == nsITextControlFrame::eForward) {
    2815               0 :     aDirection.AssignLiteral("forward");
    2816               0 :   } else if (dir == nsITextControlFrame::eBackward) {
    2817               0 :     aDirection.AssignLiteral("backward");
    2818                 :   } else {
    2819               0 :     NS_NOTREACHED("Invalid SelectionDirection value");
    2820                 :   }
    2821               0 : }
    2822                 : 
    2823                 : NS_IMETHODIMP
    2824               0 : nsHTMLInputElement::GetSelectionDirection(nsAString& aDirection)
    2825                 : {
    2826               0 :   nsresult rv = NS_ERROR_FAILURE;
    2827               0 :   nsIFormControlFrame* formControlFrame = GetFormControlFrame(true);
    2828                 : 
    2829               0 :   if (formControlFrame) {
    2830               0 :     nsITextControlFrame* textControlFrame = do_QueryFrame(formControlFrame);
    2831               0 :     if (textControlFrame) {
    2832                 :       nsITextControlFrame::SelectionDirection dir;
    2833               0 :       rv = textControlFrame->GetSelectionRange(nsnull, nsnull, &dir);
    2834               0 :       if (NS_SUCCEEDED(rv)) {
    2835               0 :         DirectionToName(dir, aDirection);
    2836                 :       }
    2837                 :     }
    2838                 :   }
    2839                 : 
    2840               0 :   if (NS_FAILED(rv)) {
    2841               0 :     nsTextEditorState *state = GetEditorState();
    2842               0 :     if (state && state->IsSelectionCached()) {
    2843               0 :       DirectionToName(state->GetSelectionProperties().mDirection, aDirection);
    2844               0 :       return NS_OK;
    2845                 :     }
    2846                 :   }
    2847                 : 
    2848               0 :   return rv;
    2849                 : }
    2850                 : 
    2851                 : NS_IMETHODIMP
    2852               0 : nsHTMLInputElement::SetSelectionDirection(const nsAString& aDirection) {
    2853               0 :   nsTextEditorState *state = GetEditorState();
    2854               0 :   if (state && state->IsSelectionCached()) {
    2855               0 :     nsITextControlFrame::SelectionDirection dir = nsITextControlFrame::eNone;
    2856               0 :     if (aDirection.EqualsLiteral("forward")) {
    2857               0 :       dir = nsITextControlFrame::eForward;
    2858               0 :     } else if (aDirection.EqualsLiteral("backward")) {
    2859               0 :       dir = nsITextControlFrame::eBackward;
    2860                 :     }
    2861               0 :     state->GetSelectionProperties().mDirection = dir;
    2862               0 :     return NS_OK;
    2863                 :   }
    2864                 : 
    2865                 :   PRInt32 start, end;
    2866               0 :   nsresult rv = GetSelectionRange(&start, &end);
    2867               0 :   if (NS_SUCCEEDED(rv)) {
    2868               0 :     rv = SetSelectionRange(start, end, aDirection);
    2869                 :   }
    2870                 : 
    2871               0 :   return rv;
    2872                 : }
    2873                 : 
    2874                 : NS_IMETHODIMP
    2875               0 : nsHTMLInputElement::GetPhonetic(nsAString& aPhonetic)
    2876                 : {
    2877               0 :   aPhonetic.Truncate();
    2878               0 :   nsIFormControlFrame* formControlFrame = GetFormControlFrame(true);
    2879                 : 
    2880               0 :   if (formControlFrame) {
    2881               0 :     nsITextControlFrame* textControlFrame = do_QueryFrame(formControlFrame);
    2882               0 :     if (textControlFrame)
    2883               0 :       textControlFrame->GetPhonetic(aPhonetic);
    2884                 :   }
    2885                 : 
    2886               0 :   return NS_OK;
    2887                 : }
    2888                 : 
    2889                 : #ifdef ACCESSIBILITY
    2890                 : /*static*/ nsresult
    2891               0 : FireEventForAccessibility(nsIDOMHTMLInputElement* aTarget,
    2892                 :                           nsPresContext* aPresContext,
    2893                 :                           const nsAString& aEventType)
    2894                 : {
    2895               0 :   nsCOMPtr<nsIDOMEvent> event;
    2896               0 :   if (NS_SUCCEEDED(nsEventDispatcher::CreateEvent(aPresContext, nsnull,
    2897                 :                                                   NS_LITERAL_STRING("Events"),
    2898                 :                                                   getter_AddRefs(event)))) {
    2899               0 :     event->InitEvent(aEventType, true, true);
    2900                 : 
    2901               0 :     nsCOMPtr<nsIPrivateDOMEvent> privateEvent(do_QueryInterface(event));
    2902               0 :     if (privateEvent) {
    2903               0 :       privateEvent->SetTrusted(true);
    2904                 :     }
    2905                 : 
    2906               0 :     nsEventDispatcher::DispatchDOMEvent(aTarget, nsnull, event, aPresContext, nsnull);
    2907                 :   }
    2908                 : 
    2909               0 :   return NS_OK;
    2910                 : }
    2911                 : #endif
    2912                 : 
    2913                 : nsresult
    2914               0 : nsHTMLInputElement::SetDefaultValueAsValue()
    2915                 : {
    2916               0 :   NS_ASSERTION(GetValueMode() == VALUE_MODE_VALUE,
    2917                 :                "GetValueMode() should return VALUE_MODE_VALUE!");
    2918                 : 
    2919                 :   // The element has a content attribute value different from it's value when
    2920                 :   // it's in the value mode value.
    2921               0 :   nsAutoString resetVal;
    2922               0 :   GetDefaultValue(resetVal);
    2923                 : 
    2924                 :   // SetValueInternal is going to sanitize the value.
    2925               0 :   return SetValueInternal(resetVal, false, false);
    2926                 : }
    2927                 : 
    2928                 : NS_IMETHODIMP
    2929               0 : nsHTMLInputElement::Reset()
    2930                 : {
    2931                 :   // We should be able to reset all dirty flags regardless of the type.
    2932               0 :   SetCheckedChanged(false);
    2933               0 :   SetValueChanged(false);
    2934                 : 
    2935               0 :   switch (GetValueMode()) {
    2936                 :     case VALUE_MODE_VALUE:
    2937               0 :       return SetDefaultValueAsValue();
    2938                 :     case VALUE_MODE_DEFAULT_ON:
    2939               0 :       return DoSetChecked(DefaultChecked(), true, false);
    2940                 :     case VALUE_MODE_FILENAME:
    2941               0 :       ClearFiles(false);
    2942               0 :       return NS_OK;
    2943                 :     case VALUE_MODE_DEFAULT:
    2944                 :     default:
    2945               0 :       return NS_OK;
    2946                 :   }
    2947                 : }
    2948                 : 
    2949                 : NS_IMETHODIMP
    2950               0 : nsHTMLInputElement::SubmitNamesValues(nsFormSubmission* aFormSubmission)
    2951                 : {
    2952                 :   // Disabled elements don't submit
    2953                 :   // For type=reset, and type=button, we just never submit, period.
    2954                 :   // For type=image and type=button, we only submit if we were the button
    2955                 :   // pressed
    2956                 :   // For type=radio and type=checkbox, we only submit if checked=true
    2957               0 :   if (IsDisabled() || mType == NS_FORM_INPUT_RESET ||
    2958                 :       mType == NS_FORM_INPUT_BUTTON ||
    2959                 :       ((mType == NS_FORM_INPUT_SUBMIT || mType == NS_FORM_INPUT_IMAGE) &&
    2960               0 :        aFormSubmission->GetOriginatingElement() != this) ||
    2961                 :       ((mType == NS_FORM_INPUT_RADIO || mType == NS_FORM_INPUT_CHECKBOX) &&
    2962               0 :        !mChecked)) {
    2963               0 :     return NS_OK;
    2964                 :   }
    2965                 : 
    2966                 :   // Get the name
    2967               0 :   nsAutoString name;
    2968               0 :   GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
    2969                 : 
    2970                 :   // Submit .x, .y for input type=image
    2971               0 :   if (mType == NS_FORM_INPUT_IMAGE) {
    2972                 :     // Get a property set by the frame to find out where it was clicked.
    2973                 :     nsIntPoint* lastClickedPoint =
    2974               0 :       static_cast<nsIntPoint*>(GetProperty(nsGkAtoms::imageClickedPoint));
    2975                 :     PRInt32 x, y;
    2976               0 :     if (lastClickedPoint) {
    2977                 :       // Convert the values to strings for submission
    2978               0 :       x = lastClickedPoint->x;
    2979               0 :       y = lastClickedPoint->y;
    2980                 :     } else {
    2981               0 :       x = y = 0;
    2982                 :     }
    2983                 : 
    2984               0 :     nsAutoString xVal, yVal;
    2985               0 :     xVal.AppendInt(x);
    2986               0 :     yVal.AppendInt(y);
    2987                 : 
    2988               0 :     if (!name.IsEmpty()) {
    2989               0 :       aFormSubmission->AddNameValuePair(name + NS_LITERAL_STRING(".x"), xVal);
    2990               0 :       aFormSubmission->AddNameValuePair(name + NS_LITERAL_STRING(".y"), yVal);
    2991                 :     } else {
    2992                 :       // If the Image Element has no name, simply return x and y
    2993                 :       // to Nav and IE compatibility.
    2994               0 :       aFormSubmission->AddNameValuePair(NS_LITERAL_STRING("x"), xVal);
    2995               0 :       aFormSubmission->AddNameValuePair(NS_LITERAL_STRING("y"), yVal);
    2996                 :     }
    2997                 : 
    2998               0 :     return NS_OK;
    2999                 :   }
    3000                 : 
    3001                 :   //
    3002                 :   // Submit name=value
    3003                 :   //
    3004                 : 
    3005                 :   // If name not there, don't submit
    3006               0 :   if (name.IsEmpty()) {
    3007               0 :     return NS_OK;
    3008                 :   }
    3009                 : 
    3010                 :   // Get the value
    3011               0 :   nsAutoString value;
    3012               0 :   nsresult rv = GetValue(value);
    3013               0 :   if (NS_FAILED(rv)) {
    3014               0 :     return rv;
    3015                 :   }
    3016                 : 
    3017               0 :   if (mType == NS_FORM_INPUT_SUBMIT && value.IsEmpty() &&
    3018               0 :       !HasAttr(kNameSpaceID_None, nsGkAtoms::value)) {
    3019                 :     // Get our default value, which is the same as our default label
    3020               0 :     nsXPIDLString defaultValue;
    3021                 :     nsContentUtils::GetLocalizedString(nsContentUtils::eFORMS_PROPERTIES,
    3022               0 :                                        "Submit", defaultValue);
    3023               0 :     value = defaultValue;
    3024                 :   }
    3025                 :       
    3026                 :   //
    3027                 :   // Submit file if its input type=file and this encoding method accepts files
    3028                 :   //
    3029               0 :   if (mType == NS_FORM_INPUT_FILE) {
    3030                 :     // Submit files
    3031                 : 
    3032               0 :     const nsCOMArray<nsIDOMFile>& files = GetFiles();
    3033                 : 
    3034               0 :     for (PRInt32 i = 0; i < files.Count(); ++i) {
    3035               0 :       aFormSubmission->AddNameFilePair(name, files[i]);
    3036                 :     }
    3037                 : 
    3038               0 :     if (files.Count() == 0) {
    3039                 :       // If no file was selected, pretend we had an empty file with an
    3040                 :       // empty filename.
    3041               0 :       aFormSubmission->AddNameFilePair(name, nsnull);
    3042                 : 
    3043                 :     }
    3044                 : 
    3045               0 :     return NS_OK;
    3046                 :   }
    3047                 : 
    3048               0 :   if (mType == NS_FORM_INPUT_HIDDEN && name.EqualsLiteral("_charset_")) {
    3049               0 :     nsCString charset;
    3050               0 :     aFormSubmission->GetCharset(charset);
    3051                 :     return aFormSubmission->AddNameValuePair(name,
    3052               0 :                                              NS_ConvertASCIItoUTF16(charset));
    3053                 :   }
    3054               0 :   if (IsSingleLineTextControl(true) &&
    3055               0 :       name.EqualsLiteral("isindex") &&
    3056               0 :       aFormSubmission->SupportsIsindexSubmission()) {
    3057               0 :     return aFormSubmission->AddIsindex(value);
    3058                 :   }
    3059               0 :   return aFormSubmission->AddNameValuePair(name, value);
    3060                 : }
    3061                 : 
    3062                 : 
    3063                 : NS_IMETHODIMP
    3064               3 : nsHTMLInputElement::SaveState()
    3065                 : {
    3066               6 :   nsRefPtr<nsHTMLInputElementState> inputState;
    3067               3 :   switch (mType) {
    3068                 :     case NS_FORM_INPUT_CHECKBOX:
    3069                 :     case NS_FORM_INPUT_RADIO:
    3070                 :       {
    3071               0 :         if (mCheckedChanged) {
    3072               0 :           inputState = new nsHTMLInputElementState();
    3073               0 :           inputState->SetChecked(mChecked);
    3074                 :         }
    3075               0 :         break;
    3076                 :       }
    3077                 : 
    3078                 :     // Never save passwords in session history
    3079                 :     case NS_FORM_INPUT_PASSWORD:
    3080               0 :       break;
    3081                 :     case NS_FORM_INPUT_EMAIL:
    3082                 :     case NS_FORM_INPUT_SEARCH:
    3083                 :     case NS_FORM_INPUT_TEXT:
    3084                 :     case NS_FORM_INPUT_TEL:
    3085                 :     case NS_FORM_INPUT_URL:
    3086                 :     case NS_FORM_INPUT_HIDDEN:
    3087                 :       {
    3088               3 :         if (mValueChanged) {
    3089               0 :           inputState = new nsHTMLInputElementState();
    3090               0 :           nsAutoString value;
    3091               0 :           GetValue(value);
    3092                 :           DebugOnly<nsresult> rv =
    3093                 :             nsLinebreakConverter::ConvertStringLineBreaks(
    3094                 :                  value,
    3095                 :                  nsLinebreakConverter::eLinebreakPlatform,
    3096               0 :                  nsLinebreakConverter::eLinebreakContent);
    3097               0 :           NS_ASSERTION(NS_SUCCEEDED(rv), "Converting linebreaks failed!");
    3098               0 :           inputState->SetValue(value);
    3099                 :        }
    3100               3 :       break;
    3101                 :     }
    3102                 :     case NS_FORM_INPUT_FILE:
    3103                 :       {
    3104               0 :         if (mFiles.Count()) {
    3105               0 :           inputState = new nsHTMLInputElementState();
    3106               0 :           inputState->SetFiles(mFiles);
    3107                 :         }
    3108               0 :         break;
    3109                 :       }
    3110                 :   }
    3111                 :   
    3112               3 :   nsresult rv = NS_OK;
    3113               3 :   nsPresState* state = nsnull;
    3114               3 :   if (inputState) {
    3115               0 :     rv = GetPrimaryPresState(this, &state);
    3116               0 :     if (state) {
    3117               0 :       state->SetStateProperty(inputState);
    3118                 :     }
    3119                 :   }
    3120                 : 
    3121               3 :   if (mDisabledChanged) {
    3122               0 :     rv |= GetPrimaryPresState(this, &state);
    3123               0 :     if (state) {
    3124                 :       // We do not want to save the real disabled state but the disabled
    3125                 :       // attribute.
    3126               0 :       state->SetDisabled(HasAttr(kNameSpaceID_None, nsGkAtoms::disabled));
    3127                 :     }
    3128                 :   }
    3129                 : 
    3130               3 :   return rv;
    3131                 : }
    3132                 : 
    3133                 : void
    3134               1 : nsHTMLInputElement::DoneCreatingElement()
    3135                 : {
    3136               1 :   mParserCreating = false;
    3137                 : 
    3138                 :   //
    3139                 :   // Restore state as needed.  Note that disabled state applies to all control
    3140                 :   // types.
    3141                 :   //
    3142                 :   bool restoredCheckedState =
    3143               1 :     !mInhibitRestoration && RestoreFormControlState(this, this);
    3144                 : 
    3145                 :   //
    3146                 :   // If restore does not occur, we initialize .checked using the CHECKED
    3147                 :   // property.
    3148                 :   //
    3149               1 :   if (!restoredCheckedState && mShouldInitChecked) {
    3150               0 :     DoSetChecked(DefaultChecked(), false, true);
    3151               0 :     DoSetCheckedChanged(false, false);
    3152                 :   }
    3153                 : 
    3154                 :   // Sanitize the value.
    3155               1 :   if (GetValueMode() == VALUE_MODE_VALUE) {
    3156               2 :     nsAutoString aValue;
    3157               1 :     GetValue(aValue);
    3158               1 :     SetValueInternal(aValue, false, false);
    3159                 :   }
    3160                 : 
    3161               1 :   mShouldInitChecked = false;
    3162               1 : }
    3163                 : 
    3164                 : nsEventStates
    3165               5 : nsHTMLInputElement::IntrinsicState() const
    3166                 : {
    3167                 :   // If you add states here, and they're type-dependent, you need to add them
    3168                 :   // to the type case in AfterSetAttr.
    3169                 :   
    3170               5 :   nsEventStates state = nsGenericHTMLFormElement::IntrinsicState();
    3171               5 :   if (mType == NS_FORM_INPUT_CHECKBOX || mType == NS_FORM_INPUT_RADIO) {
    3172                 :     // Check current checked state (:checked)
    3173               0 :     if (mChecked) {
    3174               0 :       state |= NS_EVENT_STATE_CHECKED;
    3175                 :     }
    3176                 : 
    3177                 :     // Check current indeterminate state (:indeterminate)
    3178               0 :     if (mType == NS_FORM_INPUT_CHECKBOX && mIndeterminate) {
    3179               0 :       state |= NS_EVENT_STATE_INDETERMINATE;
    3180                 :     }
    3181                 : 
    3182                 :     // Check whether we are the default checked element (:default)
    3183               0 :     if (DefaultChecked()) {
    3184               0 :       state |= NS_EVENT_STATE_DEFAULT;
    3185                 :     }
    3186               5 :   } else if (mType == NS_FORM_INPUT_IMAGE) {
    3187               0 :     state |= nsImageLoadingContent::ImageState();
    3188                 :   }
    3189                 : 
    3190               5 :   if (DoesRequiredApply() && HasAttr(kNameSpaceID_None, nsGkAtoms::required)) {
    3191               0 :     state |= NS_EVENT_STATE_REQUIRED;
    3192                 :   } else {
    3193               5 :     state |= NS_EVENT_STATE_OPTIONAL;
    3194                 :   }
    3195                 : 
    3196               5 :   if (IsCandidateForConstraintValidation()) {
    3197               5 :     if (IsValid()) {
    3198               5 :       state |= NS_EVENT_STATE_VALID;
    3199                 :     } else {
    3200               0 :       state |= NS_EVENT_STATE_INVALID;
    3201                 : 
    3202               0 :       if ((!mForm || !mForm->HasAttr(kNameSpaceID_None, nsGkAtoms::novalidate)) &&
    3203               0 :           (GetValidityState(VALIDITY_STATE_CUSTOM_ERROR) ||
    3204               0 :            (mCanShowInvalidUI && ShouldShowValidityUI()))) {
    3205               0 :         state |= NS_EVENT_STATE_MOZ_UI_INVALID;
    3206                 :       }
    3207                 :     }
    3208                 : 
    3209                 :     // :-moz-ui-valid applies if all of the following conditions are true:
    3210                 :     // 1. The element is not focused, or had either :-moz-ui-valid or
    3211                 :     //    :-moz-ui-invalid applying before it was focused ;
    3212                 :     // 2. The element is either valid or isn't allowed to have
    3213                 :     //    :-moz-ui-invalid applying ;
    3214                 :     // 3. The element has no form owner or its form owner doesn't have the
    3215                 :     //    novalidate attribute set ;
    3216                 :     // 4. The element has already been modified or the user tried to submit the
    3217                 :     //    form owner while invalid.
    3218              10 :     if ((!mForm || !mForm->HasAttr(kNameSpaceID_None, nsGkAtoms::novalidate)) &&
    3219               5 :         (mCanShowValidUI && ShouldShowValidityUI() &&
    3220               0 :          (IsValid() || (!state.HasState(NS_EVENT_STATE_MOZ_UI_INVALID) &&
    3221               0 :                         !mCanShowInvalidUI)))) {
    3222               0 :       state |= NS_EVENT_STATE_MOZ_UI_VALID;
    3223                 :     }
    3224                 :   }
    3225                 : 
    3226               5 :   if (PlaceholderApplies() && HasAttr(kNameSpaceID_None, nsGkAtoms::placeholder) &&
    3227               0 :       !nsContentUtils::IsFocusedContent((nsIContent*)(this)) &&
    3228               0 :       IsValueEmpty()) {
    3229               0 :     state |= NS_EVENT_STATE_MOZ_PLACEHOLDER;
    3230                 :   }
    3231                 : 
    3232               5 :   if (mForm && !mForm->GetValidity() && IsSubmitControl()) {
    3233               0 :     state |= NS_EVENT_STATE_MOZ_SUBMITINVALID;
    3234                 :   }
    3235                 : 
    3236                 :   return state;
    3237                 : }
    3238                 : 
    3239                 : bool
    3240               0 : nsHTMLInputElement::RestoreState(nsPresState* aState)
    3241                 : {
    3242               0 :   bool restoredCheckedState = false;
    3243                 : 
    3244                 :   nsCOMPtr<nsHTMLInputElementState> inputState
    3245               0 :     (do_QueryInterface(aState->GetStateProperty()));
    3246                 : 
    3247               0 :   if (inputState) {
    3248               0 :     switch (mType) {
    3249                 :       case NS_FORM_INPUT_CHECKBOX:
    3250                 :       case NS_FORM_INPUT_RADIO:
    3251                 :         {
    3252               0 :           if (inputState->IsCheckedSet()) {
    3253               0 :             restoredCheckedState = true;
    3254               0 :             DoSetChecked(inputState->GetChecked(), true, true);
    3255                 :           }
    3256               0 :           break;
    3257                 :         }
    3258                 : 
    3259                 :       case NS_FORM_INPUT_EMAIL:
    3260                 :       case NS_FORM_INPUT_SEARCH:
    3261                 :       case NS_FORM_INPUT_TEXT:
    3262                 :       case NS_FORM_INPUT_TEL:
    3263                 :       case NS_FORM_INPUT_URL:
    3264                 :       case NS_FORM_INPUT_HIDDEN:
    3265                 :         {
    3266               0 :           SetValueInternal(inputState->GetValue(), false, true);
    3267               0 :           break;
    3268                 :         }
    3269                 :       case NS_FORM_INPUT_FILE:
    3270                 :         {
    3271               0 :           const nsCOMArray<nsIDOMFile>& files = inputState->GetFiles();
    3272               0 :           SetFiles(files, true);
    3273               0 :           break;
    3274                 :         }
    3275                 :     }
    3276                 :   }
    3277                 : 
    3278               0 :   if (aState->IsDisabledSet()) {
    3279               0 :     SetDisabled(aState->GetDisabled());
    3280                 :   }
    3281                 : 
    3282               0 :   return restoredCheckedState;
    3283                 : }
    3284                 : 
    3285                 : bool
    3286               0 : nsHTMLInputElement::AllowDrop()
    3287                 : {
    3288                 :   // Allow drop on anything other than file inputs.
    3289                 : 
    3290               0 :   return mType != NS_FORM_INPUT_FILE;
    3291                 : }
    3292                 : 
    3293                 : /*
    3294                 :  * Radio group stuff
    3295                 :  */
    3296                 : 
    3297                 : void
    3298               0 : nsHTMLInputElement::AddedToRadioGroup()
    3299                 : {
    3300                 :   // Make sure not to notify if we're still being created by the parser
    3301               0 :   bool notify = !mParserCreating;
    3302                 : 
    3303                 :   //
    3304                 :   //  If the input element is not in a form and
    3305                 :   //  not in a document, we just need to return.
    3306                 :   //
    3307               0 :   if (!mForm && !(IsInDoc() && GetParent())) {
    3308               0 :     return;
    3309                 :   }
    3310                 : 
    3311                 :   //
    3312                 :   // If the input element is checked, and we add it to the group, it will
    3313                 :   // deselect whatever is currently selected in that group
    3314                 :   //
    3315               0 :   if (mChecked) {
    3316                 :     //
    3317                 :     // If it is checked, call "RadioSetChecked" to perform the selection/
    3318                 :     // deselection ritual.  This has the side effect of repainting the
    3319                 :     // radio button, but as adding a checked radio button into the group
    3320                 :     // should not be that common an occurrence, I think we can live with
    3321                 :     // that.
    3322                 :     //
    3323               0 :     RadioSetChecked(notify);
    3324                 :   }
    3325                 : 
    3326                 :   //
    3327                 :   // For integrity purposes, we have to ensure that "checkedChanged" is
    3328                 :   // the same for this new element as for all the others in the group
    3329                 :   //
    3330               0 :   bool checkedChanged = mCheckedChanged;
    3331                 : 
    3332                 :   nsCOMPtr<nsIRadioVisitor> visitor =
    3333               0 :     new nsRadioGetCheckedChangedVisitor(&checkedChanged, this);
    3334               0 :   VisitGroup(visitor, notify);
    3335                 : 
    3336               0 :   SetCheckedChangedInternal(checkedChanged);
    3337                 : 
    3338                 :   //
    3339                 :   // Add the radio to the radio group container.
    3340                 :   //
    3341               0 :   nsCOMPtr<nsIRadioGroupContainer> container = GetRadioGroupContainer();
    3342               0 :   if (container) {
    3343               0 :     nsAutoString name;
    3344               0 :     GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
    3345               0 :     container->AddToRadioGroup(name, static_cast<nsIFormControl*>(this));
    3346                 : 
    3347                 :     // We initialize the validity of the element to the validity of the group
    3348                 :     // because we assume UpdateValueMissingState() will be called after.
    3349                 :     SetValidityState(VALIDITY_STATE_VALUE_MISSING,
    3350               0 :                      container->GetValueMissingState(name));
    3351                 :   }
    3352                 : }
    3353                 : 
    3354                 : void
    3355               0 : nsHTMLInputElement::WillRemoveFromRadioGroup()
    3356                 : {
    3357               0 :   nsIRadioGroupContainer* container = GetRadioGroupContainer();
    3358               0 :   if (!container) {
    3359               0 :     return;
    3360                 :   }
    3361                 : 
    3362               0 :   nsAutoString name;
    3363               0 :   GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
    3364                 : 
    3365                 :   // If this button was checked, we need to notify the group that there is no
    3366                 :   // longer a selected radio button
    3367               0 :   if (mChecked) {
    3368               0 :     container->SetCurrentRadioButton(name, nsnull);
    3369                 :   }
    3370                 : 
    3371                 :   // Remove this radio from its group in the container.
    3372                 :   // We need to call UpdateValueMissingValidityStateForRadio before to make sure
    3373                 :   // the group validity is updated (with this element being ignored).
    3374               0 :   UpdateValueMissingValidityStateForRadio(true);
    3375               0 :   container->RemoveFromRadioGroup(name, static_cast<nsIFormControl*>(this));
    3376                 : }
    3377                 : 
    3378                 : bool
    3379               0 : nsHTMLInputElement::IsHTMLFocusable(bool aWithMouse, bool *aIsFocusable, PRInt32 *aTabIndex)
    3380                 : {
    3381               0 :   if (nsGenericHTMLFormElement::IsHTMLFocusable(aWithMouse, aIsFocusable, aTabIndex)) {
    3382               0 :     return true;
    3383                 :   }
    3384                 : 
    3385               0 :   if (IsDisabled()) {
    3386               0 :     *aIsFocusable = false;
    3387               0 :     return true;
    3388                 :   }
    3389                 : 
    3390               0 :   if (IsSingleLineTextControl(false)) {
    3391               0 :     *aIsFocusable = true;
    3392               0 :     return false;
    3393                 :   }
    3394                 : 
    3395                 : #ifdef XP_MACOSX
    3396                 :   const bool defaultFocusable = !aWithMouse || nsFocusManager::sMouseFocusesFormControl;
    3397                 : #else
    3398               0 :   const bool defaultFocusable = true;
    3399                 : #endif
    3400                 : 
    3401               0 :   if (mType == NS_FORM_INPUT_FILE) {
    3402               0 :     if (aTabIndex) {
    3403               0 :       *aTabIndex = -1;
    3404                 :     }
    3405               0 :     *aIsFocusable = defaultFocusable;
    3406               0 :     return true;
    3407                 :   }
    3408                 : 
    3409               0 :   if (mType == NS_FORM_INPUT_HIDDEN) {
    3410               0 :     if (aTabIndex) {
    3411               0 :       *aTabIndex = -1;
    3412                 :     }
    3413               0 :     *aIsFocusable = false;
    3414               0 :     return false;
    3415                 :   }
    3416                 : 
    3417               0 :   if (!aTabIndex) {
    3418                 :     // The other controls are all focusable
    3419               0 :     *aIsFocusable = defaultFocusable;
    3420               0 :     return false;
    3421                 :   }
    3422                 : 
    3423               0 :   if (mType != NS_FORM_INPUT_RADIO) {
    3424               0 :     *aIsFocusable = defaultFocusable;
    3425               0 :     return false;
    3426                 :   }
    3427                 : 
    3428               0 :   if (mChecked) {
    3429                 :     // Selected radio buttons are tabbable
    3430               0 :     *aIsFocusable = defaultFocusable;
    3431               0 :     return false;
    3432                 :   }
    3433                 : 
    3434                 :   // Current radio button is not selected.
    3435                 :   // But make it tabbable if nothing in group is selected.
    3436               0 :   nsIRadioGroupContainer* container = GetRadioGroupContainer();
    3437               0 :   if (!container) {
    3438               0 :     *aIsFocusable = defaultFocusable;
    3439               0 :     return false;
    3440                 :   }
    3441                 : 
    3442               0 :   nsAutoString name;
    3443               0 :   GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
    3444                 : 
    3445               0 :   nsCOMPtr<nsIDOMHTMLInputElement> currentRadio;
    3446               0 :   container->GetCurrentRadioButton(name, getter_AddRefs(currentRadio));
    3447               0 :   if (currentRadio) {
    3448               0 :     *aTabIndex = -1;
    3449                 :   }
    3450               0 :   *aIsFocusable = defaultFocusable;
    3451               0 :   return false;
    3452                 : }
    3453                 : 
    3454                 : nsresult
    3455               0 : nsHTMLInputElement::VisitGroup(nsIRadioVisitor* aVisitor, bool aFlushContent)
    3456                 : {
    3457               0 :   nsIRadioGroupContainer* container = GetRadioGroupContainer();
    3458               0 :   if (container) {
    3459               0 :     nsAutoString name;
    3460               0 :     GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
    3461               0 :     return container->WalkRadioGroup(name, aVisitor, aFlushContent);
    3462                 :   }
    3463                 : 
    3464               0 :   aVisitor->Visit(this);
    3465               0 :   return NS_OK;
    3466                 : }
    3467                 : 
    3468                 : nsHTMLInputElement::ValueModeType
    3469               9 : nsHTMLInputElement::GetValueMode() const
    3470                 : {
    3471               9 :   switch (mType)
    3472                 :   {
    3473                 :     case NS_FORM_INPUT_HIDDEN:
    3474                 :     case NS_FORM_INPUT_SUBMIT:
    3475                 :     case NS_FORM_INPUT_BUTTON:
    3476                 :     case NS_FORM_INPUT_RESET:
    3477                 :     case NS_FORM_INPUT_IMAGE:
    3478               0 :       return VALUE_MODE_DEFAULT;
    3479                 :     case NS_FORM_INPUT_CHECKBOX:
    3480                 :     case NS_FORM_INPUT_RADIO:
    3481               0 :       return VALUE_MODE_DEFAULT_ON;
    3482                 :     case NS_FORM_INPUT_FILE:
    3483               0 :       return VALUE_MODE_FILENAME;
    3484                 : #ifdef DEBUG
    3485                 :     case NS_FORM_INPUT_TEXT:
    3486                 :     case NS_FORM_INPUT_PASSWORD:
    3487                 :     case NS_FORM_INPUT_SEARCH:
    3488                 :     case NS_FORM_INPUT_TEL:
    3489                 :     case NS_FORM_INPUT_EMAIL:
    3490                 :     case NS_FORM_INPUT_URL:
    3491               9 :       return VALUE_MODE_VALUE;
    3492                 :     default:
    3493               0 :       NS_NOTYETIMPLEMENTED("Unexpected input type in GetValueMode()");
    3494               0 :       return VALUE_MODE_VALUE;
    3495                 : #else // DEBUG
    3496                 :     default:
    3497                 :       return VALUE_MODE_VALUE;
    3498                 : #endif // DEBUG
    3499                 :   }
    3500                 : }
    3501                 : 
    3502                 : bool
    3503               0 : nsHTMLInputElement::IsMutable() const
    3504                 : {
    3505               0 :   return !IsDisabled() && GetCurrentDoc() &&
    3506               0 :          !(DoesReadOnlyApply() &&
    3507               0 :            HasAttr(kNameSpaceID_None, nsGkAtoms::readonly));
    3508                 : }
    3509                 : 
    3510                 : bool
    3511               0 : nsHTMLInputElement::DoesReadOnlyApply() const
    3512                 : {
    3513               0 :   switch (mType)
    3514                 :   {
    3515                 :     case NS_FORM_INPUT_HIDDEN:
    3516                 :     case NS_FORM_INPUT_BUTTON:
    3517                 :     case NS_FORM_INPUT_IMAGE:
    3518                 :     case NS_FORM_INPUT_RESET:
    3519                 :     case NS_FORM_INPUT_SUBMIT:
    3520                 :     case NS_FORM_INPUT_RADIO:
    3521                 :     case NS_FORM_INPUT_FILE:
    3522                 :     case NS_FORM_INPUT_CHECKBOX:
    3523                 :     // TODO:
    3524                 :     // case NS_FORM_INPUT_COLOR:
    3525                 :     // case NS_FORM_INPUT_RANGE:
    3526               0 :       return false;
    3527                 : #ifdef DEBUG
    3528                 :     case NS_FORM_INPUT_TEXT:
    3529                 :     case NS_FORM_INPUT_PASSWORD:
    3530                 :     case NS_FORM_INPUT_SEARCH:
    3531                 :     case NS_FORM_INPUT_TEL:
    3532                 :     case NS_FORM_INPUT_EMAIL:
    3533                 :     case NS_FORM_INPUT_URL:
    3534               0 :       return true;
    3535                 :     default:
    3536               0 :       NS_NOTYETIMPLEMENTED("Unexpected input type in DoesReadOnlyApply()");
    3537               0 :       return true;
    3538                 : #else // DEBUG
    3539                 :     default:
    3540                 :       return true;
    3541                 : #endif // DEBUG
    3542                 :   }
    3543                 : }
    3544                 : 
    3545                 : bool
    3546               5 : nsHTMLInputElement::DoesRequiredApply() const
    3547                 : {
    3548               5 :   switch (mType)
    3549                 :   {
    3550                 :     case NS_FORM_INPUT_HIDDEN:
    3551                 :     case NS_FORM_INPUT_BUTTON:
    3552                 :     case NS_FORM_INPUT_IMAGE:
    3553                 :     case NS_FORM_INPUT_RESET:
    3554                 :     case NS_FORM_INPUT_SUBMIT:
    3555                 :     // TODO:
    3556                 :     // case NS_FORM_INPUT_COLOR:
    3557                 :     // case NS_FORM_INPUT_RANGE:
    3558               0 :       return false;
    3559                 : #ifdef DEBUG
    3560                 :     case NS_FORM_INPUT_RADIO:
    3561                 :     case NS_FORM_INPUT_CHECKBOX:
    3562                 :     case NS_FORM_INPUT_FILE:
    3563                 :     case NS_FORM_INPUT_TEXT:
    3564                 :     case NS_FORM_INPUT_PASSWORD:
    3565                 :     case NS_FORM_INPUT_SEARCH:
    3566                 :     case NS_FORM_INPUT_TEL:
    3567                 :     case NS_FORM_INPUT_EMAIL:
    3568                 :     case NS_FORM_INPUT_URL:
    3569               5 :       return true;
    3570                 :     default:
    3571               0 :       NS_NOTYETIMPLEMENTED("Unexpected input type in DoesRequiredApply()");
    3572               0 :       return true;
    3573                 : #else // DEBUG
    3574                 :     default:
    3575                 :       return true;
    3576                 : #endif // DEBUG
    3577                 :   }
    3578                 : }
    3579                 : 
    3580                 : bool
    3581               1 : nsHTMLInputElement::DoesPatternApply() const
    3582                 : {
    3583               1 :   return IsSingleLineTextControl(false);
    3584                 : }
    3585                 : 
    3586                 : // nsIConstraintValidation
    3587                 : 
    3588                 : NS_IMETHODIMP
    3589               0 : nsHTMLInputElement::SetCustomValidity(const nsAString& aError)
    3590                 : {
    3591               0 :   nsIConstraintValidation::SetCustomValidity(aError);
    3592                 : 
    3593               0 :   UpdateState(true);
    3594                 : 
    3595               0 :   return NS_OK;
    3596                 : }
    3597                 : 
    3598                 : bool
    3599               0 : nsHTMLInputElement::IsTooLong()
    3600                 : {
    3601               0 :   if (!MaxLengthApplies() ||
    3602               0 :       !HasAttr(kNameSpaceID_None, nsGkAtoms::maxlength) ||
    3603               0 :       !mValueChanged) {
    3604               0 :     return false;
    3605                 :   }
    3606                 : 
    3607               0 :   PRInt32 maxLength = -1;
    3608               0 :   GetMaxLength(&maxLength);
    3609                 : 
    3610                 :   // Maxlength of -1 means parsing error.
    3611               0 :   if (maxLength == -1) {
    3612               0 :     return false;
    3613                 :   }
    3614                 : 
    3615               0 :   PRInt32 textLength = -1;
    3616               0 :   GetTextLength(&textLength);
    3617                 : 
    3618               0 :   return textLength > maxLength;
    3619                 : }
    3620                 : 
    3621                 : bool
    3622               5 : nsHTMLInputElement::IsValueMissing() const
    3623                 : {
    3624               5 :   if (!HasAttr(kNameSpaceID_None, nsGkAtoms::required) ||
    3625               0 :       !DoesRequiredApply()) {
    3626               5 :     return false;
    3627                 :   }
    3628                 : 
    3629               0 :   if (GetValueMode() == VALUE_MODE_VALUE) {
    3630               0 :     if (!IsMutable()) {
    3631               0 :       return false;
    3632                 :     }
    3633                 : 
    3634               0 :     return IsValueEmpty();
    3635                 :   }
    3636                 : 
    3637               0 :   switch (mType)
    3638                 :   {
    3639                 :     case NS_FORM_INPUT_CHECKBOX:
    3640               0 :       return !mChecked;
    3641                 :     case NS_FORM_INPUT_FILE:
    3642                 :       {
    3643               0 :         const nsCOMArray<nsIDOMFile>& files = GetFiles();
    3644               0 :         return !files.Count();
    3645                 :       }
    3646                 :     default:
    3647               0 :       return false;
    3648                 :   }
    3649                 : }
    3650                 : 
    3651                 : bool
    3652               1 : nsHTMLInputElement::HasTypeMismatch() const
    3653                 : {
    3654               1 :   if (mType != NS_FORM_INPUT_EMAIL && mType != NS_FORM_INPUT_URL) {
    3655               1 :     return false;
    3656                 :   }
    3657                 : 
    3658               0 :   nsAutoString value;
    3659               0 :   NS_ENSURE_SUCCESS(GetValueInternal(value), false);
    3660                 : 
    3661               0 :   if (value.IsEmpty()) {
    3662               0 :     return false;
    3663                 :   }
    3664                 : 
    3665               0 :   if (mType == NS_FORM_INPUT_EMAIL) {
    3666               0 :     return HasAttr(kNameSpaceID_None, nsGkAtoms::multiple)
    3667               0 :              ? !IsValidEmailAddressList(value) : !IsValidEmailAddress(value);
    3668               0 :   } else if (mType == NS_FORM_INPUT_URL) {
    3669                 :     /**
    3670                 :      * TODO:
    3671                 :      * The URL is not checked as the HTML5 specifications want it to be because
    3672                 :      * there is no code to check for a valid URI/IRI according to 3986 and 3987
    3673                 :      * RFC's at the moment, see bug 561586.
    3674                 :      *
    3675                 :      * RFC 3987 (IRI) implementation: bug 42899
    3676                 :      *
    3677                 :      * HTML5 specifications:
    3678                 :      * http://dev.w3.org/html5/spec/infrastructure.html#valid-url
    3679                 :      */
    3680               0 :     nsCOMPtr<nsIIOService> ioService = do_GetIOService();
    3681               0 :     nsCOMPtr<nsIURI> uri;
    3682                 : 
    3683               0 :     return !NS_SUCCEEDED(ioService->NewURI(NS_ConvertUTF16toUTF8(value), nsnull,
    3684                 :                                            nsnull, getter_AddRefs(uri)));
    3685                 :   }
    3686                 : 
    3687               0 :   return false;
    3688                 : }
    3689                 : 
    3690                 : bool
    3691               1 : nsHTMLInputElement::HasPatternMismatch() const
    3692                 : {
    3693               2 :   nsAutoString pattern;
    3694               2 :   if (!DoesPatternApply() ||
    3695               1 :       !GetAttr(kNameSpaceID_None, nsGkAtoms::pattern, pattern)) {
    3696               1 :     return false;
    3697                 :   }
    3698                 : 
    3699               0 :   nsAutoString value;
    3700               0 :   NS_ENSURE_SUCCESS(GetValueInternal(value), false);
    3701                 : 
    3702               0 :   if (value.IsEmpty()) {
    3703               0 :     return false;
    3704                 :   }
    3705                 : 
    3706               0 :   nsIDocument* doc = OwnerDoc();
    3707                 : 
    3708               0 :   return !nsContentUtils::IsPatternMatching(value, pattern, doc);
    3709                 : }
    3710                 : 
    3711                 : void
    3712               1 : nsHTMLInputElement::UpdateTooLongValidityState()
    3713                 : {
    3714                 :   // TODO: this code will be re-enabled with bug 613016 and bug 613019.
    3715                 : #if 0
    3716                 :   SetValidityState(VALIDITY_STATE_TOO_LONG, IsTooLong());
    3717                 : #endif
    3718               1 : }
    3719                 : 
    3720                 : void
    3721               0 : nsHTMLInputElement::UpdateValueMissingValidityStateForRadio(bool aIgnoreSelf)
    3722                 : {
    3723               0 :   bool notify = !mParserCreating;
    3724               0 :   nsCOMPtr<nsIDOMHTMLInputElement> selection = GetSelectedRadioButton();
    3725                 : 
    3726                 :   // If there is no selection, that might mean the radio is not in a group.
    3727                 :   // In that case, we can look for the checked state of the radio.
    3728               0 :   bool selected = selection || (!aIgnoreSelf && mChecked);
    3729               0 :   bool required = !aIgnoreSelf && HasAttr(kNameSpaceID_None, nsGkAtoms::required);
    3730               0 :   bool valueMissing = false;
    3731                 : 
    3732               0 :   nsCOMPtr<nsIRadioGroupContainer> container = GetRadioGroupContainer();
    3733                 : 
    3734               0 :   if (!container) {
    3735               0 :     SetValidityState(VALIDITY_STATE_VALUE_MISSING, required && !selected);
    3736                 :     return;
    3737                 :   }
    3738                 : 
    3739               0 :   nsAutoString name;
    3740               0 :   GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
    3741                 : 
    3742                 :   // If the current radio is required and not ignored, we can assume the entire
    3743                 :   // group is required.
    3744               0 :   if (!required) {
    3745               0 :     required = (aIgnoreSelf && HasAttr(kNameSpaceID_None, nsGkAtoms::required))
    3746               0 :                  ? container->GetRequiredRadioCount(name) - 1
    3747               0 :                  : container->GetRequiredRadioCount(name);
    3748                 :   }
    3749                 : 
    3750               0 :   valueMissing = required && !selected;
    3751                 : 
    3752               0 :   if (container->GetValueMissingState(name) != valueMissing) {
    3753               0 :     container->SetValueMissingState(name, valueMissing);
    3754                 : 
    3755               0 :     SetValidityState(VALIDITY_STATE_VALUE_MISSING, valueMissing);
    3756                 : 
    3757                 :     // nsRadioSetValueMissingState will call ContentStateChanged while visiting.
    3758               0 :     nsAutoScriptBlocker scriptBlocker;
    3759                 :     nsCOMPtr<nsIRadioVisitor> visitor =
    3760               0 :       new nsRadioSetValueMissingState(this, valueMissing, notify);
    3761               0 :     VisitGroup(visitor, notify);
    3762                 :   }
    3763                 : }
    3764                 : 
    3765                 : void
    3766               5 : nsHTMLInputElement::UpdateValueMissingValidityState()
    3767                 : {
    3768               5 :   if (mType == NS_FORM_INPUT_RADIO) {
    3769               0 :     UpdateValueMissingValidityStateForRadio(false);
    3770               0 :     return;
    3771                 :   }
    3772                 : 
    3773               5 :   SetValidityState(VALIDITY_STATE_VALUE_MISSING, IsValueMissing());
    3774                 : }
    3775                 : 
    3776                 : void
    3777               1 : nsHTMLInputElement::UpdateTypeMismatchValidityState()
    3778                 : {
    3779               1 :     SetValidityState(VALIDITY_STATE_TYPE_MISMATCH, HasTypeMismatch());
    3780               1 : }
    3781                 : 
    3782                 : void
    3783               1 : nsHTMLInputElement::UpdatePatternMismatchValidityState()
    3784                 : {
    3785               1 :   SetValidityState(VALIDITY_STATE_PATTERN_MISMATCH, HasPatternMismatch());
    3786               1 : }
    3787                 : 
    3788                 : void
    3789               1 : nsHTMLInputElement::UpdateAllValidityStates(bool aNotify)
    3790                 : {
    3791               1 :   bool validBefore = IsValid();
    3792               1 :   UpdateTooLongValidityState();
    3793               1 :   UpdateValueMissingValidityState();
    3794               1 :   UpdateTypeMismatchValidityState();
    3795               1 :   UpdatePatternMismatchValidityState();
    3796                 : 
    3797               1 :   if (validBefore != IsValid()) {
    3798               0 :     UpdateState(aNotify);
    3799                 :   }
    3800               1 : }
    3801                 : 
    3802                 : void
    3803               4 : nsHTMLInputElement::UpdateBarredFromConstraintValidation()
    3804                 : {
    3805                 :   SetBarredFromConstraintValidation(mType == NS_FORM_INPUT_HIDDEN ||
    3806                 :                                     mType == NS_FORM_INPUT_BUTTON ||
    3807                 :                                     mType == NS_FORM_INPUT_RESET ||
    3808                 :                                     mType == NS_FORM_INPUT_SUBMIT ||
    3809                 :                                     mType == NS_FORM_INPUT_IMAGE ||
    3810               4 :                                     HasAttr(kNameSpaceID_None, nsGkAtoms::readonly) ||
    3811               8 :                                     IsDisabled());
    3812               4 : }
    3813                 : 
    3814                 : nsresult
    3815               0 : nsHTMLInputElement::GetValidationMessage(nsAString& aValidationMessage,
    3816                 :                                          ValidityStateType aType)
    3817                 : {
    3818               0 :   nsresult rv = NS_OK;
    3819                 : 
    3820               0 :   switch (aType)
    3821                 :   {
    3822                 :     case VALIDITY_STATE_TOO_LONG:
    3823                 :     {
    3824               0 :       nsXPIDLString message;
    3825               0 :       PRInt32 maxLength = -1;
    3826               0 :       PRInt32 textLength = -1;
    3827               0 :       nsAutoString strMaxLength;
    3828               0 :       nsAutoString strTextLength;
    3829                 : 
    3830               0 :       GetMaxLength(&maxLength);
    3831               0 :       GetTextLength(&textLength);
    3832                 : 
    3833               0 :       strMaxLength.AppendInt(maxLength);
    3834               0 :       strTextLength.AppendInt(textLength);
    3835                 : 
    3836               0 :       const PRUnichar* params[] = { strMaxLength.get(), strTextLength.get() };
    3837                 :       rv = nsContentUtils::FormatLocalizedString(nsContentUtils::eDOM_PROPERTIES,
    3838                 :                                                  "FormValidationTextTooLong",
    3839               0 :                                                  params, message);
    3840               0 :       aValidationMessage = message;
    3841                 :       break;
    3842                 :     }
    3843                 :     case VALIDITY_STATE_VALUE_MISSING:
    3844                 :     {
    3845               0 :       nsXPIDLString message;
    3846               0 :       nsCAutoString key;
    3847               0 :       switch (mType)
    3848                 :       {
    3849                 :         case NS_FORM_INPUT_FILE:
    3850               0 :           key.Assign("FormValidationFileMissing");
    3851               0 :           break;
    3852                 :         case NS_FORM_INPUT_CHECKBOX:
    3853               0 :           key.Assign("FormValidationCheckboxMissing");
    3854               0 :           break;
    3855                 :         case NS_FORM_INPUT_RADIO:
    3856               0 :           key.Assign("FormValidationRadioMissing");
    3857               0 :           break;
    3858                 :         default:
    3859               0 :           key.Assign("FormValidationValueMissing");
    3860                 :       }
    3861                 :       rv = nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES,
    3862               0 :                                               key.get(), message);
    3863               0 :       aValidationMessage = message;
    3864                 :       break;
    3865                 :     }
    3866                 :     case VALIDITY_STATE_TYPE_MISMATCH:
    3867                 :     {
    3868               0 :       nsXPIDLString message;
    3869               0 :       nsCAutoString key;
    3870               0 :       if (mType == NS_FORM_INPUT_EMAIL) {
    3871               0 :         key.AssignLiteral("FormValidationInvalidEmail");
    3872               0 :       } else if (mType == NS_FORM_INPUT_URL) {
    3873               0 :         key.AssignLiteral("FormValidationInvalidURL");
    3874                 :       } else {
    3875               0 :         return NS_ERROR_UNEXPECTED;
    3876                 :       }
    3877                 :       rv = nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES,
    3878               0 :                                               key.get(), message);
    3879               0 :       aValidationMessage = message;
    3880               0 :       break;
    3881                 :     }
    3882                 :     case VALIDITY_STATE_PATTERN_MISMATCH:
    3883                 :     {
    3884               0 :       nsXPIDLString message;
    3885               0 :       nsAutoString title;
    3886               0 :       GetAttr(kNameSpaceID_None, nsGkAtoms::title, title);
    3887               0 :       if (title.IsEmpty()) {
    3888                 :         rv = nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES,
    3889                 :                                                 "FormValidationPatternMismatch",
    3890               0 :                                                 message);
    3891                 :       } else {
    3892               0 :         if (title.Length() > nsIConstraintValidation::sContentSpecifiedMaxLengthMessage) {
    3893               0 :           title.Truncate(nsIConstraintValidation::sContentSpecifiedMaxLengthMessage);
    3894                 :         }
    3895               0 :         const PRUnichar* params[] = { title.get() };
    3896                 :         rv = nsContentUtils::FormatLocalizedString(nsContentUtils::eDOM_PROPERTIES,
    3897                 :                                                    "FormValidationPatternMismatchWithTitle",
    3898               0 :                                                    params, message);
    3899                 :       }
    3900               0 :       aValidationMessage = message;
    3901                 :       break;
    3902                 :     }
    3903                 :     default:
    3904               0 :       rv = nsIConstraintValidation::GetValidationMessage(aValidationMessage, aType);
    3905                 :   }
    3906                 : 
    3907               0 :   return rv;
    3908                 : }
    3909                 : 
    3910                 : //static
    3911                 : bool
    3912               0 : nsHTMLInputElement::IsValidEmailAddressList(const nsAString& aValue)
    3913                 : {
    3914               0 :   HTMLSplitOnSpacesTokenizer tokenizer(aValue, ',');
    3915                 : 
    3916               0 :   while (tokenizer.hasMoreTokens()) {
    3917               0 :     if (!IsValidEmailAddress(tokenizer.nextToken())) {
    3918               0 :       return false;
    3919                 :     }
    3920                 :   }
    3921                 : 
    3922               0 :   return !tokenizer.lastTokenEndedWithSeparator();
    3923                 : }
    3924                 : 
    3925                 : //static
    3926                 : bool
    3927               0 : nsHTMLInputElement::IsValidEmailAddress(const nsAString& aValue)
    3928                 : {
    3929               0 :   nsCAutoString value = NS_ConvertUTF16toUTF8(aValue);
    3930               0 :   PRUint32 i = 0;
    3931               0 :   PRUint32 length = value.Length();
    3932                 : 
    3933                 :   // Puny-encode the string if needed before running the validation algorithm.
    3934               0 :   nsCOMPtr<nsIIDNService> idnSrv = do_GetService(NS_IDNSERVICE_CONTRACTID);
    3935               0 :   if (idnSrv) {
    3936                 :     bool ace;
    3937               0 :     if (NS_SUCCEEDED(idnSrv->IsACE(value, &ace)) && !ace) {
    3938               0 :       nsCAutoString punyCodedValue;
    3939               0 :       if (NS_SUCCEEDED(idnSrv->ConvertUTF8toACE(value, punyCodedValue))) {
    3940               0 :         value = punyCodedValue;
    3941               0 :         length = value.Length();
    3942                 :       }
    3943                 :     }
    3944                 :   } else {
    3945               0 :     NS_ERROR("nsIIDNService isn't present!");
    3946                 :   }
    3947                 : 
    3948                 :   // If the email address is empty, begins with a '@' or ends with a '.',
    3949                 :   // we know it's invalid.
    3950               0 :   if (length == 0 || value[0] == '@' || value[length-1] == '.') {
    3951               0 :     return false;
    3952                 :   }
    3953                 : 
    3954                 :   // Parsing the username.
    3955               0 :   for (; i < length && value[i] != '@'; ++i) {
    3956               0 :     PRUnichar c = value[i];
    3957                 : 
    3958                 :     // The username characters have to be in this list to be valid.
    3959               0 :     if (!(nsCRT::IsAsciiAlpha(c) || nsCRT::IsAsciiDigit(c) ||
    3960                 :           c == '.' || c == '!' || c == '#' || c == '$' || c == '%' ||
    3961                 :           c == '&' || c == '\''|| c == '*' || c == '+' || c == '-' ||
    3962                 :           c == '/' || c == '=' || c == '?' || c == '^' || c == '_' ||
    3963               0 :           c == '`' || c == '{' || c == '|' || c == '}' || c == '~' )) {
    3964               0 :       return false;
    3965                 :     }
    3966                 :   }
    3967                 : 
    3968                 :   // There is no domain name (or it's one-character long),
    3969                 :   // that's not a valid email address.
    3970               0 :   if (++i >= length) {
    3971               0 :     return false;
    3972                 :   }
    3973                 : 
    3974                 :   // The domain name can't begin with a dot.
    3975               0 :   if (value[i] == '.') {
    3976               0 :     return false;
    3977                 :   }
    3978                 : 
    3979                 :   // Parsing the domain name.
    3980               0 :   for (; i < length; ++i) {
    3981               0 :     PRUnichar c = value[i];
    3982                 : 
    3983               0 :     if (c == '.') {
    3984                 :       // A dot can't follow a dot.
    3985               0 :       if (value[i-1] == '.') {
    3986               0 :         return false;
    3987                 :       }
    3988               0 :     } else if (!(nsCRT::IsAsciiAlpha(c) || nsCRT::IsAsciiDigit(c) ||
    3989               0 :                  c == '-')) {
    3990                 :       // The domain characters have to be in this list to be valid.
    3991               0 :       return false;
    3992                 :     }
    3993                 :   }
    3994                 : 
    3995               0 :   return true;
    3996                 : }
    3997                 : 
    3998                 : NS_IMETHODIMP_(bool)
    3999               0 : nsHTMLInputElement::IsSingleLineTextControl() const
    4000                 : {
    4001               0 :   return IsSingleLineTextControl(false);
    4002                 : }
    4003                 : 
    4004                 : NS_IMETHODIMP_(bool)
    4005               0 : nsHTMLInputElement::IsTextArea() const
    4006                 : {
    4007               0 :   return false;
    4008                 : }
    4009                 : 
    4010                 : NS_IMETHODIMP_(bool)
    4011               0 : nsHTMLInputElement::IsPlainTextControl() const
    4012                 : {
    4013                 :   // need to check our HTML attribute and/or CSS.
    4014               0 :   return true;
    4015                 : }
    4016                 : 
    4017                 : NS_IMETHODIMP_(bool)
    4018               0 : nsHTMLInputElement::IsPasswordTextControl() const
    4019                 : {
    4020               0 :   return mType == NS_FORM_INPUT_PASSWORD;
    4021                 : }
    4022                 : 
    4023                 : NS_IMETHODIMP_(PRInt32)
    4024               0 : nsHTMLInputElement::GetCols()
    4025                 : {
    4026                 :   // Else we know (assume) it is an input with size attr
    4027               0 :   const nsAttrValue* attr = GetParsedAttr(nsGkAtoms::size);
    4028               0 :   if (attr && attr->Type() == nsAttrValue::eInteger) {
    4029               0 :     PRInt32 cols = attr->GetIntegerValue();
    4030               0 :     if (cols > 0) {
    4031               0 :       return cols;
    4032                 :     }
    4033                 :   }
    4034                 : 
    4035               0 :   return DEFAULT_COLS;
    4036                 : }
    4037                 : 
    4038                 : NS_IMETHODIMP_(PRInt32)
    4039               0 : nsHTMLInputElement::GetWrapCols()
    4040                 : {
    4041               0 :   return -1; // only textarea's can have wrap cols
    4042                 : }
    4043                 : 
    4044                 : NS_IMETHODIMP_(PRInt32)
    4045               0 : nsHTMLInputElement::GetRows()
    4046                 : {
    4047               0 :   return DEFAULT_ROWS;
    4048                 : }
    4049                 : 
    4050                 : NS_IMETHODIMP_(void)
    4051               1 : nsHTMLInputElement::GetDefaultValueFromContent(nsAString& aValue)
    4052                 : {
    4053               1 :   nsTextEditorState *state = GetEditorState();
    4054               1 :   if (state) {
    4055               1 :     GetDefaultValue(aValue);
    4056                 :     // This is called by the frame to show the value.
    4057                 :     // We have to sanitize it when needed.
    4058               1 :     if (!mParserCreating) {
    4059               1 :       SanitizeValue(aValue);
    4060                 :     }
    4061                 :   }
    4062               1 : }
    4063                 : 
    4064                 : NS_IMETHODIMP_(bool)
    4065               1 : nsHTMLInputElement::ValueChanged() const
    4066                 : {
    4067               1 :   return mValueChanged;
    4068                 : }
    4069                 : 
    4070                 : NS_IMETHODIMP_(void)
    4071               0 : nsHTMLInputElement::GetTextEditorValue(nsAString& aValue,
    4072                 :                                        bool aIgnoreWrap) const
    4073                 : {
    4074               0 :   nsTextEditorState *state = GetEditorState();
    4075               0 :   if (state) {
    4076               0 :     state->GetValue(aValue, aIgnoreWrap);
    4077                 :   }
    4078               0 : }
    4079                 : 
    4080                 : NS_IMETHODIMP_(void)
    4081               0 : nsHTMLInputElement::SetTextEditorValue(const nsAString& aValue,
    4082                 :                                        bool aUserInput)
    4083                 : {
    4084               0 :   nsTextEditorState *state = GetEditorState();
    4085               0 :   if (state) {
    4086               0 :     state->SetValue(aValue, aUserInput);
    4087                 :   }
    4088               0 : }
    4089                 : 
    4090                 : NS_IMETHODIMP_(void)
    4091               0 : nsHTMLInputElement::InitializeKeyboardEventListeners()
    4092                 : {
    4093               0 :   nsTextEditorState *state = GetEditorState();
    4094               0 :   if (state) {
    4095               0 :     state->InitializeKeyboardEventListeners();
    4096                 :   }
    4097               0 : }
    4098                 : 
    4099                 : NS_IMETHODIMP_(void)
    4100               1 : nsHTMLInputElement::OnValueChanged(bool aNotify)
    4101                 : {
    4102               1 :   UpdateAllValidityStates(aNotify);
    4103                 : 
    4104                 :   // :-moz-placeholder pseudo-class may change when the value changes.
    4105                 :   // However, we don't want to waste cycles if the state doesn't apply.
    4106               2 :   if (PlaceholderApplies() &&
    4107               1 :       HasAttr(kNameSpaceID_None, nsGkAtoms::placeholder) &&
    4108               0 :       !nsContentUtils::IsFocusedContent(this)) {
    4109               0 :     UpdateState(aNotify);
    4110                 :   }
    4111               1 : }
    4112                 : 
    4113                 : NS_IMETHODIMP_(bool)
    4114               0 : nsHTMLInputElement::HasCachedSelection()
    4115                 : {
    4116               0 :   bool isCached = false;
    4117               0 :   nsTextEditorState *state = GetEditorState();
    4118               0 :   if (state) {
    4119               0 :     isCached = state->IsSelectionCached() &&
    4120               0 :                state->HasNeverInitializedBefore() &&
    4121               0 :                !state->GetSelectionProperties().IsDefault();
    4122               0 :     if (isCached) {
    4123               0 :       state->WillInitEagerly();
    4124                 :     }
    4125                 :   }
    4126               0 :   return isCached;
    4127                 : }
    4128                 : 
    4129                 : void
    4130               0 : nsHTMLInputElement::FieldSetDisabledChanged(bool aNotify)
    4131                 : {
    4132               0 :   UpdateValueMissingValidityState();
    4133               0 :   UpdateBarredFromConstraintValidation();
    4134                 : 
    4135               0 :   nsGenericHTMLFormElement::FieldSetDisabledChanged(aNotify);
    4136               0 : }
    4137                 : 
    4138                 : PRInt32
    4139               0 : nsHTMLInputElement::GetFilterFromAccept()
    4140                 : {
    4141               0 :   NS_ASSERTION(HasAttr(kNameSpaceID_None, nsGkAtoms::accept),
    4142                 :                "You should not call GetFileFiltersFromAccept if the element"
    4143                 :                " has no accept attribute!");
    4144                 : 
    4145               0 :   PRInt32 filter = 0;
    4146               0 :   nsAutoString accept;
    4147               0 :   GetAttr(kNameSpaceID_None, nsGkAtoms::accept, accept);
    4148                 : 
    4149               0 :   HTMLSplitOnSpacesTokenizer tokenizer(accept, ',');
    4150                 : 
    4151               0 :   while (tokenizer.hasMoreTokens()) {
    4152               0 :     const nsDependentSubstring token = tokenizer.nextToken();
    4153                 : 
    4154               0 :     PRInt32 tokenFilter = 0;
    4155               0 :     if (token.EqualsLiteral("image/*")) {
    4156               0 :       tokenFilter = nsIFilePicker::filterImages;
    4157               0 :     } else if (token.EqualsLiteral("audio/*")) {
    4158               0 :       tokenFilter = nsIFilePicker::filterAudio;
    4159               0 :     } else if (token.EqualsLiteral("video/*")) {
    4160               0 :       tokenFilter = nsIFilePicker::filterVideo;
    4161                 :     }
    4162                 : 
    4163               0 :     if (tokenFilter) {
    4164                 :       // We do not want to set more than one filter so if we found two different
    4165                 :       // kwown tokens, we will return 0 (no filter).
    4166               0 :       if (filter && filter != tokenFilter) {
    4167               0 :         return 0;
    4168                 :       }
    4169               0 :       filter = tokenFilter;
    4170                 :     }
    4171                 :   }
    4172                 : 
    4173               0 :   return filter;
    4174                 : }
    4175                 : 
    4176                 : void
    4177               0 : nsHTMLInputElement::UpdateValidityUIBits(bool aIsFocused)
    4178                 : {
    4179               0 :   if (aIsFocused) {
    4180                 :     // If the invalid UI is shown, we should show it while focusing (and
    4181                 :     // update). Otherwise, we should not.
    4182               0 :     mCanShowInvalidUI = !IsValid() && ShouldShowValidityUI();
    4183                 : 
    4184                 :     // If neither invalid UI nor valid UI is shown, we shouldn't show the valid
    4185                 :     // UI while typing.
    4186               0 :     mCanShowValidUI = ShouldShowValidityUI();
    4187                 :   } else {
    4188               0 :     mCanShowInvalidUI = true;
    4189               0 :     mCanShowValidUI = true;
    4190                 :   }
    4191            4392 : }
    4192                 : 

Generated by: LCOV version 1.7