В приложении 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