В приложении Chrome с помощью AngularJS я могу использовать директиву ngSrc непосредственно для внутренних изображений?
Я пишу приложение Chrome с помощью AngularJS. Я знаю, что при обращении к внешним изображениям вы должны выполнить XMLHttpRequest с перекрестным происхождением и служить им как blobs.
У меня есть куча внутренних изображений (ресурсов локального приложения), которые следуют шаблону, который я хочу отобразить в ngRepeat.
Я могу заставить изображения загружать статически просто отлично с чем-то вроде:
<img src="images/image1.png"/>
Но когда я пытаюсь использовать их в повторении так:
<div ng-repeat="item in myList">
<img ng-src="{{item.imageUrl}}"/>
</div>
Я получаю сообщение об ошибке для каждого изображения (хотя изображение из ошибки существует):
Refused to load the image 'unsafe:chrome-extension://hcdb...flhk/images/image1.png' because it violates the following Content Security Policy directive: "img-src 'self' data: chrome-extension-resource:".
Я смог успешно загрузить внешние ресурсы с помощью ng-src и XHR. Должен ли я следовать той же схеме для динамических загружаемых внутренних ресурсов?
Обновление - еще один простой пример
Начиная с простейшего приложения Chrome (https://github.com/GoogleChrome/chrome-app-samples/tree/master/hello-world), следующее будет работать вне приложения Chrome (в браузере), но не в пределах приложение Chrome:
index.html
<!DOCTYPE html>
<html ng-app ng-csp>
<head>
<title>Hello World</title>
<script src="js/angular.min.js"></script>
<script src="js/test.js"></script>
</head>
<body ng-controller="Ctrl">
<img ng-src="{{imageUrl}}"/>
</body>
</html>
test.js
function Ctrl($scope) {
$scope.imageUrl = 'hello_world.png';
}
Ответы
Ответ 1
Я только что нашел ответ в другом вопросе:
Angular изменяет URL-адреса на" unsafe: " на странице расширения
Angular имеет регулярное выражение в белом списке, которое должно совпадать с URL-адресом изображения src, прежде чем angular изменит src. Хром-расширение://url не соответствует ему по умолчанию, поэтому вам нужно его изменить. См. Здесь дополнительную информацию:
http://docs.angularjs.org/api/ng/provider/ $compileProvider
Я добавил следующий код, чтобы разрешить хром-расширение//URL-адреса в белый список (используя код из другого ответа на вопрос о stackoverflow):
angular.module('myApp', [])
.config( [
'$compileProvider',
function( $compileProvider ) {
var currentImgSrcSanitizationWhitelist = $compileProvider.imgSrcSanitizationWhitelist();
var newImgSrcSanitizationWhiteList = currentImgSrcSanitizationWhitelist.toString().slice(0,-1)
+ '|chrome-extension:'
+currentImgSrcSanitizationWhitelist.toString().slice(-1);
console.log("Changing imgSrcSanitizationWhiteList from "+currentImgSrcSanitizationWhitelist+" to "+newImgSrcSanitizationWhiteList);
$compileProvider.imgSrcSanitizationWhitelist(newImgSrcSanitizationWhiteList);
}
]);
Ответ 2
Подобно уже предоставленному ответу, ниже приведена функция, которая перезаписывает регулярное выражение AngluarJs для whitelisting URL-адресов img src.
В основном, происходит то, что angular js не будет доверять URL-адресу, включенному в тег ng-src, и будет пытаться проверить/дезинформировать их. В результате этого процесса URL-адрес, указанный в этом теге, будет иметь строку "небезопасная:". Это, в свою очередь, определяет время выполнения хрома, чтобы не отображать изображение, так как оно не может найти изображение, расположенное в "unsafe:/path/to/image/img.jpg".
Итак, нам нужно перезаписать регулярное выражение, которое присваивает белые URL-адреса img src. Аналогичные регулярные выражения для URL-адресов href. Для этого вам нужно прочитать документацию angular js.
appModule является основным модулем приложения в приложении angular js.
appModule.config([
'$compileProvider',
function ($compileProvider) {
// Default imgSrcSanitizationWhitelist: /^\s*((https?|ftp|file|blob):|data:image\/)/
// chrome-extension: will be added to the end of the expression
$compileProvider.imgSrcSanitizationWhitelist(/^\s*((https?|ftp|file|blob|chrome-extension):|data:image\/)/);
}
]);
Ответ 3
Попробуйте запустить каждое изображение src с помощью функции типа
<div ng-repeat="item in myList">
<img ng-src="{{trustAsResourcUrl(item.imageUrl)}}"/>
</div>
И внутри вашего контроллера
$scope.trustAsResourcUrl = function(url) {
return $sce.trustAsResourceUrl(url);
}
Не забудьте включить службу $sce. Вы также можете попытаться полностью отключить SCE
устранить его
angular.module('myAppWithSceDisabledmyApp', []).config(function($sceProvider) {
// Completely disable SCE. For demonstration purposes only!
// Do not use in new projects.
$sceProvider.enabled(false);
});
Ответ 4
Получите его для работы на основе ответа Эрика Чена, создав такую директиву:
angular.module('myAppInChromeApp',[]).directive('cspSrc', function() {
return {
restrict: 'A',
replace: false,
priority: 99, //after all build-in directive are compiled
link: function(scope, element, attrs) {
attrs.$observe('cspSrc', function(value) {
if (!value)
return;
if (element[0].nodeName.toLowerCase() === 'img' && value.indexOf('blob') !== 0) {
//if it is img tag then use XHR to load image.
var localSrc = null;
var xhr = new XMLHttpRequest();
xhr.open('GET', value, true);
xhr.responseType = 'blob';
xhr.onload = function(e) {
localSrc = URL.createObjectURL(this.response);
element[0].src = localSrc;
};
xhr.send();
scope.$on("$destroy", function() {
if (localSrc) {
URL.revokeObjectURL(localSrc);
}
});
} else {
attrs.$set('src', value);
}
});
}
};
})
;
Ответ 5
Мой подход не используется ng-src.
Я написал свой onw csp-src для политики безопасности Chrome.
angular.module('myAppInChromeApp',[]).directive('cspSrc', function () {
return {
restrict: 'A',
replace: false,
priority: 99, //after all build-in directive are compiled
link: function(scope, element, attrs) {
attrs.$observe('ngSrc', function(value) {
if (!value)
return;
if(element[0].nodeName.toLowerCase() === 'img' && value.indexOf('blob') != 0){
//if it is img tag then use XHR to load image.
var localSrc = null;
var xhr = new XMLHttpRequest();
xhr.open('GET', value, true);
xhr.responseType = 'blob';
xhr.onload = function (e) {
localSrc = URL.createObjectURL(this.response);
};
xhr.send();
scope.$on("$destroy", function() {
localSrc && URL.revokeObjectURL(localSrc);
});
attrs.$set('src', localSrc);
}else{
attrs.$set('src', value);
}
});
}
};
})
и измените ng-src на csp-src
<img csp-src="http://yourimage.jpg"/>
конечно, вы можете добавить еще условие make csp-src работать как для веб-сайта, так и для chromeapp