Skip to content

Commit

Permalink
Support OOPIF PDF viewer in Chrome
Browse files Browse the repository at this point in the history
Fix detection of document type in Chrome's built-in PDF viewer when the "OOPIF
for PDF Viewer" feature ("pdf-oopif") is enabled.

Fixes hypothesis/support#145
  • Loading branch information
robertknight committed Sep 6, 2024
1 parent f418ab6 commit cd72bf1
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 0 deletions.
24 changes: 24 additions & 0 deletions src/background/detect-content-type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,30 @@ export function detectContentType(
if (document_.querySelector('embed[type="application/pdf"]')) {
return { type: 'PDF' };
}

// Detect Chrome's PDF viewer when it is using out-of-process iframes
// ("OOPIF") instead of `<embed>`.
//
// In this case the DOM has a structure like:
//
// ```
// <body>
// # closed shadow root
// - <iframe type="application/pdf" ...></frame>
// </body>
// ```
//
// See https://github.com/hypothesis/support/issues/145#issuecomment-2330193036.
if (typeof chrome !== 'undefined') {
const bodyShadow = chrome.dom?.openOrClosedShadowRoot(document.body);
if (
bodyShadow &&
bodyShadow.querySelector('iframe[type="application/pdf"]')
) {
return { type: 'PDF' };
}
}

return null;
}

Expand Down
25 changes: 25 additions & 0 deletions tests/background/detect-content-type-test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { detectContentType } from '../../src/background/detect-content-type';

describe('detectContentType', () => {
const sandbox = sinon.createSandbox();

let el;
beforeEach(() => {
el = document.createElement('div');
Expand All @@ -9,6 +11,8 @@ describe('detectContentType', () => {

afterEach(() => {
el.parentElement.removeChild(el);

sandbox.restore();
});

it('returns HTML by default', () => {
Expand All @@ -21,6 +25,27 @@ describe('detectContentType', () => {
assert.deepEqual(detectContentType(), { type: 'PDF' });
});

it('returns "PDF" if Chrome\'s OOPIF PDF viewer is present', () => {
const fakeOpenOrClosedShadowRoot = sinon.stub();
sandbox.stub(window, 'chrome').value({
dom: {
openOrClosedShadowRoot: fakeOpenOrClosedShadowRoot,
},
});

const dummyElement = document.createElement('div');
const pdfViewer = document.createElement('iframe');
pdfViewer.setAttribute('type', 'application/pdf');
const fakeBodyShadowRoot = dummyElement.attachShadow({ mode: 'open' });
fakeBodyShadowRoot.append(pdfViewer);

fakeOpenOrClosedShadowRoot
.withArgs(document.body)
.returns(fakeBodyShadowRoot);

assert.deepEqual(detectContentType(), { type: 'PDF' });
});

it('returns "PDF" if Firefox PDF viewer is present', () => {
const fakeDocument = {
querySelector: function () {
Expand Down

0 comments on commit cd72bf1

Please sign in to comment.