Chrome расширений CORB: как реагировать на обновления в общем DOM - PullRequest
6 голосов
/ 19 января 2020

Попытка создать скрипт содержимого с расширением chrome, который добавляет дополнительную полезную навигацию на страницу проблемы GitHub. Когда взаимодействие осуществляется через обычную веб-страницу (конечный пользователь щелкает по смайлику реакции) - мой введенный элемент теряется.

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

Должен быть более элегантный способ, чем этот, который позволяет реагировать на изменения DOM, чтобы я мог затем удалить и повторно ввести элемент (вместо того, чтобы стучать в дверь время)?

Расширение, которое я пытаюсь оптимизировать, можно найти здесь

https://github.com/NorfeldtAbtion/github-issue-reactions-chrome-extension

Важные файлы в настоящее время выглядят так

addReactionsNav. js

const URL =
  window.location.origin + window.location.pathname + window.location.search
const header = document.querySelector('#partial-discussion-sidebar')
header.style = `position: relative;height: 100%;`
let wrapper = getWrapper()

// // The isolated world made it difficult to detect DOM changes in the shared DOM
// // So this monkey-hack to make it refresh when ..
// setInterval(() => {
//   wrapper.remove()
//   wrapper = getWrapper()
//   addReactionNav()
// }, 1000)

// Select the node that will be observed for mutations
const targetNode = document.querySelector('body')

// Options for the observer (which mutations to observe)
const config = { attributes: true, childList: true, subtree: true }

// Create an observer instance linked to the callback function
const observer = new MutationObserver(() => addReactionNav())

// Start observing the target node for configured mutations
observer.observe(targetNode, config)

function getWrapper() {
  const header = document.querySelector('#partial-discussion-sidebar')
  const wrapper = header.appendChild(document.createElement('div'))
  wrapper.style = `
      position:sticky;
      position: -webkit-sticky;
      top:10px;`
  return wrapper
}

function addReactionNav() {
  const title = document.createElement('div')
  title.style = `font-weight: bold`
  title.appendChild(document.createTextNode('Reactions'))
  wrapper.appendChild(title)

  // Grabbing all reactions Reactions �� �� �� �� ❤️ �� �� ��
  const reactionsNodes = document.querySelectorAll(`
    [alias="+1"].mr-1,
    [alias="rocket"].mr-1,
    [alias="tada"].mr-1,
    [alias="heart"].mr-1,
    [alias="smile"].mr-1,
    [alias="thinking_face"].mr-1,
    [alias="-1"].mr-1,
    [alias="eyes"].mr-1
  `)

  const reactionsNodesParents = [
    ...new Set(
      Array.from(reactionsNodes).map(node => node.parentElement.parentElement)
    ),
  ]

  reactionsNodesParents.forEach(node => {
    const a = document.createElement('a')
    const linkText = document.createTextNode('\n' + node.innerText)
    a.appendChild(linkText)
    a.title = node.innerText

    let id = null
    while (id == null || node != null) {
      if (node.tagName === 'A' && node.name) {
        id = node.name
        break
      }

      if (node.id) {
        id = node.id
        break
      }

      node = node.parentNode
    }
    const postURL = URL + '#' + id
    a.href = postURL
    a.style = `display:block;`

    wrapper.appendChild(a)
  })
}

манифест. json

{
  "manifest_version": 2,
  "name": "Github Issue Reactions",
  "version": "1.0",
  "description": "List a link of reactions on a github issue page",
  "permissions": ["https://www.github.com/", "http://www.github.com/"],
  "content_scripts": [
    {
      "matches": ["*://*.github.com/*/issues/*"],
      "js": ["addReactionsNav.js"],
      "run_at": "document_end"
    }
  ]
}

Найдено это краткое упоминание об «изолированных мирах»

https://youtu.be/laLudeUmXHM?t=79

Обновление

Теперь я считаю, что «ошибка» связана с CORB - что является мерой безопасности от Spectre.

Блокировка чтения из разных источников ( CORB) заблокированный перекрестный ответ https://api.github.com/_private/browser/stats с приложением MIME-типа / json. См. https://www.chromestatus.com/feature/5629709824032768 для получения более подробной информации.

Google расскажет об этом подробнее в своем выступлении Уроки «Призрака и распада» и о том, как вся сеть становится безопаснее (Google I / O '18)

Пример, упомянутый в 34: 00 , кажется, был заблокирован CORB с тех пор.

Ответы [ 2 ]

1 голос
/ 28 января 2020

Поскольку GitHub заменяет весь узел #partial-discussion-sidebar, когда «конечный пользователь нажимает emoji реакции» в первом сообщении, вам нужно снова getWrapper() перед addReactionNav() в ответе наблюдателя мутации, как показано ниже.

Обновление: поскольку узел #partial-discussion-sidebar не перерисовывается в случае обновления реакции на сообщения, отличные от первого, нам также необходимо ответить на обновление элементов временной шкалы.

const URL = window.location.origin + window.location.pathname + window.location.search;
const header = document.querySelector('#partial-discussion-sidebar');
header.style = `position: relative;height: 100%;`;
let wrapper = getWrapper();
addReactionNav();    // Initial display.

// Select the node that will be observed for mutations.
const targetNode = document.querySelector('body');

// Options for the observer (which mutations to observe).
const config = {
  childList: true,
  subtree: true
};

// Create an observer instance linked to the callback function.
const observer = new MutationObserver(mutations => {
  if (!targetNode.contains(wrapper) || mutations.some(mutation => mutation.target.matches('.js-timeline-item'))) {
    wrapper.remove();
    wrapper = getWrapper();
    addReactionNav();
  }
});

// Start observing the target node for configured mutations.
observer.observe(targetNode, config);
0 голосов
/ 19 января 2020

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

Фон. js

chrome.tabs.onUpdated.addListener(tabId, changeInfo, tab) => {
  if (changeInfo.url) {
    chrome.tabs.sendMessage(tabId, {
      message: actions.TAB_UPDATED
    });
  }
})

Контент. js

chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
  if (request.message === actions.TAB_UPDATED) {
    // show buttons
  }
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...