"Ask every time": the prompting conundrum
When "ask me every time" is selected in the cookie pref UI in firefox, a modal dialog is thrown for every cookie set or get request during a pageload. This dialog shows some basic information about the site and the cookie, and presents the user with three options: accept the cookie, accept the cookie for this session only (until browser close), or reject the cookie. A checkbox allows the user to persist this decision (by adding the domain to the permissions whitelist or blacklist), which means no further prompts will be shown involving that particular domain.This dialog blocks pageload, since the outcome of the prompt can affect what content the site delivers (e.g. login cookies, session cookies etc). This coupled with the fact that a typical pageload can involve many hosts each with many cookies (e.g. advertisers) can make this a thoroughly displeasant experience. This has become worse in firefox 3, which will fetch independent 3rd party resources concurrently during pageload, resulting in potentially deep stacks of dialogs. See first bug link below, or:
A few bugs on the UX problem:
A backgrounder on the program flow involved, courtesy of timeless:
What's the use case for this feature?
1) The user wants to see each and every cookie going through the browser, accepting and rejecting them by hand. (For instance, they might reject all cookies from a site they're casually browsing to once; but accept a login cookie, and whitelist it, for a site they frequent and manually reject third party advertising cookies from the same pageload.)
2) The user is curious and wants to see what's happening, and later turns prompting off. (Perhaps a webdeveloper wants to see, or debug, cookies associated with their page.)
3) Other ideas?
How do we make it more better?
Two basic choices: improve the modal blocking dialog to make it less annoying, or switch to something not involving blocking dialogs (an async approach).
1) Make the blocking dialog less annoying. Firefox 3 exacerbated these dialogs by foregrounding the tab when a dialog is thrown, so if you load a bunch of tabs in the background you're going to get jumped around all over the place. Bug 405239 is about bringing back firefox 2 behavior, where dialogs would pop up over whatever tab you currently have focused, and is slated to be fixed (somewhat controversially) for 3.1. We could also put some lipstick on the pig by having a single dialog object that we update as new cookie requests come in, which might make things look nicer in the multiple-concurrent-connections world. White/blacklisting could also work better if we list using the base domain of the site from the eTLD service (currently we'll throw multiple prompts if weather.yahoo.com, biz.yahoo.com and search.yahoo.com all want to deal with the same cookie set for the .yahoo.com domain).
2) Switch to an async approach, like infobars. We could have a single dropdown infobar that appears in the tab during pageload, listing all the cookie requests and offering checkboxes for which ones you want to allow or block, and a button to apply those choices. This would let us do some nice display magic too, since we now have knowledge of all the cookies at once and we can collapse/group/nest the display as appropriate. The big problem with async is that we're doing the pageload without knowing the user's choices, so we have to assume something, and then reload the page when the user has made them (if they differ from our assumptions). And secondly, things may change during the reload, causing different cookies to come up.
- For instance, we could assume a blanket reject: load the page without any cookies, make a list of all the cookie requests, and let the user twiddle them. This would work great for sites that don't really need cookies, but would suck for sites that require logins. (Whitelisting can kick in here though, and allow those cookies during initial pageload.) It's also good from a privacy perspective, since the user that uses prompting probably would prefer blanket reject to begin with. Now, on reload, different cookies might come up - different advertising sites, post-login cookies, other dynamic content - so we might want the infobar set up to accept or deny certain domains during the load, rather than specific cookies. Or even "allow all cookies for this pageload, regardless of domain" (this would be implemented by tracking the toplevel content docshell, much the way 3rd party blocking now works). Finding a good solution to the dynamic content problem might be sticky.
- Or we could blanket accept. We'd want to sandbox the cookies for the page (per tab), so each tab gets a "fresh" cookie store and there's little to no tracking going on. So we'd load the page with all its cookies, and if a user later decides to reject them we do nothing - they'll get thrown away with the sandbox. If they accept them (or it's whitelisted) then we unsandbox them and overwrite any duplicate cookie in the main cookie store. This would get around sites that like to give "you must turn on cookies" warnings, but would still suck for sites that want logins. There would also be ordering problems: say you load twenty tabs from the same site in the background, then click through accepting cookies randomly... the site could be trying to set the same session cookie twenty times, which one do we keep? This isn't any worse than the blocking dialog situation though, so a minor issue. If the user accepts a cookie and there's one already in the main cookie store, we probably want to throw away the new one and use the main one (e.g. logins). The nice thing about blanket accept is that it kinda avoids the dynamic content problem with blanket reject, since we're accepting everything into a sandbox. If the user decides to let the site see his one login cookie and reloads, we reload the page into a sandbox but using that login cookie, and whatever new dynamic cookies come up still get sandboxed - and we can update the infobar with these new cookies. One simple question is, how much would doing this sandboxed acceptance affect privacy/tracking? The actual implementation shouldn't be hard (especially once we have per-docshell cookie stores from the per-window/per-tab cookie bug).
Doing two pageloads some fraction of the time would use more bandwidth. It's better UX for the case where a user opens many tabs that don't need cookies in the background, but probably worse for the case where they do all their browsing in one tab. (There's an extension called doppelganger that takes this one step further, and concurrently loads a link i) with cookies and ii) without cookies, compares the data served up, and enables or disables cookies based on whether the content differs.)
What do we do for cookie requests that have no associated page? (Safebrowsing, AUS, OCSP certificates, xpinstall, sidebar extensions, other random cookie-loving extensions.) We may have to keep a modal dialog around to deal with these cases. Or just always allow them?
Maybe we could use infobars in a sync way? Just make the dialog a nonmodal infobar instead so it's less intrusive? Not sure if this can be done, but basically falls under 1) and amounts to timeless' rant linked above.