Bug 1141455 - Do not treat an element with tabindex as an interactive content in label. r=smaug
authorTooru Fujisawa <arai_a@mac.com>
Wed, 18 Mar 2015 05:42:14 +0900
changeset 234160 39a861ac2bb6a096d98c6a7e91bcad5691ba3360
parent 234159 56267a6107055035980f4e86e1dbf33e630ea3a0
child 234161 2b44490589d824ec9bc2360b95237f399cbb2e5a
push id28436
push usercbook@mozilla.com
push dateWed, 18 Mar 2015 12:52:36 +0000
treeherdermozilla-central@41a61514461e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1141455
milestone39.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1141455 - Do not treat an element with tabindex as an interactive content in label. r=smaug
dom/base/Element.cpp
dom/base/Element.h
dom/html/HTMLAnchorElement.h
dom/html/HTMLAudioElement.cpp
dom/html/HTMLAudioElement.h
dom/html/HTMLButtonElement.h
dom/html/HTMLIFrameElement.h
dom/html/HTMLImageElement.cpp
dom/html/HTMLImageElement.h
dom/html/HTMLInputElement.cpp
dom/html/HTMLInputElement.h
dom/html/HTMLLabelElement.cpp
dom/html/HTMLLabelElement.h
dom/html/HTMLObjectElement.cpp
dom/html/HTMLObjectElement.h
dom/html/HTMLSelectElement.h
dom/html/HTMLTextAreaElement.h
dom/html/HTMLVideoElement.cpp
dom/html/HTMLVideoElement.h
dom/html/nsGenericHTMLElement.cpp
dom/html/nsGenericHTMLElement.h
dom/html/test/forms/test_interactive_content_in_label.html
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -1827,17 +1827,17 @@ Element::SetSMILOverrideStyleRule(css::S
 
 bool
 Element::IsLabelable() const
 {
   return false;
 }
 
 bool
-Element::IsInteractiveHTMLContent() const
+Element::IsInteractiveHTMLContent(bool aIgnoreTabindex) const
 {
   return false;
 }
 
 css::StyleRule*
 Element::GetInlineStyleRule()
 {
   return nullptr;
--- a/dom/base/Element.h
+++ b/dom/base/Element.h
@@ -271,17 +271,17 @@ public:
   /**
    * Returns if the element is labelable as per HTML specification.
    */
   virtual bool IsLabelable() const;
 
   /**
    * Returns if the element is interactive content as per HTML specification.
    */
-  virtual bool IsInteractiveHTMLContent() const;
+  virtual bool IsInteractiveHTMLContent(bool aIgnoreTabindex) const;
 
   /**
    * Is the attribute named stored in the mapped attributes?
    *
    * // XXXbz we use this method in HasAttributeDependentStyle, so svg
    *    returns true here even though it stores nothing in the mapped
    *    attributes.
    */
--- a/dom/html/HTMLAnchorElement.h
+++ b/dom/html/HTMLAnchorElement.h
@@ -38,17 +38,17 @@ public:
   // CC
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLAnchorElement,
                                            nsGenericHTMLElement)
 
   virtual int32_t TabIndexDefault() MOZ_OVERRIDE;
   virtual bool Draggable() const MOZ_OVERRIDE;
 
   // Element
-  virtual bool IsInteractiveHTMLContent() const MOZ_OVERRIDE
+  virtual bool IsInteractiveHTMLContent(bool aIgnoreTabindex) const MOZ_OVERRIDE
   {
     return true;
   }
 
   // nsIDOMHTMLAnchorElement
   NS_DECL_NSIDOMHTMLANCHORELEMENT
 
   // DOM memory reporter participant
--- a/dom/html/HTMLAudioElement.cpp
+++ b/dom/html/HTMLAudioElement.cpp
@@ -36,17 +36,17 @@ HTMLAudioElement::HTMLAudioElement(alrea
 {
 }
 
 HTMLAudioElement::~HTMLAudioElement()
 {
 }
 
 bool
-HTMLAudioElement::IsInteractiveHTMLContent() const
+HTMLAudioElement::IsInteractiveHTMLContent(bool aIgnoreTabindex) const
 {
   return HasAttr(kNameSpaceID_None, nsGkAtoms::controls);
 }
 
 already_AddRefed<HTMLAudioElement>
 HTMLAudioElement::Audio(const GlobalObject& aGlobal,
                         const Optional<nsAString>& aSrc,
                         ErrorResult& aRv)
--- a/dom/html/HTMLAudioElement.h
+++ b/dom/html/HTMLAudioElement.h
@@ -19,17 +19,17 @@ namespace dom {
 class HTMLAudioElement MOZ_FINAL : public HTMLMediaElement
 {
 public:
   typedef mozilla::dom::NodeInfo NodeInfo;
 
   explicit HTMLAudioElement(already_AddRefed<NodeInfo>& aNodeInfo);
 
   // Element
-  virtual bool IsInteractiveHTMLContent() const MOZ_OVERRIDE;
+  virtual bool IsInteractiveHTMLContent(bool aIgnoreTabindex) const MOZ_OVERRIDE;
 
   // nsIDOMHTMLMediaElement
   using HTMLMediaElement::GetPaused;
 
   virtual nsresult Clone(NodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;
   virtual nsresult SetAcceptHeader(nsIHttpChannel* aChannel) MOZ_OVERRIDE;
 
   virtual nsIDOMNode* AsDOMNode() MOZ_OVERRIDE { return this; }
--- a/dom/html/HTMLButtonElement.h
+++ b/dom/html/HTMLButtonElement.h
@@ -32,17 +32,17 @@ public:
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   virtual int32_t TabIndexDefault() MOZ_OVERRIDE;
 
   NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLButtonElement, button)
 
   // Element
-  virtual bool IsInteractiveHTMLContent() const MOZ_OVERRIDE
+  virtual bool IsInteractiveHTMLContent(bool aIgnoreTabindex) const MOZ_OVERRIDE
   {
     return true;
   }
 
   // nsIDOMHTMLButtonElement
   NS_DECL_NSIDOMHTMLBUTTONELEMENT
 
   // overriden nsIFormControl methods
--- a/dom/html/HTMLIFrameElement.h
+++ b/dom/html/HTMLIFrameElement.h
@@ -22,17 +22,17 @@ public:
                              FromParser aFromParser = NOT_FROM_PARSER);
 
   NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLIFrameElement, iframe)
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // Element
-  virtual bool IsInteractiveHTMLContent() const MOZ_OVERRIDE
+  virtual bool IsInteractiveHTMLContent(bool aIgnoreTabindex) const MOZ_OVERRIDE
   {
     return true;
   }
 
   // nsIDOMHTMLIFrameElement
   NS_DECL_NSIDOMHTMLIFRAMEELEMENT
 
   // nsIContent
--- a/dom/html/HTMLImageElement.cpp
+++ b/dom/html/HTMLImageElement.cpp
@@ -144,17 +144,17 @@ NS_IMPL_URI_ATTR(HTMLImageElement, LongD
 NS_IMPL_STRING_ATTR(HTMLImageElement, Sizes, sizes)
 NS_IMPL_STRING_ATTR(HTMLImageElement, Lowsrc, lowsrc)
 NS_IMPL_URI_ATTR(HTMLImageElement, Src, src)
 NS_IMPL_STRING_ATTR(HTMLImageElement, Srcset, srcset)
 NS_IMPL_STRING_ATTR(HTMLImageElement, UseMap, usemap)
 NS_IMPL_INT_ATTR(HTMLImageElement, Vspace, vspace)
 
 bool
-HTMLImageElement::IsInteractiveHTMLContent() const
+HTMLImageElement::IsInteractiveHTMLContent(bool aIgnoreTabindex) const
 {
   return HasAttr(kNameSpaceID_None, nsGkAtoms::usemap);
 }
 
 bool
 HTMLImageElement::IsSrcsetEnabled()
 {
   return Preferences::GetBool(kPrefSrcsetEnabled, false);
--- a/dom/html/HTMLImageElement.h
+++ b/dom/html/HTMLImageElement.h
@@ -42,17 +42,17 @@ public:
                                            nsGenericHTMLElement)
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   virtual bool Draggable() const MOZ_OVERRIDE;
 
   // Element
-  virtual bool IsInteractiveHTMLContent() const MOZ_OVERRIDE;
+  virtual bool IsInteractiveHTMLContent(bool aIgnoreTabindex) const MOZ_OVERRIDE;
 
   // nsIDOMHTMLImageElement
   NS_DECL_NSIDOMHTMLIMAGEELEMENT
 
   NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLImageElement, img)
 
   // override from nsImageLoadingContent
   CORSMode GetCORSMode() MOZ_OVERRIDE;
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -3217,17 +3217,17 @@ HTMLInputElement::Focus(ErrorResult& aEr
       }
     }
   }
 
   return;
 }
 
 bool
-HTMLInputElement::IsInteractiveHTMLContent() const
+HTMLInputElement::IsInteractiveHTMLContent(bool aIgnoreTabindex) const
 {
   return mType != NS_FORM_INPUT_HIDDEN;
 }
 
 NS_IMETHODIMP
 HTMLInputElement::Select()
 {
   if (mType == NS_FORM_INPUT_NUMBER) {
--- a/dom/html/HTMLInputElement.h
+++ b/dom/html/HTMLInputElement.h
@@ -115,17 +115,17 @@ public:
   NS_DECL_ISUPPORTS_INHERITED
 
   virtual int32_t TabIndexDefault() MOZ_OVERRIDE;
   using nsGenericHTMLElement::Focus;
   virtual void Blur(ErrorResult& aError) MOZ_OVERRIDE;
   virtual void Focus(ErrorResult& aError) MOZ_OVERRIDE;
 
   // Element
-  virtual bool IsInteractiveHTMLContent() const MOZ_OVERRIDE;
+  virtual bool IsInteractiveHTMLContent(bool aIgnoreTabindex) const MOZ_OVERRIDE;
 
   // nsIDOMHTMLInputElement
   NS_DECL_NSIDOMHTMLINPUTELEMENT
 
   // nsIPhonetic
   NS_DECL_NSIPHONETIC
 
   // nsIDOMNSEditableElement
--- a/dom/html/HTMLLabelElement.cpp
+++ b/dom/html/HTMLLabelElement.cpp
@@ -83,17 +83,17 @@ HTMLLabelElement::Focus(ErrorResult& aEr
 }
 
 static bool
 InInteractiveHTMLContent(nsIContent* aContent, nsIContent* aStop)
 {
   nsIContent* content = aContent;
   while (content && content != aStop) {
     if (content->IsElement() &&
-        content->AsElement()->IsInteractiveHTMLContent()) {
+        content->AsElement()->IsInteractiveHTMLContent(true)) {
       return true;
     }
     content = content->GetParent();
   }
   return false;
 }
 
 nsresult
--- a/dom/html/HTMLLabelElement.h
+++ b/dom/html/HTMLLabelElement.h
@@ -28,17 +28,17 @@ public:
   }
 
   NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLLabelElement, label)
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // Element
-  virtual bool IsInteractiveHTMLContent() const MOZ_OVERRIDE
+  virtual bool IsInteractiveHTMLContent(bool aIgnoreTabindex) const MOZ_OVERRIDE
   {
     return true;
   }
 
   // nsIDOMHTMLLabelElement
   NS_DECL_NSIDOMHTMLLABELELEMENT
 
   using nsGenericHTMLFormElement::GetForm;
--- a/dom/html/HTMLObjectElement.cpp
+++ b/dom/html/HTMLObjectElement.cpp
@@ -45,17 +45,17 @@ HTMLObjectElement::HTMLObjectElement(alr
 
 HTMLObjectElement::~HTMLObjectElement()
 {
   UnregisterActivityObserver();
   DestroyImageLoadingContent();
 }
 
 bool
-HTMLObjectElement::IsInteractiveHTMLContent() const
+HTMLObjectElement::IsInteractiveHTMLContent(bool aIgnoreTabindex) const
 {
   return HasAttr(kNameSpaceID_None, nsGkAtoms::usemap);
 }
 
 bool
 HTMLObjectElement::IsDoneAddingChildren()
 {
   return mIsDoneAddingChildren;
--- a/dom/html/HTMLObjectElement.h
+++ b/dom/html/HTMLObjectElement.h
@@ -32,17 +32,17 @@ public:
 
 #ifdef XP_MACOSX
   // nsIDOMEventTarget
   NS_IMETHOD PostHandleEvent(EventChainPostVisitor& aVisitor) MOZ_OVERRIDE;
   static void HandleFocusBlurPlugin(Element* aElement, WidgetEvent* aEvent);
 #endif
 
   // Element
-  virtual bool IsInteractiveHTMLContent() const MOZ_OVERRIDE;
+  virtual bool IsInteractiveHTMLContent(bool aIgnoreTabindex) const MOZ_OVERRIDE;
 
   // nsIDOMHTMLObjectElement
   NS_DECL_NSIDOMHTMLOBJECTELEMENT
 
   virtual nsresult BindToTree(nsIDocument *aDocument, nsIContent *aParent,
                               nsIContent *aBindingParent,
                               bool aCompileEventHandlers) MOZ_OVERRIDE;
   virtual void UnbindFromTree(bool aDeep = true,
--- a/dom/html/HTMLSelectElement.h
+++ b/dom/html/HTMLSelectElement.h
@@ -143,17 +143,17 @@ public:
   NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLSelectElement, select)
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   virtual int32_t TabIndexDefault() MOZ_OVERRIDE;
 
   // Element
-  virtual bool IsInteractiveHTMLContent() const MOZ_OVERRIDE
+  virtual bool IsInteractiveHTMLContent(bool aIgnoreTabindex) const MOZ_OVERRIDE
   {
     return true;
   }
 
   // nsIDOMHTMLSelectElement
   NS_DECL_NSIDOMHTMLSELECTELEMENT
 
   // WebIdl HTMLSelectElement
--- a/dom/html/HTMLTextAreaElement.h
+++ b/dom/html/HTMLTextAreaElement.h
@@ -49,17 +49,17 @@ public:
                                FromParser aFromParser = NOT_FROM_PARSER);
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   virtual int32_t TabIndexDefault() MOZ_OVERRIDE;
 
   // Element
-  virtual bool IsInteractiveHTMLContent() const MOZ_OVERRIDE
+  virtual bool IsInteractiveHTMLContent(bool aIgnoreTabindex) const MOZ_OVERRIDE
   {
     return true;
   }
 
   // nsIDOMHTMLTextAreaElement
   NS_DECL_NSIDOMHTMLTEXTAREAELEMENT
 
   // nsIDOMNSEditableElement
--- a/dom/html/HTMLVideoElement.cpp
+++ b/dom/html/HTMLVideoElement.cpp
@@ -122,17 +122,17 @@ nsresult HTMLVideoElement::SetAcceptHead
       "audio/*;q=0.6,*/*;q=0.5");
 
   return aChannel->SetRequestHeader(NS_LITERAL_CSTRING("Accept"),
                                     value,
                                     false);
 }
 
 bool
-HTMLVideoElement::IsInteractiveHTMLContent() const
+HTMLVideoElement::IsInteractiveHTMLContent(bool aIgnoreTabindex) const
 {
   return HasAttr(kNameSpaceID_None, nsGkAtoms::controls);
 }
 
 uint32_t HTMLVideoElement::MozParsedFrames() const
 {
   MOZ_ASSERT(NS_IsMainThread(), "Should be on main thread.");
   if (!sVideoStatsEnabled) {
--- a/dom/html/HTMLVideoElement.h
+++ b/dom/html/HTMLVideoElement.h
@@ -45,17 +45,17 @@ public:
 
   // Set size with the current video frame's height and width.
   // If there is no video frame, returns NS_ERROR_FAILURE.
   nsresult GetVideoSize(nsIntSize* size);
 
   virtual nsresult SetAcceptHeader(nsIHttpChannel* aChannel) MOZ_OVERRIDE;
 
   // Element
-  virtual bool IsInteractiveHTMLContent() const MOZ_OVERRIDE;
+  virtual bool IsInteractiveHTMLContent(bool aIgnoreTabindex) const MOZ_OVERRIDE;
 
   // WebIDL
 
   uint32_t Width() const
   {
     return GetIntAttr(nsGkAtoms::width, 0);
   }
 
--- a/dom/html/nsGenericHTMLElement.cpp
+++ b/dom/html/nsGenericHTMLElement.cpp
@@ -1789,21 +1789,21 @@ nsGenericHTMLElement::GetContextMenu(nsI
 
 bool
 nsGenericHTMLElement::IsLabelable() const
 {
   return IsAnyOfHTMLElements(nsGkAtoms::progress, nsGkAtoms::meter);
 }
 
 bool
-nsGenericHTMLElement::IsInteractiveHTMLContent() const
+nsGenericHTMLElement::IsInteractiveHTMLContent(bool aIgnoreTabindex) const
 {
   return IsAnyOfHTMLElements(nsGkAtoms::details, nsGkAtoms::embed,
                              nsGkAtoms::keygen) ||
-         HasAttr(kNameSpaceID_None, nsGkAtoms::tabindex);
+         (!aIgnoreTabindex && HasAttr(kNameSpaceID_None, nsGkAtoms::tabindex));
 }
 
 already_AddRefed<UndoManager>
 nsGenericHTMLElement::GetUndoManager()
 {
   nsDOMSlots* slots = GetExistingDOMSlots();
   if (slots && slots->mUndoManager) {
     nsRefPtr<UndoManager> undoManager = slots->mUndoManager;
--- a/dom/html/nsGenericHTMLElement.h
+++ b/dom/html/nsGenericHTMLElement.h
@@ -918,17 +918,17 @@ public:
   }
 
   bool IsHidden() const
   {
     return HasAttr(kNameSpaceID_None, nsGkAtoms::hidden);
   }
 
   virtual bool IsLabelable() const MOZ_OVERRIDE;
-  virtual bool IsInteractiveHTMLContent() const MOZ_OVERRIDE;
+  virtual bool IsInteractiveHTMLContent(bool aIgnoreTabindex) const MOZ_OVERRIDE;
 
   static bool TouchEventsEnabled(JSContext* /* unused */, JSObject* /* unused */);
 
   static inline bool
   CanHaveName(nsIAtom* aTag)
   {
     return aTag == nsGkAtoms::img ||
            aTag == nsGkAtoms::form ||
--- a/dom/html/test/forms/test_interactive_content_in_label.html
+++ b/dom/html/test/forms/test_interactive_content_in_label.html
@@ -27,23 +27,23 @@ https://bugzilla.mozilla.org/show_bug.cg
     <img id="yes7" src="data:image/png," usemap="#map">
     <input id="yes8" type="text" size="4">
     <keygen id="yes9">
     <label id="yes10">label</label>
     <object id="yes11" usemap="#map">object</object>
     <select id="yes12"><option>select</option></select>
     <textarea id="yes13" cols="1" rows="1"></textarea>
     <video id="yes14" controls></video>
-    <span id="yes15" tabindex="1">tabindex</span>
 
     <audio id="no1"></audio>
     <img id="no2" src="data:image/png,">
     <input id="no3" type="hidden">
     <object id="no4">object</object>
     <video id="no5"></video>
+    <span id="no6" tabindex="1">tabindex</span>
   </label>
 </form>
 <script class="testbody" type="text/javascript">
 
 /** Test for Bug 229925 **/
 
 var target = document.getElementById("target");
 
@@ -57,26 +57,26 @@ var yes_nodes = [
   document.getElementById("yes7"),
   document.getElementById("yes8"),
   document.getElementById("yes9"),
   document.getElementById("yes10"),
   document.getElementById("yes11"),
   document.getElementById("yes12"),
   document.getElementById("yes13"),
   document.getElementById("yes14"),
-  document.getElementById("yes15"),
 ];
 
 var no_nodes = [
   document.getElementById("text"),
   document.getElementById("no1"),
   document.getElementById("no2"),
   document.getElementById("no3"),
   document.getElementById("no4"),
   document.getElementById("no5"),
+  document.getElementById("no6"),
 ];
 
 var target_clicked = false;
 target.addEventListener("click", function() {
   target_clicked = true;
 });
 
 var node;