Подтвердить что ты не робот

Обнаруживать, выполняется ли JavaScript в изолированном iframe?

У меня есть продукт, который воспроизводит видео во Flash (если доступно) и возвращается к HTML5, если Flash недоступен.

Я не могу найти способ определить, выполняется ли JavaScript в iframe с атрибутом "песочница", который необходим для моего решения, потому что изолированные iframes изолированы от всех плагинов. Песочница iframe может быть простой:

<iframe src="http://www.cross-domain.com/" sandbox="allow-scripts">

Чтобы определить, включена ли Flash, я использую swfobject метод проверки описания navigator.plugins [ "Shockwave Flash" ]., которое устанавливается даже в изолированном iframe. Я могу загрузить объект swf, но он не воспроизводится.

Чтобы воспроизвести эту проблему, зайдите в http://jsfiddle.net/max_winderbaum/9cqkjo45/, откройте свой хромовый инспектор и нажмите "Запустить". script на междоменном сайте приостановится в контексте изолированного iframe.

В соответствии со спецификацией W3 в http://dev.w3.org/html5/spec-preview/browsers.html#sandboxing-flag-set предполагается, что в документе, к которому может обращаться JavaScript, должен быть установлен "активный флаг песочницы" (по крайней мере, тот как я читаю спецификацию). В документе iframe не установлен какой-либо флаг.

Есть ли у кого-нибудь идеи/решения о том, как определить, выполняется ли JavaScript из изолированного iframe?

4b9b3361

Ответ 1

Проект sandblaster может помочь вам определить, работает ли вы в песочнице.

Песочница проверяет, сначала ли создан кадр, а затем просматривает атрибуты элемента фрейма для обнаружения нескольких сведений о себе. Они включают в себя framed, crossOrigin, sandboxed, sandboxAllowances, unsandboxable, resandboxable, sandboxable.

Чтобы определить, является ли сам песочником в нашем случае, он проверяет, имеет ли элемент фрейма атрибут sandbox.

// On below `frameEl` is the detected frame element
try {
  result.sandboxed = frameEl.hasAttribute("sandbox");
}
catch (sandboxErr) {
  result.sandboxed = null;
  if (typeof errback === "function") {
    errback(sandboxErr);
  }
}

Я попытался реплицировать вашу проблему и проверить, работает ли это решение, мне пришлось вставить script в само окно из-за проблемы с безопасностью.

<html>
    <head>
    </head>
    <body>

    <script>
        //Paste the contents of the script(https://raw.githubusercontent.com/JamesMGreene/sandblaster/master/dist/sandblaster.js) here

        var result = sandblaster.detect();
        if(result.sandboxed === true) {
            //sandboxed
        }
        debugger;
    </script>
    </body>
</html>

Вот демо: http://jsfiddle.net/Starx/tzmn4088/, который показывает, что это работает.

Ответ 2

Я рассмотрю различные типы iframes (выберите первый применимый случай):

Примечание: Firefox обрабатывает URI данных как одноименное, так что это нормально. Однако Chrome относится к ним как к перекрестному происхождению. Тогда frameElement не работает, а document.domain - это пустая строка, независимо от того, изолирована ли iframe или нет. Вы можете проверить, есть ли location.protocol строка 'data:' для определения URI данных.

В общем вы можете попробовать что-то вроде

function isSandboxedIframe() {
  if (window.parent === window) return 'no-iframe';
  try { var f = window.frameElement; } catch(err) { f = null; }
  if(f === null) {
    if(document.domain !== '') return 'unkown'; // Probably 'non-sandboxed'
    if(location.protocol !== 'data:') return 'sandboxed';
    return 'unkown'; // Can be 'sandboxed' on Firefox
  }
  return f.hasAttribute('sandbox') ? 'sandboxed' : 'non-sandboxed';
}