Open Bug 898856 Opened 7 years ago Updated 2 years ago

FileHandle API: getFile() returns invalid files

Categories

(Core :: DOM: Core & HTML, defect, P5)

24 Branch
x86_64
macOS
defect

Tracking

()

UNCONFIRMED

People

(Reporter: Soeren.Balko, Unassigned)

Details

(Keywords: testcase)

Attachments

(3 files)

User Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.71 Safari/537.36

Steps to reproduce:

I implemented a simple blob storage feature which relies on the FileHandle API in IDB. To do so, I followed the instructions on https://developer.mozilla.org/en-US/docs/WebAPI/FileHandle?redirectlocale=en-US&redirectslug=WebAPI%2FFileHandle_API. That is, I first create a database and initially add an object store, create a file handle, add that file handle into the object store, then open locked file for writing, append a Blob, call flush. Finally, I retrieve a file calling getFile() on the file handle. 

I am on the current Aurora release on OSX (version 24.0a2, 64bit)


Actual results:

Everything goes fine and I could also verify on disk that a corresponding file was created and populated with data (). Now when I try to get a URL for the file (as asynchronously retrieved from FileHandle.getFile()) the following happens:
- Calling window.URL.createObjectURL(...) returns a seemingly valid blob URL. However, embedding it into a <a href="url" download="myfile.bin" /> has no effect - i.e., clicking on the URL does not cause FF to download the file or to alternatively render it. Actually, nothing happens.
- Calling (new FileReader()).readAdDataURL(file) returns undefined.

When debugging this issue I noticed that the mozFullPath property on the file is an empty string which seems wrong.




Expected results:

Naturally, the file that is returned from the file handle's getFile() function should represent the actual file on disk where the previously stored blob is contained.
Correction: the above stated report says that creating a data URL through the FileReader interface did not work. Actually, I meanwhile confirmed that it does actually work.

However, I cannot seem to be able to use the Blob URL I retrieve from window.URL.createObjectURL() to use it for the href attribute of an anchor tag like to:

<a href="blob:...." download="myfile.bin" type="application/octet-stream">Download file</a>

This really seems to be a particularity of the files created through the FileHandle API. Regular Blobs which create created in memory (new Blob(...)) do not seem to be affected by this issue. That is to say, clicking on an anchor link like the one above opens a download dialog, as expected.

This is the code I use:

       var openRequest = indexedDB.open('myfiledb');
        var handle, file;

        openRequest.onsuccess = function(event) {
            var database = event.target.result;
            var createRequest = database.mozCreateFileHandle('foo.bin', 'binary');

            createRequest.onsuccess = function(event) {
                handle = event.target.result;
                var locked = handle.open('readwrite');
                var writeRequest = locked.write('This is a test!');

                writeRequest.onsuccess = function() {
                    var flushRequest = locked.flush();

                    flushRequest.onsuccess = function() {
                        locked.abort();
                        var fileRequest = handle.getFile();

                        fileRequest.onsuccess = function(event) {
                            file = event.target.result;

                            var blobUrl = window.URL.createObjectURL(file, {autoRevoke: false});
                            var links = document.getElementById('links');

                            var reader = new FileReader();
                            reader.onloadend = function(event) {
                                var dataUrl = event.target.result;
                                links.innerHTML = '<a href="'+blobUrl+'" type="application/octet-stream" download="download.bin">Download from Blob URL</a><br><a href="'+dataUrl+'" type="application/octet-stream" download="download.bin">Download from Data URL</a>';
                            };
                            reader.readAsDataURL(file);

                        };

                    };
                };
            }; 
        };
Hardware: x86 → x86_64
Another observation is that as soon as I store a file snapshot in some object store and retrieve it from there later on, the URL that is generated from URL.createObjectURL(...) does resolve into the actual file content.
Could you attach a testcase showing the issue, please.
Component: General → DOM
Flags: needinfo?(Soeren.Balko)
Keywords: testcase-wanted
This test case creates a file handle (without inserting it into an IDB object store), then opens a locked file, inserts a string, flushes to disk, then gets the file from the handle and constructs a Blob URL and a data URL. The data URL behaves as expected whereas the Blob URL can apparently not be resolved.
Flags: needinfo?(Soeren.Balko)
Attachment #782406 - Attachment mime type: text/plain → text/html
Attached file ffbug2.html
Here is a second test case showing a surprising behavior. When I create a file handle and start appending chunks, retrieving the File object works OK (i.e., a File object with the proper size is returned) up to a certain file size. In my case, the borderline between correct and incorrect is somewhere between 3 and 4 GBs. Starting a 4 GB, the File object has a size that appears random to me and is, at any rate, different to what is being returned from the "getMetadata" call on the locked file. In order to play with different behaviors, you may alter the first parameter in the call to "fillFile" (like 43) until you see a deviation.
Attachment #784664 - Attachment mime type: text/plain → text/html
I just checked whether the bug has been fixed in current releases. I tested version 26.0a2 (Aurora) on OSX and version 25 on Windows. Sadly, this issue has not been fixed. 

Is there a way how I can help narrowing down the root cause? As this bug only surfaces for very large files (>3 GB), I suspect a 32bit integer overflow to be behind this issue. 

Also, the sole reason why we need Firefox' FileHandle API is to be able to generate a Blob URL for a large, single piece of data. That Blob URL then becomes a clickable anchor tag on the Web site where users can download that piece of data into a local file. The Blob is too large to fit into main memory apiece. This is why we need to build it up progressively on a local persistence. Unfortunately, Firefox does not support the FileSystem API (FileWriter/FileWriterSync) such that the FileHandle API seems like the only viable alternative. Perhaps except for using plugins such as Java or Flash for that purpose. 

Any support was greatly appreciated!
I would like to add that I have also experienced this bug. I can make an <img src=url> but not make <a href=url>. getFile does produce a blob url that works for img, but not for a.
Hi, my peers and I were looking into this bug for a school project we were working on for one of our computer science courses. We'd like to note that we found that this bug also causes the browser to crash when the bad blob URL is clicked on multiple times in succession (we were able to modify the testcase provided by Soeren Balko to trigger the crash automatically using JavaScript). Looking at the crash report and running it through GDB, we found that the crash occurs at dom/filehandle/FileHandle.cpp:471 due to a segmentation fault which causes an assertion failure (mRequestMode == PARALLEL). Upon closer inspection, we found the location of 'this' at that point to be 0x58. We tried to reproduce this with MemorySanitizer but were unable to, which might suggest that this is being caused due to a race condition. We've been able to reproduce this in OS X, Linux, and Windows. We are sharing this as part of our project, and we hope that this information will come in handy for fixing this bug!

Crash report: https://crash-stats.mozilla.com/report/index/1d172a30-643a-4689-9c51-47b1e2141215
I should also note that this occurs in the current stable release version of Firefox (34.0.5).
could you attach the minimal testcase, please.
Flags: needinfo?(amit.burstein)
Attached file reduced test case
Flags: needinfo?(amit.burstein)
I've attached the testcase. Note that it's pretty identical to the original, just with some removed cruft and a JS function that clicks the bad anchor tag in a loop (with delay) to trigger the crash (check the browser console to see how many "clicks" it takes before a crash occurs). The fact that the number of clicks required is nondeterministic across attempts further suggests that a race condition is causing this. Hope that helps!
(In reply to amit.burstein from comment #12)
> I've attached the testcase. Note that it's pretty identical to the original,
> just with some removed cruft and a JS function that clicks the bad anchor
> tag in a loop (with delay) to trigger the crash (check the browser console
> to see how many "clicks" it takes before a crash occurs). The fact that the
> number of clicks required is nondeterministic across attempts further
> suggests that a race condition is causing this. Hope that helps!

Ty. As your testcase crashes the browser, I think it's a different bug. I filed bug 1113062 about that.
https://bugzilla.mozilla.org/show_bug.cgi?id=1472046

Move all DOM bugs that haven’t been updated in more than 3 years and has no one currently assigned to P5.

If you have questions, please contact :mdaly.
Priority: -- → P5
Component: DOM → DOM: Core & HTML
You need to log in before you can comment on or make changes to this bug.