Как разрешить встроенные скрипты chrome extension [duplicate]

Ответ Фабрисио на месте; но я хотел дополнить его ответ чем-то менее техническим, который фокусируется на аналогии, чтобы помочь объяснить концепцию асинхронности .


Аналогия ...

Вчера работа, которую я делал, требовала некоторой информации от коллеги. Я позвонил ему; вот как прошел разговор:

Me: Привет, Боб, мне нужно знать, как мы foo 'd bar ' d на прошлой неделе , Джим хочет сообщить об этом, и вы единственный, кто знает подробности об этом.

blockquote>

Боб: Конечно, но мне понадобится около 30 минут?

blockquote>

Я: Это замечательно Боб. Дайте мне звонок, когда у вас есть информация!

blockquote>

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


Представьте, если бы разговор пошел именно так:

Me: Привет, Боб, мне нужно знать, как мы foo на панели 'd на прошлой неделе.

blockquote>

Боб: Конечно, но мне понадобится около 30 минут?

blockquote>

Я: Это замечательно Боб. Я подожду.

blockquote>

И я сидел и ждал. И ждал. И ждал. В течение 40 минут. Не делать ничего, кроме ожидания. В конце концов, Боб дал мне информацию, мы повесили трубку, и я закончил свой отчет. Но я потерял 40 минут производительности.


Это асинхронное и синхронное поведение

Это именно то, что происходит во всех примерах нашего вопроса. Загрузка изображения, загрузка файла с диска и запрос страницы через AJAX - это медленные операции (в контексте современных вычислений).

Вместо того, чтобы ожидает для выполнения этих медленных операций, JavaScript позволяет зарегистрировать функцию обратного вызова, которая будет выполнена при завершении медленной операции. Тем временем, однако, JavaScript будет продолжать выполнять другой код. Тот факт, что JavaScript выполняет другой код , ожидая завершения медленной операции, делает поведение асинхронным. Если JavaScript выполнил операцию до завершения любого другого кода, это было бы синхронным поведением.

var outerScopeVar;    
var img = document.createElement('img');

// Here we register the callback function.
img.onload = function() {
    // Code within this function will be executed once the image has loaded.
    outerScopeVar = this.width;
};

// But, while the image is loading, JavaScript continues executing, and
// processes the following lines of JavaScript.
img.src = 'lolcat.png';
alert(outerScopeVar);

В приведенном выше коде мы запрашиваем JavaScript для загрузки lolcat.png, который операция sloooow . Функция обратного вызова будет выполнена после выполнения этой медленной операции, но в то же время JavaScript будет продолжать обрабатывать следующие строки кода; т.е. alert(outerScopeVar).

Вот почему мы видим предупреждение, показывающее undefined; так как alert() обрабатывается немедленно, а не после загрузки изображения.

Чтобы исправить наш код, все, что нам нужно сделать, - переместить код alert(outerScopeVar) в функцию обратного вызова. Вследствие этого нам больше не нужна переменная outerScopeVar, объявленная как глобальная переменная.

var img = document.createElement('img');

img.onload = function() {
    var localScopeVar = this.width;
    alert(localScopeVar);
};

img.src = 'lolcat.png';

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

Поэтому во всех наших примерах function() { /* Do something */ } является обратным вызовом; чтобы исправить все примеры, все, что нам нужно сделать, - это переместить код, который нуждается в ответе операции там!

* Технически вы можете использовать eval(), но eval() для этой цели является злом


Как мне ждать моего вызывающего абонента?

В настоящее время у вас есть код, похожий на этот:

function getWidthOfImage(src) {
    var outerScopeVar;

    var img = document.createElement('img');
    img.onload = function() {
        outerScopeVar = this.width;
    };
    img.src = src;
    return outerScopeVar;
}

var width = getWidthOfImage('lolcat.png');
alert(width);

Однако теперь мы знаем, что return outerScopeVar происходит немедленно; перед тем как функция обратного вызова onload обновила переменную. Это приводит к getWidthOfImage() возврату undefined и undefined.

Чтобы исправить это, нам нужно разрешить функции, вызывающей getWidthOfImage(), зарегистрировать обратный вызов, а затем переместить предупреждение ширины, которая должна находиться внутри этого обратного вызова,

function getWidthOfImage(src, cb) {     
    var img = document.createElement('img');
    img.onload = function() {
        cb(this.width);
    };
    img.src = src;
}

getWidthOfImage('lolcat.png', function (width) {
    alert(width);
});

... как и прежде, обратите внимание, что нам удалось удалить глобальные переменные (в данном случае width).

51
задан Xan 8 September 2014 в 10:02
поделиться

3 ответа

Расширения Chrome не позволяют иметь встроенный JavaScript ( documentation ). Вам нужно будет сделать что-то похожее на это.

Назначить идентификатор ссылки (<a onClick=hellYeah("xxx")> становится <a id="link">) и использовать addEventListener , чтобы связать мероприятие. Поместите в файл popup.js следующее:

document.addEventListener('DOMContentLoaded', function() {
    var link = document.getElementById('link');
    // onClick's logic below:
    link.addEventListener('click', function() {
        hellYeah('xxx');
    });
});
96
ответ дан Rob W 27 August 2018 в 01:04
поделиться

Причина

Это не работает, потому что Chrome запрещает любой тип встроенного кода в расширениях через политику безопасности контента.

Встроенный JavaScript не будет выполняться. Это ограничение запрещает как встроенные блоки <script>, так и встроенные обработчики событий (например, <button onclick="...">).

Как обнаружить

Если это действительно проблема, Chrome выполните следующую ошибку в консоли:

Отказано в выполнении встроенного скрипта, поскольку оно нарушает следующую директиву политики безопасности контента: «script-src» self 'chrome-extension-resource: ». Для включения встроенного выполнения требуется либо ключевое слово «небезопасное-встроенное», либо хэш («sha256 -...»), либо nonce («nonce -...»).

Чтобы получить доступ к консоли JavaScript для всплывающих окон (что полезно для отладки в целом), щелкните правой кнопкой мыши кнопку вашего внутреннего абонента и выберите «Осмотреть всплывающее окно» в контекстном меню.

Доступна дополнительная информация об отладке всплывающего окна здесь .

Как исправить

Нужно удалить все встроенные JavaScript. Существует руководство в документации Chrome .

Предположим, что оригинал выглядит так:

<a onclick="handler()">Click this</a> <!-- Bad -->

Нужно удалить атрибут onclick и дать элемент уникальный id:

<a id="click-this">Click this</a> <!-- Fixed -->

И затем присоедините слушателя из скрипта (который должен находиться в файле .js, предположим popup.js):

// Pure JS:
document.addEventListener('DOMContentLoaded', function() {
  document.getElementById("click-this").addEventListener("click", handler);
});

// The handler also must go in a .js file
function handler() {
  /* ... */
}

Обратите внимание на обертку в событии DOMContentLoaded. Это гарантирует, что элемент существует во время выполнения. Теперь добавьте тег скрипта, например, в <head> документа:

<script src="popup.js"></script>

Альтернатива, если вы используете jQuery:

// jQuery
$(document).ready(function() {
  $("#click-this").click(handler);
});

Расслабляющая политика

В: Ошибка указывает способы разрешить встроенный код. Я не хочу / не могу изменить свой код, как включить встроенные скрипты?

A: Несмотря на то, что говорит ошибка, вы не можете включить встроенный скрипт :

Нет механизма ослабления ограничения на выполнение встроенного JavaScript. В частности, установка политики скрипта, которая включает в себя 'unsafe-inline', не будет иметь никакого эффекта.

Обновление: с Chrome 46 можно настроить белый список определенных встроенных блоков кода:

Начиная с Chrome 46 встроенные скрипты могут быть включены в белый список, указывая хэш-код, основанный на base64 исходного кода в политике. Этот хеш должен быть префикс используемого хэш-алгоритма (sha256, sha384 или sha512). См. Использование хэша для <script> элементов для примера.

Однако я не вижу причины использовать это и не включит встроенные атрибуты как onclick="code".

29
ответ дан 3 revs, 2 users 99% 27 August 2018 в 01:04
поделиться

У меня была такая же проблема, и я не хотел переписывать код, поэтому я написал функцию для изменения кода и создания встроенных декларируемых событий:

function compile(qSel){
    var matches = [];
    var match = null;
    var c = 0;

    var html = $(qSel).html();
    var pattern = /(<(.*?)on([a-zA-Z]+)\s*=\s*('|")(.*)('|")(.*?))(>)/mg;

    while (match = pattern.exec(html)) {
        var arr = [];
        for (i in match) {
            if (!isNaN(i)) {
                arr.push(match[i]);
            }
        }
        matches.push(arr);
    }
    var items_with_events = [];
    var compiledHtml = html;

    for ( var i in matches ){
        var item_with_event = {
            custom_id : "my_app_identifier_"+i,
            code : matches[i][5],
            on : matches[i][3],
        };
        items_with_events.push(item_with_event);
        compiledHtml = compiledHtml.replace(/(<(.*?)on([a-zA-Z]+)\s*=\s*('|")(.*)('|")(.*?))(>)/m, "<$2 custom_id='"+item_with_event.custom_id+"' $7 $8");
    }

    $(qSel).html(compiledHtml);

    for ( var i in items_with_events ){
        $("[custom_id='"+items_with_events[i].custom_id+"']").bind(items_with_events[i].on, function(){
            eval(items_with_events[i].code);
        });
    }
}

$(document).ready(function(){
    compile('#content');
})

Это должно удалить все встроенные события из выбранного узла и вместо этого создайте их с помощью jquery.

1
ответ дан sergio0983 27 August 2018 в 01:04
поделиться
Другие вопросы по тегам:

Похожие вопросы: