Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Chromium extension using streamsPrivate API! #4126

Merged
merged 5 commits into from
Jan 22, 2014

Conversation

Rob--W
Copy link
Member

@Rob--W Rob--W commented Jan 15, 2014

Opera 19 has finally added support for the streamsPrivate API, and whitelisted the PDF Viewer hosted on addons.opera.com with (extension ID encfpfilknmenlmjemepncnlbbjlabkc).

This feature was developed 5 months ago at https://github.com/Rob--W/pdf.js/issues/1. The main new features are support for POST requests and FTP urls.

See commit messages for implementation notes.
To test the extension in Opera 19, follow the following steps:

  1. Get Opera 19 from http://www.opera.com/computer/next (I've tested with v19.0.1326.26).
  2. Build the extension (instructions at https://github.com/Rob--W/pdf.js/issues/1), or get a test build from https://robwu.nl/pdfjs/pdfjs-0.8.877-streamsPrivate.zip
  3. Unpack the zip file.
  4. Start Opera, and go to Extensions (Ctrl + E).
  5. Click on the button to enable Developer mode.
  6. Click on "Load unpacked extension".
  7. Use the file browser to select the directory containing the contents of the extracted zip file (or if you've built yourself: pdf.js/build/chromium).
  8. To verify that the new feature works as intended, try to view a PDF file from a FTP site. Just Google for "ftp pdf" and pick any search result that serves a PDF file over ftp:.

Unfortunately, Chromium has not yet responded to the request of getting the extension ID whitelisted: https://code.google.com/p/chromium/issues/detail?id=326949 The extension will gracefully fall back to the current behavior in Chrome/Chromium.

Fixes issues:

/cc @andreasbovens

This method captures all application/pdf streams, loads the viewer
and passes the stream to the PDF.js viewer.

This commit shows a proof of concept using the chrome.streamsPrivate API.

Advantages of new method:
- Access to the response body of the original request, thus fewer
  network requests.
- PDFs from non-GET requests (e.g. POST) are now supported.
- FTP files are also supported.

Possible improvements:
- Use declared content scripts instead of dynamic chrome.tabs.executeScript.
  This allows the extension to render the viewer in frames when the
  extension is disallowed to run executeScript for the top URL.
- Use chrome.declarativeWebRequest instead of webRequest, and replace
  background page with event page (don't forget to profile the
  difference & will the background/event page still work as intended?).
This is needed for propagating the extension's permissions
to the extension's iframe, in the rare event that the PDF is
loaded in a sub frame, and the extension does not have access to the
top frame. For instance, when a http:-PDF file is embedded in a
local file, while "Allow access to local URLs" is disabled.

Note: Propagating permissions by inserting content scripts is an
 undocumented feature (http://crbug.com/302548).

Whenever it breaks, the issue (cross-domain permissions for XHR)
can be solved by using a content script that gets the blob using
the XMLHttpRequest API, followed by `postMessage` (via transferables)
to efficiently pass the arraybuffer back to the PDF Viewer.
Also:
- Use webNavigation.getAllFrames to find out whether the navigation has
  already started. This is (at least) needed for top-level navigation to
  a stream. The webNavigation.onErrorOccurred event has become obsolete,
  and has been removed.
When a new incognito session is started, the onExecuteMimeTypeHandler event is
often not dispatched in time. Instead, it's triggered in the non-incognito profile.

This commit offers a work-around that allows new incognito instances to view PDF files.
Use streamsPrivate API when available.
When the API is not available, the extension will still work on
on http/https/file URLs, but not for POST requests or FTP.

As of writing, the Chromium project has still not whitelisted
the PDF Viewer extension in the Chrome Web Store.
 (extension ID oemmndcbldboiebfnladdacbdfmadadm)
Request to whitelist PDF.js in Chromium:
 https://code.google.com/p/chromium/issues/detail?id=326949

Opera 19 has whitelisted the PDF Viewer extension from
 https://addons.opera.com/extensions/details/pdf-viewer/
 (extension ID encfpfilknmenlmjemepncnlbbjlabkc)
 (https://github.com/Rob--W/pdf.js/issues/1#issuecomment-32357302)

If you want to test the streamsPrivate feature in Chrome,
edit the build/extensions/manifest.json and add the "key" again
 (see this commit for the value of this "key" field).
Rob--W referenced this pull request Jan 17, 2014
Before commit:
chrome-extension://EXTENSIONID/content/web/viewer.html?file=http%3A%2F%2Fexample.com%2Ffile.pdf

After commit:
chrome-extension://EXTENSIONID/http://example/file.pdf

Technical details:
- The extension's background page uses the webRequest API to intercept
  requests for <extension host>/<real path to pdf>, and redirect it to
  the viewer's URL.
- viewer.js uses history.replaceState to rewrite the URL, so that it's
  easier for users to recognize and copy-paste URLs.
- The fake paths /http:, /https:, /file:, etc. have been added to the
  web_accessible_resources section of the manifest file, in order to
  avoid seeing chrome-extension://invalid/ instead of the actual URL
  when using history back/forward to navigate from/to the PDF viewer.
- Since the relative path resolving doesn't work because relative URLs
  are inaccurate, a <base> tag has been added. This method has already
  been proven to work in the Firefox add-on.

Notes:
- This commit has been cherry-picked from crx-using-streams-api.
- Need to merge #3582 to deal with
  a bug in Chrome <=30
- In Chrome, getting the contents of a FTP file is not possible, so
  there's no support for FTP files, even though the extension router
  recognizes the ftp: scheme.
@yurydelendik
Copy link
Contributor

web/* parts look good (new api stuff were not tested)

yurydelendik added a commit that referenced this pull request Jan 22, 2014
Chromium extension using streamsPrivate API!
@yurydelendik yurydelendik merged commit ba1eb4d into mozilla:master Jan 22, 2014
@yurydelendik
Copy link
Contributor

Thanks for the patch

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants