mozilla/pdf.js — pull request #3017 by Rob--W (2013-03-31 14:26:41+00:00)
Title: Chrome extension - Highly improved

I've rewritten the Chrome extension, which includes the following improvements:

1. It works in incognito mode.
2. The URL is preserved (#1511).
3. Binds to the application/pdf MIME-type, instead of the .pdf extension (#2277).
Consequently, PDFs whose URL does not end with .pdf are displayed correctly,
and non-PDF resources (e.g. 404 Not Found) does not trigger the PDF viewer.
4. Support for PDFs in frames.
5. Improved Download method (i.a. by using `` when available).

Fixes #1511, #2277, #2284, #2410
Linked: #682, #772

The Chrome extension is uploaded https://chrome.google.com/webstore/detail/pdf-viewer/oemmndcbldboiebfnladdacbdfmadadm, and intend to actively provide support for it.

I tried hard to find the best way of integrating PDF.js in Chrome, and some decisions are not directly obvious. So I've explained some of my methods and decisions below:

## Mime type binding
I'm using the [`chrome.webRequest`](https://developer.chrome.com/extensions/webRequest.html) API to capture all requests. When the `Content-Type` header contains `application/pdf` (inclusive) OR `application/octet-stream` + extension `.pdf`, the PDF viewer is activated.

## Activation of PDF viewer.
To prevent the default pdf viewer from showing up, the Content-Type header has to be changed. After many attempts, I ended up using `application/xhtml+xml`, because it's the only MIME-type without unwanted side effects. The bonus of the XHTML doctype is that PDF files are never valid XHTML, so the strict parser will immediately give up and render a parse error.

When the PDF file is downloaded, a content script is inserted which replaced the whole document with the content of `content/web/viewer.html`. There's no significant (<1ms) latency for fetching this file, because it's packaged with the Chrome extension.
After inserting the HTML, all scripts are loaded, some variables are set and the `DOMContentLoaded` is triggered, which renders the PDF.

## XHTML quirks
A few issues were raised in viewer.js by the use of the XHTML document mode, all of them have been fixed:

- In XHTML, the tag names are lowercase (oposed to uppercase in regular HTML). To fix this difference, I transformed the tag name to uppercase where necessary.
- In Chrome, `document.activeElement` is not defined for XHTML documents. Falling back to `document.querySelector(':focus')` when `document.activeElement` is unavailable fixes the problem.