Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "doqment",
"version": "0.9.1",
"version": "0.9.2",
"description": "Mozilla's HTML5 PDF Viewer with Reader-mode add-on.",
"homepage": "https://github.com/shivaprsd/doqment",
"repository": "github:shivaprsd/doqment",
Expand Down
2 changes: 1 addition & 1 deletion src/doq
2 changes: 1 addition & 1 deletion src/manifest-v2.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"manifest_version": 2,
"version": "0.9.1",
"version": "0.9.2",

"name": "doqment PDF Reader",
"short_name": "doqment",
Expand Down
2 changes: 1 addition & 1 deletion src/manifest-v3.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"manifest_version": 3,
"version": "0.9.1",
"version": "0.9.2",
"minimum_chrome_version": "116",

"name": "doqment PDF Reader",
Expand Down
11 changes: 11 additions & 0 deletions src/options.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"type": "schema",
"properties": {
"showPdfTitle": {
"title": "Show PDF title on viewer tabs",
"description": "Whether to display the PDF's title (if present) in the titlebar/on the tabs, before the filename.",
"type": "boolean",
"default": true
}
}
}
Binary file modified src/pages/Try Again
Binary file not shown.
3 changes: 3 additions & 0 deletions src/pages/options.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
<script src="/scripts/options.js" type="module"></script>
</head>
<body>
<div id="extOptions" class="options">
<h3>Extension options</h3>
</div>
<div id="doqOptions" class="options">
<h3>Reader mode options</h3>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/pdfjs
Submodule pdfjs updated 137 files
20 changes: 19 additions & 1 deletion src/scripts/doqment.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ const Doqment = {
return {
docStyle: document.documentElement.style,
viewer: document.getElementById("viewerContainer"),
printButton: document.getElementById("printButton"),
secondaryOpen: document.getElementById("secondaryOpenFile"),
viewerClassList: document.getElementById("outerContainer").classList
};
},
Expand All @@ -30,22 +32,37 @@ const Doqment = {
if (isTouchScreen()) {
this.options.autoToolbar = true;
}
const {viewer} = this.config;
const { viewer, printButton, secondaryOpen } = this.config;
viewer.addEventListener("scroll", this.toggleToolbar.bind(this));
viewer.addEventListener("dblclick", this.toggleSmartZoom.bind(this));
document.addEventListener("keydown", this.handleShortcut.bind(this));
this.recreateOpenFile(printButton, "print").addEventListener("click", e => {
secondaryOpen.dispatchEvent(new Event("click"));
});
const app = window.PDFViewerApplication;
getViewerEventBus(app).then(eventBus => {
/* Set base URL of PDF's links (bookmarks) to the original URL */
eventBus.on("documentinit", () => {
app.pdfLinkService.baseUrl = app.baseUrl;
});
const options = JSON.parse(localStorage.getItem("doqment.options"));
if (options?.showPdfTitle === false) {
eventBus.on("metadataloaded", () => app.setTitleUsingUrl(app.url));
}
eventBus.on("documenterror", this.handleError.bind(this));
eventBus.on("resize", this.resetZoomStatus.bind(this));
eventBus.on("scalechanging", this.resetZoomStatus.bind(this));
});
},

recreateOpenFile(toolbarButton, name) {
const openButton = toolbarButton.cloneNode(true);
openButton.id = "openFile";
toolbarButton.before(openButton);
openButton.outerHTML = openButton.outerHTML.replaceAll(name, "open-file");
return toolbarButton.previousElementSibling;
},

toggleToolbar() {
const smallDevice = window.matchMedia("(max-height: 384px)");
if (!this.options.autoToolbar || !smallDevice.matches) {
Expand Down Expand Up @@ -93,6 +110,7 @@ const Doqment = {
window.alert(details.message);
app.loadingBar?.hide();
app.close();
chrome.runtime.sendMessage({ action: "removeViewer" });
},

/* Smart zoom */
Expand Down
17 changes: 10 additions & 7 deletions src/scripts/mv2/background.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Intercept loading of PDF files and redirect them to the add-on
* Adapted from => [pdf.js]/extensions/chromium/pdfHandler.js
*/
import { getViewerURL } from "../utils.js";
import { getViewerURL, execOnEvent } from "../utils.js";

const pdfSources = {
urls: ["<all_urls>"],
Expand All @@ -11,13 +11,13 @@ const pdfSources = {
const options = ["blocking", "responseHeaders"];
const localPdf = {
url: [
{urlPrefix: "file://", pathSuffix: ".pdf"},
{urlPrefix: "file://", pathSuffix: ".PDF"}
{ urlPrefix: "file://", pathSuffix: ".pdf" },
{ urlPrefix: "file://", pathSuffix: ".PDF" }
]
};
browser.webRequest.onHeadersReceived.addListener(redirect, pdfSources, options);
browser.webNavigation.onBeforeNavigate.addListener(loadViewer, localPdf);
browser.browserAction.onClicked.addListener(newViewer);
browser.webNavigation.onBeforeNavigate.addListener(showMessage, localPdf);

/* Event handlers */
const baseUrl = browser.runtime.getURL("pdfjs/web/viewer.html");
Expand All @@ -28,9 +28,12 @@ function redirect(details) {
if (isPdfResp(details) && !shouldDownload(details))
return { redirectUrl: getViewerURL(baseUrl, details.url) };
}
function loadViewer(details) {
if (!details.frameId)
browser.tabs.update(details.tabId, { url: messageUrl });
function showMessage(details) {
if (!details.frameId) {
const messageTab = { openerTabId: details.tabId, url: messageUrl };
execOnEvent("open-local-pdf", [() => browser.tabs.create(messageTab)]);
browser.webNavigation.onBeforeNavigate.removeListener(showMessage);
}
}
function newViewer(_, clickData) {
const btn = clickData?.button;
Expand Down
14 changes: 9 additions & 5 deletions src/scripts/mv2/page-script.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,15 @@ async function disableAnnotEditors() {
}
}

/* Disable hardware accelerated rendering of canvas */
function forceSoftwareRender() {
const doqOptions = { softwareRender: true };
localStorage.setItem("doq.options", JSON.stringify(doqOptions));
/* Remove obsolete softwareRender doq option */
function removeSoftwareRender() {
const doqOptions = JSON.parse(localStorage.getItem("doq.options"));
if (doqOptions) {
delete doqOptions["softwareRender"];
localStorage.setItem("doq.options", JSON.stringify(doqOptions));
}
localStorage.removeItem("doqment.update-0.9");
}

execOnEvent("init", [selectFirefox, disableAnnotEditors])
execOnEvent("update-0.9", [forceSoftwareRender])
execOnEvent("update-1.0", [removeSoftwareRender])
9 changes: 9 additions & 0 deletions src/scripts/mv3/page-script.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,12 @@ async function activateAndPrompt(message, reply) {
await chrome.tabs.update(tab.id, { active: true });
reply([{ result: window.confirm(message) }]);
}

if (window.name === "doqmentViewer") {
const updateTitle = () => {
const request = { action: "updateTitle", body: document.title };
chrome.runtime.sendMessage(request);
};
const title = document.querySelector("title");
new MutationObserver(updateTitle).observe(title, { childList: true });
}
53 changes: 35 additions & 18 deletions src/scripts/mv3/service-worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,13 @@ function createMenus() {
const createMenu = (id, title, contexts, extras) => {
chrome.contextMenus.create({ id, title, contexts, ...extras });
};
const createOption = (...args) => createMenu(...args, { type: "checkbox" });
const createOption = (id, title, extras) => {
createMenu(id, title, ["action"], { type: "checkbox", ...extras });
};

createMenu("open-link", getMenuTitle(false), ["link", "frame"]);
createOption("allow-all", "Always allow access to sites", ["action"]);
createOption("make-default", "Make doqment the default viewer", ["action"]);
createOption("allow-all", "Always allow access to sites");
createOption("make-default", "Make doqment the default viewer");
}

async function handleClick(info, tab) {
Expand All @@ -55,20 +57,25 @@ async function handleClick(info, tab) {
/* if doqment is the default, open in the built-in viewer instead */
async function openLink(url, openerTabId) {
const permit = { origins: [url] };
let viewerUrl;
if (!url.startsWith(baseUrl) && await chrome.permissions.request(permit)) {
viewerUrl = getViewerURL(baseUrl, url);
const allowed = await chrome.permissions.request(permit).catch(r => {});
if (allowed === false) {
return;
}
const isViewerUrl = url.startsWith(baseUrl);
const scripts = await chrome.scripting.getRegisteredContentScripts();
/* We cannot check this earlier because `permissions.request()`
* has to be called immediately after user action where needed */
if (scripts.length > 0) {
if (isViewerUrl) {
url = new URL(url).searchParams.get("file");
}
url = new URL(url);
url.searchParams.set("doqment", "ignore");
chrome.tabs.create({ url: url.toString(), openerTabId });
} else if (viewerUrl) {
} else {
const newTab = await chrome.tabs.create({ url, openerTabId });
loadViewer(viewerUrl, newTab.id);
if (allowed)
loadViewer(getViewerURL(baseUrl, url), newTab.id);
}
}

Expand Down Expand Up @@ -106,13 +113,21 @@ function toggleAutoOpen(enable, menuId) {
}

function respond(request, sender, sendResponse) {
const tabId = sender.tab.id;
if (request.action === "loadViewer") {
const viewerUrl = getViewerURL(baseUrl, request.body);
if (sender.frameId === 0) {
loadViewer(viewerUrl, sender.tab.id);
loadViewer(viewerUrl, tabId);
} else {
sendResponse({ url: viewerUrl });
}
} else if (request.action === "removeViewer") {
const func = () => document.getElementById("doqmentViewer").remove();
chrome.scripting.executeScript({ target: {tabId}, func });
} else if (request.action === "updateTitle") {
const func = title => document.title = title;
const title = request.body;
chrome.scripting.executeScript({ target: { tabId }, func, args: [title] });
}
}

Expand Down Expand Up @@ -179,32 +194,34 @@ async function newViewer(tab) {
return chrome.extension.isAllowedFileSchemeAccess();
};
const url = tab.url;
let viewerUrl;
let viewerUrl = splashUrl;
if (new URL(url).protocol === "file:" && !await hasFilesAccess()) {
viewerUrl = messageUrl;
} else if (await isPdfTab(tab.id)) {
viewerUrl = getViewerURL(baseUrl, url);
}

if (viewerUrl) {
loadViewer(viewerUrl, tab.id);
} else {
chrome.tabs.create({ url: splashUrl, index: tab.index + 1 });
loadViewer(getViewerURL(baseUrl, url), tab.id);
return;
}
chrome.tabs.create({ url: viewerUrl, index: tab.index + 1 });
}

/* Load viewer in a full page frame in the given tab */
function loadViewer(viewerUrl, tabId) {
const injectFrame = src => {
const frame = document.createElement("iframe");
frame.src = src;
frame.id = "doqmentViewer";
frame.name = frame.id = "doqmentViewer";
frame.setAttribute("allow", "fullscreen");
document.body.prepend(frame);
};
const removeEmbed = () => {
document.querySelector("embed[type='application/pdf']")?.remove();
};
chrome.scripting.executeScript({
target: {tabId}, func: injectFrame, args: [viewerUrl]
}).then(() => {
chrome.scripting.insertCSS({ target: {tabId}, files: [viewerCSS] });
}).then(() => {
chrome.scripting.executeScript({ target: {tabId}, func: removeEmbed });
});
}

Expand Down
50 changes: 34 additions & 16 deletions src/scripts/options.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,31 @@
import { hasCoarsePointer } from "./utils.js";

const DoqPrefs = {
defaults: {},
store: {},
stash: {},
class Preferences {
#defaults = {};
#storeKey = "";

constructor(storeKey) {
this.#storeKey = storeKey;
this.store = {};
this.stash = {};
}
init(properties) {
for (let key in properties) {
this.defaults[key] = properties[key].default;
this.#defaults[key] = properties[key].default;
}
Object.freeze(this.defaults);
this.store = JSON.parse(localStorage.getItem("doq.options")) ?? this.store;
},
Object.freeze(this.#defaults);
this.store = JSON.parse(localStorage.getItem(this.#storeKey)) ?? this.store;
}
get(key) {
return this.store[key] ?? this.defaults[key];
},
return this.store[key] ?? this.#defaults[key];
}
set(key, value) {
this.store[key] = value;
localStorage.setItem("doq.options", JSON.stringify(this.store));
},
localStorage.setItem(this.#storeKey, JSON.stringify(this.store));
}
reset() {
this.store = (browser === chrome) ? {} : { softwareRender: true };
localStorage.setItem("doq.options", JSON.stringify(this.store));
this.store = {};
localStorage.setItem(this.#storeKey, JSON.stringify(this.store));
}
}

Expand Down Expand Up @@ -61,22 +66,34 @@ browser.runtime.getPlatformInfo().then(info => {
document.body.classList.add(info.os);
});

const extOptions = document.getElementById("extOptions");
const doqOptions = document.getElementById("doqOptions");
const pdfjsOptions = document.getElementById("pdfjsOptions");
const moreOptions = document.getElementById("moreOptions").content;
const resetOptions = document.getElementById("resetOptions");
const undoReset = document.getElementById("undoReset");

const ExtPrefs = new Preferences("doqment.options");
const DoqPrefs = new Preferences("doq.options");
extOptions.addEventListener("change", e => updatePrefs(ExtPrefs, e.target));
doqOptions.addEventListener("change", e => updatePrefs(DoqPrefs, e.target));
pdfjsOptions.addEventListener("change", e => updatePrefs(PdfjsPrefs, e.target));

moreOptions.querySelector("legend").addEventListener("change", toggleMore);
doqOptions.addEventListener("change", toggleUndo);
pdfjsOptions.addEventListener("change", toggleUndo);
[extOptions, doqOptions, pdfjsOptions].forEach(options => {
options.addEventListener("change", toggleUndo);
});
resetOptions.onclick = undoReset.onclick = restorePrefs;

const extSchema = browser.runtime.getURL("options.json");
const doqSchema = browser.runtime.getURL("doq/addon/options.json");
const pdfjsSchema = browser.runtime.getURL("pdfjs/preferences_schema.json");

fetch(extSchema).then(resp => resp.json()).then(schema => {
ExtPrefs.init(schema.properties);
render(ExtPrefs, schema, extOptions);
});

fetch(doqSchema).then(resp => resp.json()).then(schema => {
DoqPrefs.init(schema.properties);
render(DoqPrefs, schema, doqOptions);
Expand Down Expand Up @@ -224,6 +241,7 @@ async function restorePrefs() {
updateControl(prefs, document.getElementById(key));
}
};
await restore(ExtPrefs);
await restore(DoqPrefs);
await restore(PdfjsPrefs);
toggleUndo(reset);
Expand Down
2 changes: 1 addition & 1 deletion src/scripts/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,4 @@ export function isTouchScreen() {
return nonHoverable.matches && hasCoarsePointer();
}

export { getViewerEventBus } from "../doq/addon/lib/utils.js";
export { getViewerEventBus } from "../doq/addon/app/utils.js";