У меня есть сценарий Механика, который работает просто великолепно в Firefox и Opera. Я борюсь с тем, чтобы заставлять это работать в Chrome, как бы то ни было. Проблема вводит функцию в страницу, которая может быть вызвана кодом от страницы. Вот то, что я делаю до сих пор:
Во-первых, я получаю ссылку помощника на unsafeWindow для Firefox. Это позволяет мне иметь тот же код для FF и Opera (и Chrome, я думал).
var uw = (this.unsafeWindow) ? this.unsafeWindow : window;
Затем, я ввожу функцию в страницу. Это - действительно просто очень тонкая обертка, которая делает только вызов соответствующей функции в контексте моего сценария GM:
uw.setConfigOption = function(newValue) {
setTimeout(setConfigOption, 0, newValue);
}
Затем существует соответствующая функция прямо в моем сценарии:
setConfigOption = function(newValue) {
// do something with it, e.g. store in localStorage
}
Наконец, я ввожу некоторый HTML в страницу со ссылкой для вызова функции.
var p = document.createElement('p');
p.innerHTML = 'set config option to 1';
document.getElementById('injection-point').appendChild(p);
Подводить итог: В Firefox, когда пользователь нажимает, который ввел ссылку, она выполнит вызов функции на unsafeWindow, который затем инициировал тайм-аут, который вызывает соответствующую функцию в контексте моего сценария GM, который затем делает фактическую обработку. (Исправьте меня, если я неправ здесь.)
В Chrome я просто получаю "Непойманный ReferenceError: setConfigOption не определяется" ошибка. И действительно, ввод "window.setConfigOption" в консоль приводит к "неопределенному". В Firebug и консоли разработчика Opera, функция там.
Возможно, существует другой способ сделать это, но несколько моих функций вызываются объектом Flash на странице, которой я верю, заставляет, что у меня есть функции в контексте страницы.
Я бросил беглый взгляд на альтернативы unsafeWindow на Механике Wiki, но они все выглядят довольно ужасными. Я полностью на ложном пути здесь, или я должен более тесно изучить их?
РАЗРЕШЕНИЕ: Я последовал Max S.' совет, и он работает и в Firefox и в Chrome теперь. Поскольку функции, я должен был быть доступен странице, должны были перезвонить в регулярные, я переместил свой целый сценарий в страницу, т.е. это полностью перенесено в функцию, которую он вызвал 'основным ()'.
Для создания дополнительной уродливости из того взлома терпимой я мог, по крайней мере, отбросить использование unsafeWindow и wrappedJSObject теперь.
Мне все еще не удалось получить довольное бегун объема от Механика работа Wiki. Это должно сделать то же, и это, кажется, выполняется очень хорошо, но мои функции никогда не доступны для элементы от страницы, например. Я еще не выяснил, почему это.
Единственный способ взаимодействия с кодом, выполняющимся на странице в Chrome, - через DOM, поэтому вам придется использовать такой хак, как вставка тега с вашим кодом. Обратите внимание, что это может оказаться не совсем удобным, если ваш скрипт должен выполняться раньше всего остального на странице.
EDIT: Вот как расширение Nice Alert делает это:
function main () {
// ...
window.alert = function() {/* ... */};
// ...
}
var script = document.createElement('script');
script.appendChild(document.createTextNode('('+ main +')();'));
(document.body || document.head || document.documentElement).appendChild(script);
Я бегло просмотрел альтернативы unsafeWindow на вики Greasemonkey, но все они выглядят довольно уродливо. Я совершенно не на том пути или мне следует более внимательно изучить их?
Вам следует изучить, потому что это единственный доступный вариант. Я бы предпочел использовать location hack.
myscript.user.js:
function myFunc(){
alert('Hello World!');
}
location.href="javascript:(function(){" + myFunc + "})()"
example.com/mypage.html
<script>
myFunc() // Hello World!
</script>
Конечно, это уродливо. Но работает хорошо.
Метод Content Scope Runner, упомянутый Max S., лучше, чем location hack, потому что его легче отлаживать.
У меня есть это:
contentscript.js:
function injectJs(link) {
var scr = document.createElement('script');
scr.type="text/javascript";
scr.src=link;
document.getElementsByTagName('head')[0].appendChild(scr)
//document.body.appendChild(scr);
}
injectJs(chrome.extension.getURL('injected.js'));
injected.js:
function main() {
alert('Hello World!');
}
main();