Есть ли эквивалент FF для chrome.declarativeContent.onPageChanged?

Я переношу расширение Chrome в Firefox WebExtensions и не могу найти обходной путь для chrome.declarativeContent.onPageChanged.

My FF Webextension содержит действие страницы, которое должно отображаться при навигации по определенным веб-сайтам. Однако ни один из слушателей в доступном API, похоже, не позволяет этого.

В частности, я пробовал:

chrome.runtime.onInstalled.addListener(onChange);
chrome.tabs.onCreated.addListener(onChange);
chrome.tabs.onActivated.addListener(onChange);
chrome.tabs.onUpdated.addListener(onChange);
chrome.webNavigation.onDOMContentLoaded(onChange);
chrome.webNavigation.onCreatedNavigationTarget(onChange);

Существуют ли какие-либо известные обходные пути?


person ktouchie    schedule 31.08.2016    source источник


Ответы (3)


Вам придется показать pageAction вручную, потому что API declarativeContent еще не поддерживается.

chrome.pageAction.show(tabId);
chrome.pageAction.hide(tabId);

В случае, если правила основаны на сопоставлении URL-адресов, реализация довольно проста:

chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
    if (changeInfo.status === 'complete' && tab.url.match(/something/)) {
        chrome.pageAction.show(tabId);
    } else {
        chrome.pageAction.hide(tabId);
    }
});

Однако, если он основан на элементах DOM, вам придется использовать скрипт содержимого:

chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
    if (changeInfo.status === 'complete' && tab.url.match(/something/)) {
        chrome.tabs.executeScript(tabId, {
            code: 'document.querySelector(' + JSON.stringify(someSelector) + ')'
        }, function(results) {
            if (results[0]) {
                chrome.pageAction.show(tabId);
            } else {
                chrome.pageAction.hide(tabId);
            }
        });
    } else {
        chrome.pageAction.hide(tabId);
    }
});

Это очень упрощенный код. Его можно улучшить, чтобы искать элементы во время загрузки страницы.

person wOxxOm    schedule 31.08.2016
comment
В случае подхода, основанного на контент-скрипте, слушатель onUpdated может даже не понадобиться. - person Xan; 31.08.2016
comment
chrome.tabs.onUpdated.addListener работает при переходе на разные сайты, но не при первом открытии вкладки. Опубликую мой обходной путь ниже! - person ktouchie; 31.08.2016
comment
К вашему сведению: ваш код будет внедрять и выполнять сценарий содержимого несколько раз на большинстве страниц. Событие tabs.onUpdated часто запускается несколько раз при загрузке страницы с помощью tab.status === 'complete' (ошибка IMO). Возможно: ищите changeInfo.url && changeInfo.status==='complete'. Для более подробного ознакомления с доступными событиями см. changeInfo.status tabs.onUpdated.addListener изменяется с undefined на Complete без перехода к загрузке. Код в этом ответе может помочь изучить доступные события и определить, какие критерии подходят для данной ситуации. - person Makyen♦; 31.08.2016
comment
Правильный. Но иногда нет ничего плохого в многократном выполнении, если действие страницы должно быть скрыто после исчезновения элемента со страницы. Хотя в этом случае обратный вызов MutationObserver или setInterval кажется лучшим выбором. На самом деле, я изначально хотел использовать changeInfo.status, так что спасибо, ответ обновлен. - person wOxxOm; 31.08.2016
comment
Для простого случая (выполнение и завершение) кода здесь многократное выполнение в порядке. Люди сталкиваются с проблемами, когда они многократно вводят что-то, что не полностью завершается. Да, для селекторов CSS в chrome.declarativeContent на самом деле не существует эффективного решения, кроме внедрения постоянного скрипта контента на каждую страницу, соответствующую URL-адресу (проще? с manifest.json "content_scripts"), который использует MutationObserver или setTimeout, а затем отправляет сообщение фоновому сценарию при совпадении. chrome.declarativeContent, в конце концов, специально предназначен для этого. - person Makyen♦; 31.08.2016
comment
Я бы рекомендовал не проверять changeInfo.url. Я только что видел, что по крайней мере в Chrome это не устанавливается во время события 'complete'. Вместо этого, вероятно, имеет смысл проверить наличие tab.url. - person AndyO; 11.08.2018

Для простого сопоставления URL-адресов и для новых вкладок, а также для изменений в существующей вкладке это работает:

  • включить разрешение tabs в манифест.

.

chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
  if (changeInfo.status === 'complete' && tab.url.match(/something/)) {
    chrome.pageAction.show(tabId);
  } else if (changeInfo.status === 'complete') {
    chrome.pageAction.hide(tabId);
  }
});
chrome.tabs.onCreated.addListener(function(tab) {
  if (tab.url && tab.url.match(/something/)) {
    chrome.pageAction.show(tab.id);
  } else if (tab.url) {
    chrome.pageAction.hide(tab.id);
  }
});
person Rob Hawkins    schedule 01.08.2019

Лучший эквивалент на данный момент выглядит следующим образом:

var target = "<all_urls>";
chrome.webRequest.onCompleted.addListener(onChange, {urls: [target]});

(onChange() включает сопоставление текущего URL с регулярным выражением, а затем chrome.pageAction.show(tabInfo.id);)

person ktouchie    schedule 31.08.2016
comment
Он будет срабатывать для всех типов веб-запросов, включая изображения, сценарии и стили. Используйте фильтрацию, чтобы ограничить его только основным кадром: chrome.webRequest.onCompleted.addListener(onChange, {urls: [target], types: ['main_frame']}); - person wOxxOm; 31.08.2016