#javascript #google-chrome #pdf #google-chrome-extension
Вопрос:
Я создаю расширение chrome, которое изменяет заголовок какой-либо страницы pdf, например https://arxiv.org/pdf/2005.01463v2.pdf.
Код отлично работает до загрузки pdf, но когда pdf загружен полностью, заголовок окна возвращается к имени pdf (вместо моего заголовка), и использование document.title = "cool title"
сообщений или Chrome на background.js
не работает.
Однако выполнение руководства document.title = "cool title"
с консоли на данной странице pdf хорошо работает.
// content_script.js
const makeTitle = (time) => {
setTimeout(() => {
title = "cool title"
console.log("Updating pdf title");
chrome.runtime.sendMessage({ type: "update-title", options: { title } })
window.document.title = title;
}, time)
}
makeTitle(0)
makeTitle(1 * 1000);
makeTitle(5 * 1000);
makeTitle(10 * 1000);
makeTitle(20 * 1000);
makeTitle(60 * 1000);
makeTitle(5 * 60 * 1000);
// background.js
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
console.log("Executing background message")
if (request.type == "update-title") {
const { title } = request.options;
chrome.tabs.executeScript(sender.tab.id, { code: `document.title = "${title}"` });
}
});
Я должен использовать их, setTimeout
потому что не могу определить, загружен ли файл PDF. makeTitle
отлично работает до загрузки PDF-файла, но не после, и я хотел бы решить эту проблему. Спасибо!
PS: Я знаю, что есть дубликат изменения названия, просто ни одна из этих 2 стратегий не работает
Комментарии:
1. Используйте chrome.tabs.onUpdated в фоновом режиме. js и когда changeInfo содержит новое
title
, вызовите executeScript. В качестве альтернативы, используйте MutationObserver в сценарии содержимого, чтобы отслеживать изменения в документе. Элемент querySelector(«заголовок»).2. Я попробую, но есть ли у вас какие-либо идеи, почему установка заголовка не работает в том, что я пробовал?
3. Потому что программа просмотра pdf устанавливает его, конечно, после загрузки документа.
4. Дело не в этом, если вы внимательно прочтете мой вопрос, вы увидите, что после загрузки документа есть задатчики заголовков, и в этом весь смысл вопроса 🙂 (setTimeout)
5. Я намеревался сделать только одно замечание, потому что это тривиальная проблема, и решение также тривиально. Вы уже пробовали это сделать?
Ответ №1:
Это ошибка в Chrome. Он задает заголовок внутри и игнорирует title
элемент DOM.
Обходной путь состоит в том, чтобы использовать chrome.tabs.onUpdated для установки пустого заголовка, а затем установить нужный.
background.js
const title = 'foo';
chrome.tabs.onUpdated.addListener((tabId, info, tab) => {
if (info.title amp;amp; info.title !== title amp;amp; tab.url.endsWith('.pdf')) {
chrome.tabs.executeScript(tabId, {
code: `document.title=''; document.title="${title}"`,
runAt: 'document_start',
// runs immediately if this change occurs before DOMContentLoaded
});
}
});
В Chrome есть еще одна ошибка: он периодически отображает встроенный заголовок при переключении на другую вкладку и обратно. Эта конкретная ошибка, похоже, исправлена в предстоящем «несезонном» просмотрщике PDF, который в настоящее время можно включить с помощью chrome://flags/#pdf-unseasoned
Комментарии:
1. Это помогло мне решить проблему сеттера. Так что это было нетривиально 😉 Большое спасибо за ваше расследование
2. Просто для ясности, это вызовет бесконечный цикл обновления, нет? конечно, то, что находится внутри, если не сработает более одного раза, но все равно будет вызван прослушиватель событий (на самом деле дважды из-за 2-х сеттеров
code
). Может ли это, по вашему мнению, вызвать проблемы с производительностью?3. Прослушиватель будет работать до тех пор, пока вы не отмените его регистрацию, так что он действительно бесконечен. Чтобы предотвратить саморекурсию, есть проверка
info.title !== title
. Поскольку это тривиальная операция, я не вижу никаких проблем с производительностью, но если вы обеспокоены, вы можете использовать chrome://трассировка или другие инструменты низкого уровня производительности.4. В случае, если вы имели в виду такой цикл, как
while(true){}
тогда, я не наблюдал такого поведения в своих тестах.5. Нет, я имел в виду бесконечный цикл событий -> название обновления ->> событие и т. Д.