Gijs, I talked things over with Jonathan, here are our findings.
(In reply to :Gijs (he/him) from comment #9)
- we used to always use system principal for saves. bug 1398229 made us use the node's principal. That seems to have just not worked for the http auth case. I don't really know why. I don't even know if the preflight request ever did anything better when it did use system principal (ie maybe it didn't work before we started passing the node's principal). Anyway, now we're passing loading principal. I find this a little odd; is loading principal really the best idea if we have webpage 1 (html) linking to webpage 2 (also html) ? Shouldn't it be triggering principal? It's just a link, not an included image or other included resource.
Right, so good we are not using the SystemPrincipal anymore, that was definitely wrong. Jonathan and I are with you, we should in fact use the triggeringPrincipal (which we suppose is this.principal) instead of the node's principal.
- there was a fallback that "just" called saveURL without using a principal. That used to use system principal because no principal was present. Then bug 1409449 made us not show an http auth prompt for that.
Right - that sounds good as well - using SystemPrincipal was definitely wrong.
- then I made webbrowserpersist / saving anything require a principal, in bug 1469916. But this code didn't pass one, so it crashed, until I fixed bug 1473507. I thought I got all the consumers there (ie added principals everywhere), clearly I was wrong. I blame the insane amount of indirection we have for saving anything - there must be at least 10 different utility functions that eventually call internalSave, and they get called all over the shop.
So, that quirks we have accumulated over time within internalSave() to query the right principal  makes me nervous quite a bit. We should file a follow up bug, adding some kind of assertion (similar to what we did for providing the top-level triggeringPrincipal) that we always pass an explicit TriggeringPrincipal to internalSave().
Anyway... the trivial fix is to just add a principal to the fallback case. I've added a patch for that. But I'm confused about why the preflight request doesn't handle the http auth prompt itself, ie why are we hitting the fallback? Christoph/Baku, can you check both why we're not handling http auth for the initial request and whether loading principal is really right here, or should the initial request use triggering principal, too?
The patch you have looks good, but I can't help you with the http auth problem - I have no idea why we are hitting the fallback. Probably Dragana or someone from the Necko team can be of more help with that problem.