Bug 841949 - Improve id3 parsing in the music app

r? @davidflanagan

I've split this PR up into discrete chunks (add a test, then add the feature that I'm testing in the next commit) to hopefully make it easier to test everything, or at least to see what it is that I'm doing. When this gets r+, I'll collapse them all into one commit.

First, I added tests for our existing id3 parsing. Then I tested and fixed an issue with our extended header support. I'm pretty sure this is correct now, since it's what the spec says and other parsers do it, though I think extended headers are extremely rare in practice.

Next, I wrote tests for unsynchronization and then implemented it. I think I got this right, and it works on the real-world examples of unsynchronization that I have.

Finally, I tested and added support for multi-value frames in id3v2.4. This should all be correct, except that I'm not 100% sure that there'll only be one BOM for the whole frame under UTF-16. I couldn't find any real world examples of this, since all the id3v2.4 stuff I've seen uses UTF-8.

If you'd like to understand the test mp3s I made, go over to https://github.com/jimporter/id3gen, which contains all the code I use to generate the test files.

https://bugzilla.mozilla.org/show_bug.cgi?id=841949
I'm still not used to chained promises. I found this code confusing because I hadn't gotten to the .then() call below, so I was suprised you were returning a blob here instead of a url. If you gave this function a name, you could have code like:

checkCache(cacheKey).then(createThumbnail).then(makeURL) 

And I could wrap my head around that.

Anyway: this bit is a little confusingi, and if you can simplify, that would be great.  Adding to the confusion, of course, is that there are two layers of cache and the terminology does not clearly distinguish between them.