Many APIs block. In reality, all APIs can block if they touch code or data that needs to be paged in, but the worst offenders are those that want to go out to disk to check out some files before returning. It's easy to write code without noticing you're calling a blocking API (I did it myself recently in some of the Greasemonkey code); a good tip-off is if it can return a "file not found" error.
A fundamental design goal of Chromium was to not make blocking calls on the UI thread, as that makes the UI hang. So there's some extra threads; the important two are the IO thread and the file thread.
The IO thread, confusingly, is not for doing blocking IO. Instead it's basically used to do all the non-UI work, including passing messages around asynchronously, starting up HTTP fetches, etc. Importantly, if it's blocked then interacting with a page will stall (as your interactions are proxied over to the renderer subprocess). The file thread, then, is then the extra thread for asynchronously performing random operations that can block on the disk. (There are additional threads for subsystems like history which also involve the disk.)
The potential for confusion of these names is likely what led to r8166 — Run ShellExecute on the file thread instead of the IO thread. How did Darin notice this? I'm not sure. It seems unlikely you'd call this code too often, and the penalty for blocking the IO thread is just that some non-blocking waits happening elsewhere end up taking too long. The jankometer can be used to identify when these threads block for too long — currently it allows the UI thread to wander off for 350ms and the IO thread to take 200ms — but I wouldn't expect it to cover this, as you have to be watching it when this code is exercised.