Back out a5a5d2c176f7 (bug 882865) because of Android test failures on a CLOSED TREE
[gecko.git] / b2g / components / FilePicker.js
blob4d27d01f51c1d9db8cd3dc3832a6cc2e11343a08
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this
4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 /*
7  * No magic constructor behaviour, as is de rigeur for XPCOM.
8  * If you must perform some initialization, and it could possibly fail (even
9  * due to an out-of-memory condition), you should use an Init method, which
10  * can convey failure appropriately (thrown exception in JS,
11  * NS_FAILED(nsresult) return in C++).
12  *
13  * In JS, you can actually cheat, because a thrown exception will cause the
14  * CreateInstance call to fail in turn, but not all languages are so lucky.
15  * (Though ANSI C++ provides exceptions, they are verboten in Mozilla code
16  * for portability reasons -- and even when you're building completely
17  * platform-specific code, you can't throw across an XPCOM method boundary.)
18  */
20 const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
22 // FIXME: improve this list of filters.
23 const IMAGE_FILTERS = ['image/gif', 'image/jpeg', 'image/pjpeg',
24                        'image/png', 'image/svg+xml', 'image/tiff',
25                        'image/vnd.microsoft.icon'];
26 const VIDEO_FILTERS = ['video/mpeg', 'video/mp4', 'video/ogg',
27                        'video/quicktime', 'video/webm', 'video/x-matroska',
28                        'video/x-ms-wmv', 'video/x-flv'];
29 const AUDIO_FILTERS = ['audio/basic', 'audio/L24', 'audio/mp4',
30                        'audio/mpeg', 'audio/ogg', 'audio/vorbis',
31                        'audio/vnd.rn-realaudio', 'audio/vnd.wave',
32                        'audio/webm'];
34 Cu.import('resource://gre/modules/XPCOMUtils.jsm');
36 XPCOMUtils.defineLazyServiceGetter(this, 'cpmm',
37                                    '@mozilla.org/childprocessmessagemanager;1',
38                                    'nsIMessageSender');
40 function FilePicker() {
43 FilePicker.prototype = {
44   classID: Components.ID('{436ff8f9-0acc-4b11-8ec7-e293efba3141}'),
45   QueryInterface: XPCOMUtils.generateQI([Ci.nsIFilePicker]),
47   /* members */
49   mParent: undefined,
50   mFilterTypes: [],
51   mFileEnumerator: undefined,
52   mFilePickerShownCallback: undefined,
54   /* methods */
56   init: function(parent, title, mode) {
57     this.mParent = parent;
59     if (mode != Ci.nsIFilePicker.modeOpen &&
60         mode != Ci.nsIFilePicker.modeOpenMultiple) {
61       throw Cr.NS_ERROR_NOT_IMPLEMENTED;
62     }
63   },
65   /* readonly attribute nsILocalFile file - not implemented; */
66   /* readonly attribute nsISimpleEnumerator files - not implemented; */
67   /* readonly attribute nsIURI fileURL - not implemented; */
69   get domfiles() {
70     return this.mFilesEnumerator;
71   },
73   get domfile() {
74     return this.mFilesEnumerator ? this.mFilesEnumerator.mFiles[0] : null;
75   },
77   appendFilters: function(filterMask) {
78     // Ci.nsIFilePicker.filterHTML is not supported
79     // Ci.nsIFilePicker.filterText is not supported
81     if (filterMask & Ci.nsIFilePicker.filterImages) {
82       this.mFilterTypes = this.mFilterTypes.concat(IMAGE_FILTERS);
83     }
85     // Ci.nsIFilePicker.filterXML is not supported
86     // Ci.nsIFilePicker.filterXUL is not supported
87     // Ci.nsIFilePicker.filterApps is not supported
88     // Ci.nsIFilePicker.filterAllowURLs is not supported
90     if (filterMask & Ci.nsIFilePicker.filterVideo) {
91       this.mFilterTypes = this.mFilterTypes.concat(VIDEO_FILTERS);
92     }
94     if (filterMask & Ci.nsIFilePicker.filterAudio) {
95       this.mFilterTypes = this.mFilterTypes.concat(AUDIO_FILTERS);
96     }
98     // Ci.nsIFilePicker.filterAll is by default
99   },
101   appendFilter: function(title, extensions) {
102     // pick activity doesn't support extensions
103   },
105   open: function(aFilePickerShownCallback) {
106     this.mFilePickerShownCallback = aFilePickerShownCallback;
108     cpmm.addMessageListener('file-picked', this);
110     let detail = {};
111     if (this.mFilterTypes) {
112        detail.type = this.mFilterTypes;
113     }
115     cpmm.sendAsyncMessage('file-picker', detail);
116   },
118   fireSuccess: function(file) {
119     this.mFilesEnumerator = {
120       QueryInterface: XPCOMUtils.generateQI([Ci.nsISimpleEnumerator]),
122       mFiles: [file],
123       mIndex: 0,
125       hasMoreElements: function() {
126         return (this.mIndex < this.mFiles.length);
127       },
129       getNext: function() {
130         if (this.mIndex >= this.mFiles.length) {
131           throw Components.results.NS_ERROR_FAILURE;
132         }
133         return this.mFiles[this.mIndex++];
134       }
135     };
137     if (this.mFilePickerShownCallback) {
138       this.mFilePickerShownCallback.done(Ci.nsIFilePicker.returnOK);
139       this.mFilePickerShownCallback = null;
140     }
141   },
143   fireError: function() {
144     if (this.mFilePickerShownCallback) {
145       this.mFilePickerShownCallback.done(Ci.nsIFilePicker.returnCancel);
146       this.mFilePickerShownCallback = null;
147     }
148   },
150   receiveMessage: function(message) {
151     if (message.name !== 'file-picked') {
152       return;
153     }
155     cpmm.removeMessageListener('file-picked', this);
157     let data = message.data;
158     if (!data.success || !data.result.blob) {
159       this.fireError();
160       return;
161     }
163     var mimeSvc = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
164     var mimeInfo = mimeSvc.getFromTypeAndExtension(data.result.blob.type, '');
166     var name = 'blob';
167     if (mimeInfo) {
168       name += '.' + mimeInfo.primaryExtension;
169     }
171     let file = new this.mParent.File(data.result.blob,
172                                      { name: name,
173                                        type: data.result.blob.type });
174     if (file) {
175       this.fireSuccess(file);
176     } else {
177       this.fireError();
178     }
179   }
182 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([FilePicker]);