Bug 490287 - slider of audio/video element hasn't accessible name, r=marcoz, davidb, dolske, l10n, mconor, sr=neil
authorAlexander Surkov <surkov.alexander@gmail.com>
Thu, 14 May 2009 13:29:33 +0800
changeset 28315 d5b86378d271c066b22fa9d2f7d9689cfbfd8167
parent 28314 fe3e17356dfe85efc4bf2c406a431d705b919950
child 28316 2322a5800d590ae9e5da2bf5aaec074244efa8a1
push id7000
push usersurkov.alexander@gmail.com
push dateThu, 14 May 2009 04:30:18 +0000
treeherdermozilla-central@d5b86378d271 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmarcoz, davidb, dolske, l10n, mconor, neil
bugs490287
milestone1.9.2a1pre
Bug 490287 - slider of audio/video element hasn't accessible name, r=marcoz, davidb, dolske, l10n, mconor, sr=neil
accessible/public/Makefile.in
accessible/public/nsIXBLAccessible.idl
accessible/src/base/nsAccessible.cpp
accessible/tests/mochitest/test_elm_media.html
toolkit/content/widgets/videocontrols.xml
toolkit/locales/en-US/chrome/global/videocontrols.dtd
--- a/accessible/public/Makefile.in
+++ b/accessible/public/Makefile.in
@@ -67,16 +67,17 @@ XPIDLSRCS = \
       nsIAccessibleEvent.idl \
       nsIAccessibleEditableText.idl \
       nsIAccessibleHyperLink.idl \
       nsIAccessibleHyperText.idl \
       nsIAccessibleTable.idl \
       nsIAccessibleText.idl \
       nsIAccessibleValue.idl \
       nsIAccessibleImage.idl \
+      nsIXBLAccessible.idl \
       $(NULL)
 
 ifdef MOZ_XUL
 XPIDLSRCS += \
       nsIAccessibleTreeCache.idl \
       $(NULL)
 endif
 
new file mode 100644
--- /dev/null
+++ b/accessible/public/nsIXBLAccessible.idl
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla browser.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Alexander Surkov <surkov.alexander@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+/**
+ * XBL controls can implement this interface to provide own implementation of
+ * accessible properties.
+ */
+[scriptable, uuid(3716eb86-166b-445b-a94a-9b522fee96e6)]
+interface nsIXBLAccessible : nsISupports
+{
+  /**
+   * Return accessible name.
+   */
+  readonly attribute DOMString accessibleName;
+};
--- a/accessible/src/base/nsAccessible.cpp
+++ b/accessible/src/base/nsAccessible.cpp
@@ -38,16 +38,17 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsAccessible.h"
 #include "nsAccessibleRelation.h"
 #include "nsHyperTextAccessibleWrap.h"
 
 #include "nsIAccessibleDocument.h"
 #include "nsIAccessibleHyperText.h"
+#include "nsIXBLAccessible.h"
 #include "nsAccessibleTreeWalker.h"
 
 #include "nsIDOMElement.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMDocumentXBL.h"
 #include "nsIDOMDocumentTraversal.h"
 #include "nsIDOMHTMLDocument.h"
 #include "nsIDOMHTMLFormElement.h"
@@ -278,16 +279,23 @@ nsAccessible::GetName(nsAString& aName)
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
   GetARIAName(aName);
   if (!aName.IsEmpty())
     return NS_OK;
 
+  nsCOMPtr<nsIXBLAccessible> xblAccessible(do_QueryInterface(mDOMNode));
+  if (xblAccessible) {
+    nsresult rv = xblAccessible->GetAccessibleName(aName);
+    if (!aName.IsEmpty())
+      return NS_OK;
+  }
+
   nsresult rv = GetNameInternal(aName);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (!aName.IsEmpty())
     return NS_OK;
 
   // In the end get the name from tooltip.
   nsCOMPtr<nsIContent> content = nsCoreUtils::GetRoleContent(mDOMNode);
--- a/accessible/tests/mochitest/test_elm_media.html
+++ b/accessible/tests/mochitest/test_elm_media.html
@@ -62,20 +62,21 @@ https://bugzilla.mozilla.org/show_bug.cg
           },
           { // buffer bar
             role: ROLE_PROGRESSBAR
           },
           { // progress bar
             role: ROLE_PROGRESSBAR
           },
           { // slider of progress bar
-            role: ROLE_SLIDER
+            role: ROLE_SLIDER,
+            name: "0:00 of 0:01 elapsed"
           },
-          { // duration label
-            role: ROLE_LABEL
+          { // duration label, role="presentation"
+            role: ROLE_NOTHING
           },
           { // mute button
             role: ROLE_PUSHBUTTON,
             name: "Mute"
           }
         ]
       };
       testAccessibleTree("audio", accTree);
--- a/toolkit/content/widgets/videocontrols.xml
+++ b/toolkit/content/widgets/videocontrols.xml
@@ -73,17 +73,34 @@
           ]]>
           </body>
       </method>
       </implementation>
   </binding>
 
   <binding id="suppressChangeEvent"
             extends="chrome://global/content/bindings/scale.xml#scale">
-      <implementation>
+    <implementation implements="nsIXBLAccessible">
+      <!-- nsIXBLAccessible -->
+      <property name="accessibleName" readonly="true">
+        <getter>
+          if (this.type != "scrubber")
+              return "";
+
+          var currTime = this.thumb.timeLabel.getAttribute("value");
+          var totalTime = this.durationValue;
+
+          return this.scrubberNameFormat.replace(/#1/, currTime).
+              replace(/#2/, totalTime);
+        </getter>
+      </property>
+
+      <!-- Public -->
+      <field name="scrubberNameFormat">"&scrubberScale.nameFormat;"</field>
+      <field name="durationValue">""</field>
 
       <field name="thumb">null</field>
       <field name="type">null</field>
       <field name="Utils">null</field>
       <constructor>
           <![CDATA[
           this.thumb = document.getAnonymousElementByAttribute(this, "class", "scale-thumb");
           this.type = this.getAttribute("class");
@@ -154,17 +171,17 @@
                             pauselabel="&playButton.pauseLabel;"/>
                     <stack class="scrubberStack" flex="1">
                         <box class="backgroundBar"/>
                         <progressmeter class="bufferBar"/>
                         <progressmeter class="progressBar" max="10000"/>
                         <scale class="scrubber" movetoclick="true"/>
                     </stack>
                     <vbox class="durationBox">
-                        <label class="durationLabel"/>
+                        <label class="durationLabel" role="presentation"/>
                     </vbox>
                     <button class="muteButton"
                             mutelabel="&muteButton.muteLabel;"
                             unmutelabel="&muteButton.unmuteLabel;"/>
                     <stack class="volumeStack" hidden="true">
                         <box class="volumeBackgroundBar"/>
                         <scale class="volumeControl" orient="vertical" dir="reverse" movetoclick="true"/>
                     </stack>
@@ -493,16 +510,20 @@
                         if (mins < 10)
                             mins = "0" + mins;
                         timeString = hours + ":" + mins + ":" + secs;
                     } else {
                         timeString = mins + ":" + secs;
                     }
                     this.durationLabel.setAttribute("value", timeString);
 
+                    // "durationValue" property is used by scale binding to
+                    // generate accessible name.
+                    this.scrubber.durationValue = timeString;
+
                     // If the duration is over an hour, thumb should show h:mm:ss instead of mm:ss
                     this.scrubberThumb.showHours = (duration >= 3600000);
 
                     this.scrubber.max = duration;
                     // XXX Can't set increment here, due to bug 473103. Also, doing so causes
                     // snapping when dragging with the mouse, so we can't just set a value for
                     // the arrow-keys.
                     //this.scrubber.increment = duration / 50;
--- a/toolkit/locales/en-US/chrome/global/videocontrols.dtd
+++ b/toolkit/locales/en-US/chrome/global/videocontrols.dtd
@@ -1,5 +1,12 @@
 <!ENTITY playButton.playLabel "Play">
 <!ENTITY playButton.pauseLabel "Pause">
 <!ENTITY muteButton.muteLabel "Mute">
 <!ENTITY muteButton.unmuteLabel "Unmute">
 
+<!--
+Localization note: the #1 string is the current media position, and the #2
+string is the total duration. For example, when at the 5 minute mark in a 6
+hour long video, #1 would be "5:00" and #2 would be "6:00:00", result string
+would be "5:00 of 6:00:00 elapsed".
+-->
+<!ENTITY scrubberScale.nameFormat "#1 of #2 elapsed">