Хотя вы можете напрямую получить доступ к DOM страницы вашего собственного расширения, открытой в новой вкладке, с помощью chrome.extension.getViews, но для этого необходимо открыть вкладку в фоновом режиме (active:false
в параметрах chrome.tabs.create), чтоненадежен, потому что другое расширение может принудительно активировать вкладку, закрывая, таким образом, ваше всплывающее окно, которое немедленно прервет ваш скрипт всплывающего окна.
Правильный подход - передать данные на другую страницу и обработать данные внутри загруженного скрипта.на этой странице HTML через стандартный <script src="other-page.js"></script>
.
1.Совместное использование через HTML5 localStorage + синхронный доступ
Используйте, если вам необходимо получить доступ к данным во время загрузки на другой странице перед первым нарисованным кадром, например, для выбора светлой / темной темы.Вам придется JSON'ить нестандартные типы, такие как объекты или массивы.
Недостаток: может быть медленным, если вы наблюдаете событие DOM 'storage'
на других страницах вашего расширения.
popup.js:
localStorage.sharedData = JSON.stringify({foo: 123, bar: [1, 2, 3], theme: 'dark'});
chrome.tabs.create({url: 'other-page.html'});
other-page.js:
let sharedData;
try {
sharedData = JSON.parse(localStorage.sharedData);
if (sharedData.theme === 'dark') {
document.documentElement.style = 'background: #000; color: #aaa;';
}
} catch (e) {}
delete localStorage.sharedData;
2.Обмен через параметры URL + синхронный доступ
Используйте, если вам нужен доступ к данным во время загрузки на другой странице перед первым окрашенным кадром, например, для выбора светлой / темной темы.Вам придется JSON'ить нестандартные типы, такие как объекты или массивы.
Недостаток: длинный адрес в адресной строке.
popup.js:
chrome.tabs.create({
url: 'other-page.html?data=' + encodeURIComponent(JSON.stringify({foo: [1, 2, 3]})),
});
other-page.js:
let sharedData;
try {
sharedData = JSON.parse(new URLSearchParams(location.search).get('data'));
} catch (e) {}
// simplify the displayed URL in the address bar
history.replace({}, document.title, location.origin + location.pathname);
3.Совместное использование через фоновую страницу глобальной переменной + синхронный доступ
Используйте, если вам нужно получить доступ к данным во время загрузки на другой странице перед первым нарисованным кадром, например, чтобы выбрать светлую / темную тему.Вам придется JSON'ить нестроковые типы, такие как объекты или массивы.
Недостаток 1: необходимость в фоновой странице.
Недостаток 2: необходимость глубокого клонированияобъекты с использованием JSON'ification или пользовательского deepClone, который работает должным образом для кросс-оконных контекстов (AFAIK, ни один из популярных deepClone не реализует это условие), в частности, он должен использовать ссылку целевого окна на конструктор объекта.
manifest.json:
"background": {
"scripts": ["bg.js"],
"persistent": false
}
popup.js:
// ensure the non-persistent background page is loaded
chrome.runtime.getBackgroundPage(bg => {
// using JSON'ification to avoid dead cross-window references.
bg.sharedData = JSON.stringify({foo: 123, bar: [1, 2, 3], theme: 'dark'});
chrome.tabs.create({url: 'other-page.html'});
});
other-page.js:
// if this tab was reloaded the background page may be unloaded and the variable is lost
// but we were saving a copy in HTML5 sessionStorage!
let sharedData = sessionStorage.sharedData;
if (!sharedData) {
const bg = chrome.extension.getBackgroundPage();
sharedData = bg && bg.sharedData;
if (sharedData) {
sessionStorage.sharedData = sharedData;
}
}
// using JSON'ification to avoid dead cross-window references.
try {
sharedData = JSON.parse(sharedData);
} catch (e) {}
4.Поделиться через фоновую страницу сообщениями в два прыжка
Используйте, если вам нужно выполнить последовательность действий на фоновой странице, открытие вкладки - это только первый шаг.Например, нам нужно передать данные на втором шаге.
Фоновая страница необходима, потому что всплывающее окно будет закрыто, и его сценарии больше не будут работать, когда активная вкладка откроется в том же окне, где всплывающее окноотображается.Можно подумать, что создание вкладки с active: false
решит проблему, но только до тех пор, пока пользователь не решит установить другое расширение, которое отменяет поведение при открытии вкладки.Вы могли бы подумать, что можете открыть новое окно, но опять же нет никакой гарантии, что какое-то другое расширение не присоединит вкладку нового окна к существующему окну, закрывая таким образом ваше всплывающее окно.
Недостаток 1: в Chrome данныеJSON'ified внутренне, поэтому он уничтожает все нестандартные типы, такие как WeakMap, TypedArray, Blob и т. Д. В Firefox они, похоже, используют структурированное клонирование, поэтому можно использовать больше типов.
Недостаток 2: мы отправляемодно и то же сообщение с данными дважды.
Примечание: я использую Мозилла WebExtension polyfill .
manifest.json:
"background": {
"scripts": [
"browser-polyfill.min.js",
"bg.js"
],
"persistent": false
}
popup.js:
chrome.runtime.sendMessage({
action: 'openTab',
url: '/other-page.html',
data: {foo: 123, bar: [1, 2, 3], theme: 'dark'},
});
bg.js:
function onTabLoaded(tabId) {
return new Promise(resolve => {
browser.tabs.onUpdated.addListener(function onUpdated(id, change) {
if (id === tabId && change.status === 'complete') {
browser.tabs.onUpdated.removeListener(onUpdated);
resolve();
}
});
});
}
browser.runtime.onMessage.addListener(async (msg = {}, sender) => {
if (msg.action === 'openTab') {
const tab = await browser.tabs.create({url: msg.url});
await onTabLoaded(tab.id);
await browser.tabs.sendMessage(tab.id, {
action: 'setData',
data: msg.data,
});
}
});
other-page.html:
<!doctype html>
<p id="text"></p>
<!-- scripts at the end of the page run when DOM is ready -->
<script src="other-page.js"></script>
other-page.js:
chrome.runtime.onMessage.addListener((msg, sender) => {
if (msg.action === 'setData') {
console.log(msg.data);
document.getElementById('text').textContent = JSON.stringify(msg.data, null, ' ');
// you can use msg.data only inside this callback
// and you can save it in a global variable to use in the code
// that's guaranteed to run at a later point in time
}
});
5.Поделиться через chrome.storage.local
См. Пример для chrome.storage.local в этот ответ .