Как правило, пытаться обойти Content Security Policy в наших приложениях — очень плохая идея. Тем не менее, есть один частный случай, в котором мы хотели бы избавиться от него, чтобы свободно загружать некоторые дополнительные ресурсы по сети. Я говорю о расширениях Chrome. В зависимости от вашей архитектуры вы можете быть ограничены правилами CSP, и если это так, эта статья поможет вам преодолеть это.

Когда это происходит?

Если ваше расширение отображает себя поверх страницы, вероятно, у вас возникнут проблемы с CSP на некоторых веб-сайтах. Это зависит от того, как вы встраиваете свои пользовательские представления на страницу. Если вы используете iframe, вам не нужно думать об ограничениях хоста. Встроенные фреймы могут рассматриваться как почти изолированные от хоста, и поэтому любые правила, наложенные на них, здесь не работают. Однако совсем другое дело, если вы встраиваете свой код непосредственно в DOM, как это делают многие популярные расширения. Затем вы должны поделиться контекстом выполнения с хостом, и, как вы, наверное, догадались, это не так уж и просто.

Как мы можем обойти это?

Каждое расширение может включать сценарии содержимого и фоновые сценарии. В данном случае нам понадобятся оба. В двух словах, вы можете получить все, что вам нравится, в фоновых сценариях, а сценарии содержимого могут общаться с ними с помощью сообщений. Идея состоит в том, чтобы получить фоновое изображение, а затем отправить его сценарию контента. Звучит легко, правда? Проблема в том, что все данные, отправляемые через API обмена сообщениями, должны быть сериализуемыми, а изображения — нет по умолчанию. Вы, вероятно, наткнулись на кодировку Base64, которая позволяет нам кодировать любые двоичные данные в строку ASCII. Мы можем использовать его здесь, чтобы получить сериализованное представление и отправить его в скрипт содержимого. Последняя недостающая часть прослушивает ошибки. Изображения, которые не удалось загрузить, выдают событие ошибки, которое не всплывает, но может быть захвачено на любом уровне. Мы можем добавить прослушиватель событий «ошибка» на уровне документа на этапе захвата. Таким образом, мы будем получать информацию, когда какое-либо изображение на странице не загружается.

Как это реализовать?

Начнем с создания пользовательской оболочки над элементом изображения. Это позволит нам переключать видимость, чтобы скрыть состояние ошибки по умолчанию от конечного пользователя.

Затем мы должны создать сценарий содержимого и поместить сюда прослушиватель событий. В обработчике мы хотели бы игнорировать все события, не вызванные нашим пользовательским компонентом. Мы можем добиться этого, проверив наличие атрибута расширения данных. Затем мы отправим сообщение фоновому сценарию с запросом представления запрашиваемого изображения в кодировке Base64. Когда придет ответ, мы можем поменять источник и снова сделать изображение видимым. Обратите внимание на значение true, переданное в качестве последнего параметра в вызове addEventListener. Это означает, что мы хотим использовать режим захвата. Это необходимо, так как события ошибок не всплывают, как другие.

Теперь пришло время для последней части, создания фонового скрипта. Мы будем использовать его для прослушивания сообщений и обработки их, извлекая запрошенный ресурс, сериализуя его в строку Base64 и отправляя обратно в качестве ответа. Нам также нужно найти значение заголовка Content-Type и поместить его содержимое в ответ. Без него браузер не сможет правильно декодировать и отобразить изображение. В случае какой-либо ошибки мы отправим ее обратно и оставим ее обработку сценарию содержимого.

Вот и все! Теперь все изображения должны нормально загружаться. Будет небольшая задержка, но это лучше, чем ничего, не так ли? Я использовал этот шаблон в одном из своих расширений, и у меня никогда не было с ним проблем. Это просто работает.

Я надеюсь, что эта статья оказалась полезной. Если вы хотите ознакомиться с исходным кодом, см. это суть.

Оставайтесь с нами, чтобы не пропустить новые советы и рекомендации!