В принципе мы можем создать объект весеннего контейнера двумя способами
оба являются интерфейсами
с использованием классов реализации мы можем создать объект для весеннего контейнера
, приходя к различиям
BeanFactory
ex: BeanFactory context = new XmlBeanFactory (новый ресурс ("applicationContext.xml"));
ApplicationContext
ex: ApplicationContext context = new ClasspathXmlApplicationContext ("applicationContext.xml");
Если вам действительно нужно, вы можете вставить элемент <script>
в DOM страницы; код внутри вашего элемента <script>
будет выполнен, и этот код будет иметь доступ к переменным JavaScript в области видимости окна. Затем вы можете передать их обратно в скрипт контента, используя атрибуты data-
и вызывая пользовательские события.
Звучит неловко? Почему да, и намеренно по всем причинам в документации, которую цитировал serg. Но если вам действительно нужно это сделать, это можно сделать. См. здесь и здесь для получения дополнительной информации. И удачи!
Я создал небольшой вспомогательный метод, получайте удовольствие:)
для извлечения переменных окна «lannister», «always», «pays», «his», «долгов» , вы выполняете следующее:
var windowVariables = retrieveWindowVariables(["lannister", "always", "pays", "his", "debts"]);
console.log(windowVariables.lannister);
console.log(windowVariables.always);
мой код:
function retrieveWindowVariables(variables) {
var ret = {};
var scriptContent = "";
for (var i = 0; i < variables.length; i++) {
var currVariable = variables[i];
scriptContent += "if (typeof " + currVariable + " !== 'undefined') $('body').attr('tmp_" + currVariable + "', " + currVariable + ");\n"
}
var script = document.createElement('script');
script.id = 'tmpScript';
script.appendChild(document.createTextNode(scriptContent));
(document.body || document.head || document.documentElement).appendChild(script);
for (var i = 0; i < variables.length; i++) {
var currVariable = variables[i];
ret[currVariable] = $("body").attr("tmp_" + currVariable);
$("body").removeAttr("tmp_" + currVariable);
}
$("#tmpScript").remove();
return ret;
}
обратите внимание, что я использовал jQuery .. вы можете легко использовать нативный js «removeAttribute» и вместо «removeChild» .
Используя решение Лиран, я добавляю исправление для Objects
, вот правильное решение:
function retrieveWindowVariables(variables) {
var ret = {};
var scriptContent = "";
for (var i = 0; i < variables.length; i++) {
var currVariable = variables[i];
scriptContent += "if (typeof " + currVariable + " !== 'undefined') $('body').attr('tmp_" + currVariable + "', JSON.stringify(" + currVariable + "));\n"
}
var script = document.createElement('script');
script.id = 'tmpScript';
script.appendChild(document.createTextNode(scriptContent));
(document.body || document.head || document.documentElement).appendChild(script);
for (var i = 0; i < variables.length; i++) {
var currVariable = variables[i];
ret[currVariable] = $.parseJSON($("body").attr("tmp_" + currVariable));
$("body").removeAttr("tmp_" + currVariable);
}
$("#tmpScript").remove();
return ret;
}
Документация Chrome дает вам хорошую отправную точку: https://developer.chrome.com/extensions/content_scripts#host-page-communication
Этот метод позволяет вам извлечь Глобальная переменная страницы в вашем скрипте контента. Он также использует идею, чтобы принимать только входящие сообщения, которые вы узнаете, учитывая ваше рукопожатие. Вы также можете просто использовать Math.random()
для рукопожатия, но мне было весело.
propagateVariable
и передает текущее handShake и имя целевой переменной в строку для сохранения, так как функция будет не имеют доступа к нашей области содержимого скрипта.
const globalToExtract = 'someVariableName';
const array = new Uint32Array(5);
const handShake = window.crypto.getRandomValues(array).toString();
function propagateVariable(handShake, variableName) {
const message = { handShake };
message[variableName] = window[variableName];
window.postMessage(message, "*");
}
(function injectPropagator() {
const script = `( ${propagateVariable.toString()} )('${handShake}', '${globalToExtract}');`
const scriptTag = document.createElement('script');
const scriptBody = document.createTextNode(script);
scriptTag.id = 'chromeExtensionDataPropagator';
scriptTag.appendChild(scriptBody);
document.body.append(scriptTag);
})();
window.addEventListener("message", function({data}) {
console.log("INCOMINGGGG!", data);
// We only accept messages from ourselves
if (data.handShake != handShake) return;
console.log("Content script received: ", data);
}, false);
function extractGlobal(variableName) {
const array = new Uint32Array(5);
const handShake = window.crypto.getRandomValues(array).toString();
function propagateVariable(handShake, variableName) {
const message = { handShake };
message[variableName] = window[variableName];
window.postMessage(message, "*");
}
(function injectPropagator() {
const script = `( ${propagateVariable.toString()} )('${handShake}', '${variableName}');`
const scriptTag = document.createElement('script');
const scriptBody = document.createTextNode(script);
scriptTag.id = 'chromeExtensionDataPropagator';
scriptTag.appendChild(scriptBody);
document.body.append(scriptTag);
})();
return new Promise(resolve => {
window.addEventListener("message", function({data}) {
// We only accept messages from ourselves
if (data.handShake != handShake) return;
resolve(data);
}, false);
});
}
extractGlobal('someVariableName').then(data => {
// Do Work Here
});
Я бы порекомендовал добавить класс в его собственный файл и экспортировать его по умолчанию, если используются модули es. Тогда это просто становится:
ExtractPageVariable('someGlobalPageVariable').data.then(pageVar => {
// Do work here
На самом деле я работал над этим, используя API localStorge. Примечание: чтобы использовать это, наш contentcript должен быть в состоянии прочитать localStorage. В файле manifest.json просто добавьте строку «storage»:
"permissions": [...,"storage"]
Функция hijack находится в скрипте содержимого:
function hijack(callback) {
"use strict";
var code = function() {
//We have access to topframe - no longer a contentscript
var ourLocalStorageObject = {
globalVar: window.globalVar,
globalVar2: window.globalVar2
};
var dataString = JSON.stringify(ourLocalStorageObject);
localStorage.setItem("ourLocalStorageObject", dataString);
};
var script = document.createElement('script');
script.textContent = '(' + code + ')()';
(document.head||document.documentElement).appendChild(script);
script.parentNode.removeChild(script);
callback();
}
Теперь мы можем вызывать из contentcript
document.addEventListener("DOMContentLoaded", function(event) {
hijack(callback);
});
или если вы используете jQuery в вашем файле содержания, как я:
$(document).ready(function() {
hijack(callback);
});
, чтобы извлечь содержимое:
function callback() {
var localStorageString = localStorage.getItem("ourLocalStorageObject");
var ourLocalStorageObject= JSON.parse(localStorageString);
console.log("I can see now on content script", ourLocalStorageObject);
//(optional cleanup):
localStorage.removeItem("ourLocalStorageObject");
}
Это может быть вызвано несколько раз поэтому, если ваша страница изменяет элементы или внутренний код, вы можете добавить прослушиватели событий для обновления вашего расширения новыми данными.
Редактировать: я добавил обратные вызовы, чтобы вы могли быть уверены, что ваши данные не будут недействительными (была эта проблема сама)
№
Сценарии содержимого выполняются в специальной среде, называемой изолированным миром. Они имеют доступ к DOM страницы, в которую они внедрены, но не к каким-либо переменным или функциям JavaScript, созданным этой страницей. Каждый скрипт содержимого выглядит так, как будто на странице, на которой он запущен, нет другого JavaScript-кода. То же самое верно и в обратном: JavaScript, работающий на странице, не может вызывать какие-либо функции или обращаться к любым переменным, определенным скриптами содержимого.
Изолированные миры позволяют каждому скрипту контента вносить изменения в свою среду JavaScript, не беспокоясь о конфликте со страницей или другими скриптами контента. Например, сценарий контента может включать JQuery v1, а страница может включать JQuery v2, и они не будут конфликтовать друг с другом.
Другим важным преимуществом изолированных миров является то, что они полностью отделяют JavaScript на странице от JavaScript в расширениях. Это позволяет нам предлагать дополнительные функции сценариям содержимого, которые не должны быть доступны с веб-страниц, не беспокоясь о доступе к ним веб-страниц.
Если вы знаете, к каким переменным вы хотите получить доступ, вы можете быстро создать собственный скрипт контента для получения их значений.
В popup.js
:
chrome.tabs.executeScript(null, {code: 'var name = "property"'}, function() {
chrome.tabs.executeScript(null, {file: "retrieveValue.js"}, function(ret) {
for (var i = 0; i < ret.length; i++) {
console.log(ret[i]); //prints out each returned element in the array
}
});
});
В retrieveValue.js
:
function returnValues() {
return document.getElementById("element")[name];
//return any variables you need to retrieve
}
returnValues();
Вы можете изменить код для возврата массивов или других объектов.
Как объяснено частично в других ответах, переменные JS со страницы изолированы от вашего скрипта содержимого расширения Chrome. Обычно нет никакого доступа к ним.
Но если вы вставите тег JavaScript на страницу, у вас будет доступ к тем переменным, которые там определены.
Я использую служебную функцию для ввода моего скрипта на странице:
/**
* inject - Inject some javascript in order to expose JS variables to our content JavaScript
* @param {string} source - the JS source code to execute
* Example: inject('(' + myFunction.toString() + ')()');
*/
function inject(source) {
const j = document.createElement('script'),
f = document.getElementsByTagName('script')[0];
j.textContent = source;
f.parentNode.insertBefore(j, f);
f.parentNode.removeChild(j);
}
Затем вы можете сделать:
function getJSvar(whichVar) {
document.body.setAttribute('data-'+whichVar,whichVar);
}
inject('(' + getJSvar.toString() + ')("somePageVariable")');
var pageVar = document.body.getAttribute('data-somePageVariable');
Обратите внимание, что если переменная представляет собой сложный тип данных ( object, array ...), вам нужно будет сохранить значение в виде строки JSON в getJSvar (), и JSON.parse вернуть его в свой скрипт контента.