Bug 565272: Implement the accept attribute for audio/*, video/*. r=sicking
authorMounir Lamouri <mounir.lamouri@gmail.com>
Sat, 17 Jul 2010 00:00:28 -0700
changeset 47851 4dbc2a614b44493013160d3a455585a2d7ab5627
parent 47850 9fc8bbdd1ace93e34a338c12ced981de684c10a8
child 47852 bcc82f4858c56849693c76e746b5a422d3696add
push id14447
push userme@kylehuey.com
push dateSat, 17 Jul 2010 07:01:18 +0000
treeherderautoland@4dbc2a614b44 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssicking
bugs565272
milestone2.0b2pre
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 565272: Implement the accept attribute for audio/*, video/*. r=sicking
layout/forms/nsFileControlFrame.cpp
layout/forms/test/test_bug377624.html
toolkit/components/filepicker/src/nsFilePicker.js
toolkit/content/filepicker.properties
toolkit/locales/en-US/chrome/global/filepicker.properties
widget/public/nsIFilePicker.idl
widget/src/xpwidgets/nsBaseFilePicker.cpp
--- a/layout/forms/nsFileControlFrame.cpp
+++ b/layout/forms/nsFileControlFrame.cpp
@@ -858,16 +858,20 @@ nsFileControlFrame::CreateAccessible()
 PRInt32
 nsFileControlFrame::GetFileFilterFromAccept() const
 {
   nsAutoString accept;
   mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::accept, accept);
 
   if (accept.EqualsLiteral("image/*")) {
     return nsIFilePicker::filterImages;
+  } else if (accept.EqualsLiteral("audio/*")) {
+    return nsIFilePicker::filterAudio;
+  } else if (accept.EqualsLiteral("video/*")) {
+    return nsIFilePicker::filterVideo;
   }
 
   return 0;
 }
 ////////////////////////////////////////////////////////////
 // Mouse listener implementation
 
 NS_IMPL_ISUPPORTS2(nsFileControlFrame::MouseListener,
--- a/layout/forms/test/test_bug377624.html
+++ b/layout/forms/test/test_bug377624.html
@@ -9,17 +9,19 @@ https://bugzilla.mozilla.org/show_bug.cg
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 </head>
 <body onload="runTests();">
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=377624">Mozilla Bug 377624</a>
 <p id="display"></p>
 <div id="content">
-  <input id='i' type='file' accept="image/*">
+  <input id='a' type='file' accept="image/*">
+  <input id='b' type='file' accept="audio/*">
+  <input id='c' type='file' accept="video/*">
 </div>
 <pre id="test">
 <script type="application/javascript">
 
 /** Test for Bug 377624 **/
 
 SimpleTest.waitForExplicitFinish();
 
@@ -56,16 +58,19 @@ FilePickerService.prototype = {
   returnReplace: 2,
   filterAll: 1,
   filterHTML: 2,
   filterText: 4,
   filterImages: 8,
   filterXML: 16,
   filterXUL: 32,
   filterApps: 64,
+  filterAllowURLs: 128,
+  filterAudio: 256,
+  filterVideo: 512,
 
   // properties
   defaultExtension: "",
   defaultString: "",
   get displayDirectory() { return null; },
   set displayDirectory(val) { },
   file: null,
   get files() { return null; },
@@ -95,25 +100,46 @@ FilePickerService.prototype = {
 factory = {
   createInstance: function(aOuter, aIid) {
     if (aOuter != null)
       throw Cr.NS_ERROR_NO_AGGREGATION;
     return new FilePickerService().QueryInterface(aIid);
   }
 };
 
-document.getElementById('i').addEventListener("focus", function (aEvent) {
+document.getElementById('a').addEventListener("focus", function (aEvent) {
+    aEvent.target.removeEventListener("focus", arguments.callee, false);
+    synthesizeKey('VK_SPACE', {});
+  }, false);
+document.getElementById('b').addEventListener("focus", function (aEvent) {
+    aEvent.target.removeEventListener("focus", arguments.callee, false);
+    synthesizeKey('VK_SPACE', {});
+  }, false);
+document.getElementById('c').addEventListener("focus", function (aEvent) {
     aEvent.target.removeEventListener("focus", arguments.callee, false);
     synthesizeKey('VK_SPACE', {});
   }, false);
 
+var testData = [["a", FilePickerService.prototype.filterImages],
+                ["b",  FilePickerService.prototype.filterAudio],
+                ["c",  FilePickerService.prototype.filterVideo]];
+var currentTest = 0;
+
+function launchNextTest(aObserver)
+{
+  aObserver.shown = false;
+  aObserver.appendFilterCalled = false;
+  aObserver.filters = [];
+  aObserver.filterIndex = 0;
+
+  document.getElementById(testData[currentTest][0]).focus();
+}
+
 function runTests()
 {
-  var i = document.getElementById('i');
-
   netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
 
   Cm.registerFactory(CUSTOM_FILE_PICKER_ID,
                      FILE_PICKER_DESCRIPTION,
                      FILE_PICKER_CID,
                      factory);
 
   var obs = Cc["@mozilla.org/observer-service;1"].
@@ -130,51 +156,58 @@ function runTests()
           break;
         case "TEST_FILEPICKER_SHOW":
           this.shown = true;
           this.filterIndex = aData;
 
           SimpleTest.executeSoon(function () {
             netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
 
-            ok(observer.shown, "File picker show method should have been called");
-            ok(!observer.appendFilterCalled, "appendFilter should not have been called");
-            is(observer.filters.length, 1, "AppendFilters should have been called once");
+            ok(observer.shown,
+               "File picker show method should have been called");
+            ok(!observer.appendFilterCalled,
+               "appendFilter should not have been called");
+            is(observer.filters.length, 1,
+               "appendFilters should have been called once");
             is(observer.filters[0], FilePickerService.prototype.filterAll +
-               FilePickerService.prototype.filterImages,
-              "All and Images filters should have been added");
+               testData[currentTest][1],
+               "Incorrect filters have been added");
             is(observer.filterIndex, 1,
                "File picker should show the second filter index (first is zero)");
 
-            obs.removeObserver(observer, "TEST_FILEPICKER_APPENDFILTER", false);
-            obs.removeObserver(observer, "TEST_FILEPICKER_APPENDFILTERS", false);
-            obs.removeObserver(observer, "TEST_FILEPICKER_SHOW", false);
-            Cm.unregisterFactory(CUSTOM_FILE_PICKER_ID, factory);
+            if (++currentTest == testData.length) {
+              obs.removeObserver(observer, "TEST_FILEPICKER_APPENDFILTER", false);
+              obs.removeObserver(observer, "TEST_FILEPICKER_APPENDFILTERS", false);
+              obs.removeObserver(observer, "TEST_FILEPICKER_SHOW", false);
+              Cm.unregisterFactory(CUSTOM_FILE_PICKER_ID, factory);
 
-            Cm.registerFactory(FILE_PICKER_ID,
-                               "File Picker Service",
-                               FILE_PICKER_CID,
-                               null);
+              Cm.registerFactory(FILE_PICKER_ID,
+                                 "File Picker Service",
+                                 FILE_PICKER_CID,
+                                 null);
 
-            SimpleTest.finish();
+              SimpleTest.finish();
+            } else {
+              launchNextTest(observer);
+            }
           } );
           break;
       }
     },
     shown: false,
     appendFilterCalled: false,
     filters: [],
     filterIndex: 0
   };
 
   obs.addObserver(observer, "TEST_FILEPICKER_APPENDFILTER", false);
   obs.addObserver(observer, "TEST_FILEPICKER_APPENDFILTERS", false);
   obs.addObserver(observer, "TEST_FILEPICKER_SHOW", false);
 
   // We are simulating a focus then a SPACE key press to open the file picker.
   // We were not able to do this with |synthesizeMouse|.
-  i.focus();
+  launchNextTest(observer);
 }
 
 </script>
 </pre>
 </body>
 </html>
--- a/toolkit/components/filepicker/src/nsFilePicker.js
+++ b/toolkit/components/filepicker/src/nsFilePicker.js
@@ -188,16 +188,24 @@ nsFilePicker.prototype = {
                         filterBundle.GetStringFromName("xulFilter"));
     }
     this.mAllowURLs = !!(filterMask & nsIFilePicker.filterAllowURLs);
     if (filterMask & nsIFilePicker.filterApps) {
       // We use "..apps" as a special filter for executable files
       this.appendFilter(titleBundle.GetStringFromName("appsTitle"),
                         "..apps");
     }
+    if (filterMask & nsIFilePicker.filterAudio) {
+      this.appendFilter(titleBundle.GetStringFromName("audioTitle"),
+                        filterBundle.GetStringFromName("audioFilter"));
+    }
+    if (filterMask & nsIFilePicker.filterVideo) {
+      this.appendFilter(titleBundle.GetStringFromName("videoTitle"),
+                        filterBundle.GetStringFromName("videoFilter"));
+    }
     if (filterMask & nsIFilePicker.filterAll) {
       this.appendFilter(titleBundle.GetStringFromName("allTitle"),
                         filterBundle.GetStringFromName("allFilter"));
     }
   },
 
   appendFilter: function(title, extensions) {
     this.mFilterTitles.push(title);
--- a/toolkit/content/filepicker.properties
+++ b/toolkit/content/filepicker.properties
@@ -1,6 +1,8 @@
 allFilter=*
 htmlFilter=*.html; *.htm; *.shtml; *.xhtml
 textFilter=*.txt; *.text
 imageFilter=*.jpe; *.jpg; *.jpeg; *.gif; *.png; *.bmp; *.ico; *.svg; *.svgz; *.tif; *.tiff; *.ai; *.drw; *.pct; *.psp; *.xcf; *.psd; *.raw
 xmlFilter=*.xml
 xulFilter=*.xul
+audioFilter=*.aac; *.aif; *.flac; *.iff; *.m4a; *.m4b; *.mid; *.midi; *.mp3; *.mpa; *.mpc; *.oga; *.ogg; *.ra; *.ram; *.snd; *.wav; *.wma
+videoFilter=*.avi; *.divx; *.flv; *.m4v; *.mkv; *.mov; *.mp4; *.mpeg; *.mpg; *.ogm; *.ogv; *.ogx; *.rm; *.rmvb; *.smil; *.webm; *.wmv; *.xvid
--- a/toolkit/locales/en-US/chrome/global/filepicker.properties
+++ b/toolkit/locales/en-US/chrome/global/filepicker.properties
@@ -2,16 +2,18 @@
 #                    now live in toolkit/content/filepicker.properties
 allTitle=All Files
 htmlTitle=HTML Files
 textTitle=Text Files
 imageTitle=Image Files
 xmlTitle=XML Files
 xulTitle=XUL Files
 appsTitle=Applications
+audioTitle=Audio Files
+videoTitle=Video Files
 
 dirTextInputLabel=Directory name:
 dirTextInputAccesskey=n
 
 confirmTitle=Confirm
 confirmFileReplacing=%S already exists.\nDo you want to replace it?
 openButtonLabel=Open
 saveButtonLabel=Save
--- a/widget/public/nsIFilePicker.idl
+++ b/widget/public/nsIFilePicker.idl
@@ -51,28 +51,38 @@ interface nsIFilePicker : nsISupports
   const short modeSave        = 1;              // Save a file or directory
   const short modeGetFolder   = 2;              // Select a folder/directory
   const short modeOpenMultiple= 3;              // Load multiple files
 
   const short returnOK        = 0;              // User hit Ok, process selection
   const short returnCancel    = 1;              // User hit cancel, ignore selection
   const short returnReplace   = 2;              // User acknowledged file already exists so ok to replace, process selection
 
-  const long filterAll        = 0x01;           // *.*
-  const long filterHTML       = 0x02;           // *.html; *.htm
-  const long filterText       = 0x04;           // *.txt
-  const long filterImages     = 0x08;           // *.jpe; *.jpg; *.jpeg; *.gif;
+  const long filterAll        = 0x001;          // *.*
+  const long filterHTML       = 0x002;          // *.html; *.htm
+  const long filterText       = 0x004;          // *.txt
+  const long filterImages     = 0x008;          // *.jpe; *.jpg; *.jpeg; *.gif;
                                                 // *.png; *.bmp; *.ico; *.svg;
                                                 // *.svgz; *.tif; *.tiff; *.ai;
                                                 // *.drw; *.pct; *.psp; *.xcf;
                                                 // *.psd; *.raw
-  const long filterXML        = 0x10;           // *.xml
-  const long filterXUL        = 0x20;           // *.xul
-  const long filterApps       = 0x40;           // Applications (per-platform implementation)
-  const long filterAllowURLs  = 0x80;           // Allow URLs
+  const long filterXML        = 0x010;          // *.xml
+  const long filterXUL        = 0x020;          // *.xul
+  const long filterApps       = 0x040;          // Applications (per-platform implementation)
+  const long filterAllowURLs  = 0x080;          // Allow URLs
+  const long filterAudio      = 0x100;          // *.aac; *.aif; *.flac; *.iff;
+                                                // *.m4a; *.m4b; *.mid; *.midi;
+                                                // *.mp3; *.mpa; *.mpc; *.oga;
+                                                // *.ogg; *.ra; *.ram; *.snd;
+                                                // *.wav; *.wma
+  const long filterVideo      = 0x200;          // *.avi; *.divx; *.flv; *.m4v;
+                                                // *.mkv; *.mov; *.mp4; *.mpeg;
+                                                // *.mpg; *.ogm; *.ogv; *.ogx;
+                                                // *.rm; *.rmvb; *.smil; *.webm;
+                                                // *.wmv; *.xvid
 
  /**
   * Initialize the file picker widget.  The file picker is not valid until this
   * method is called.
   *
   * @param      parent   nsIDOMWindow parent.  This dialog will be dependent
   *                      on this parent. parent must be non-null.
   * @param      title    The title for the file widget
--- a/widget/src/xpwidgets/nsBaseFilePicker.cpp
+++ b/widget/src/xpwidgets/nsBaseFilePicker.cpp
@@ -127,16 +127,26 @@ nsBaseFilePicker::AppendFilters(PRInt32 
     filterBundle->GetStringFromName(NS_LITERAL_STRING("textFilter").get(), getter_Copies(filter));
     AppendFilter(title,filter);
   }
   if (aFilterMask & filterImages) {
     titleBundle->GetStringFromName(NS_LITERAL_STRING("imageTitle").get(), getter_Copies(title));
     filterBundle->GetStringFromName(NS_LITERAL_STRING("imageFilter").get(), getter_Copies(filter));
     AppendFilter(title,filter);
   }
+  if (aFilterMask & filterAudio) {
+    titleBundle->GetStringFromName(NS_LITERAL_STRING("audioTitle").get(), getter_Copies(title));
+    filterBundle->GetStringFromName(NS_LITERAL_STRING("audioFilter").get(), getter_Copies(filter));
+    AppendFilter(title,filter);
+  }
+  if (aFilterMask & filterVideo) {
+    titleBundle->GetStringFromName(NS_LITERAL_STRING("videoTitle").get(), getter_Copies(title));
+    filterBundle->GetStringFromName(NS_LITERAL_STRING("videoFilter").get(), getter_Copies(filter));
+    AppendFilter(title,filter);
+  }
   if (aFilterMask & filterXML) {
     titleBundle->GetStringFromName(NS_LITERAL_STRING("xmlTitle").get(), getter_Copies(title));
     filterBundle->GetStringFromName(NS_LITERAL_STRING("xmlFilter").get(), getter_Copies(filter));
     AppendFilter(title,filter);
   }
   if (aFilterMask & filterXUL) {
     titleBundle->GetStringFromName(NS_LITERAL_STRING("xulTitle").get(), getter_Copies(title));
     filterBundle->GetStringFromName(NS_LITERAL_STRING("xulFilter").get(), getter_Copies(filter));