2015-04-03 4 views
13

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

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

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

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

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

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

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

+0

Но, конечно же, это точка возврата HTML5? – theonlygusti

+1

@theonlygusti Если вы продолжаете читать, проблема в том, что я понятия не имею, когда мне нужно вернуться к HTML5. Все, что я могу получить в браузере, говорит мне, что Flash включен, поэтому я загружаю Flash. Если мне нужно загрузить мое решение HTML5, мне нужно знать, отключена ли Flash в JavaScript. Если вы скажете мне, как я могу определить, отключена ли Flash, это решит мою проблему. – Omninternet

+0

Как насчет document.plugins? Это может сказать вам нечто иное, чем navigator.plugins. Последний - это установленные плагины, первый (предположительно) плагины в документе, которые могут отличаться из-за того, что они изолированы. Я еще не проверил. –

ответ

4

проект, 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); 
    } 
} 

Я попытался повторить свой вопрос и проверить, если это решение работает, я должен был вставить скрипт в самом окно из-за проблемы безопасности.

<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/, которая показывает эту работу.

+0

Вы можете добавить немного о том, как sandblaster делает то, что он делает с этим сообщением, а также в случае, если проект исчезнет в будущем? –

+0

@TimB, конечно. Я добавил некоторые, которые, по моему мнению, актуальны. – Starx

+0

Это отлично работает для меня, даже для кросс-домена. Ключ находится в функции _getEffectiveScriptOrigin(). В принципе, если вы находитесь в изолированном iframe, document.domain будет пустой строкой. В противном случае он будет настроен на что-то. – Omninternet

4

Я буду рассматривать различные виды фреймов (выбрать первый случай, который применяется):

  • Iframes с sandboxed scripts browsing context flag

    То есть, плавающие фреймы с атрибутом sandbox, который не содержит ключевое слово allow-scripts.

    Этот флаг blocks script execution. В частности, вы не можете использовать скрипт, чтобы проверить, изолирован ли iframe.

  • Same-происхождения фреймов без sandboxed origin browsing context flag

    То есть, тот же происхождения, не имеющие плавающие фреймы sandbox атрибута, или же происхождения фреймов с атрибутом sandbox который содержит allow-same-origin и allow-scripts ключевые слова.

    В этом случае вы можете использовать глобальное свойство frameElement для доступа к элементу фрейма (возвращает null, когда он не используется внутри iframe).

    Как только у вас есть ссылка на iframe, вы можете использовать hasAttribute или getAttribute, чтобы проверить его атрибут sandboxed. Существует также свойство sandboxed, которое должно вернуть DOMSettableTokenList (старые браузеры могут возвращать строку в соответствии со старой спецификацией).

  • Перекрестная происхождения фреймов без sandboxed origin browsing context flag

    То есть, кросс-происхождения фреймов, не имеющие sandbox атрибута, или кросс-происхождения фреймов с атрибутом sandbox который содержит allow-same-origin и allow-scripts ключевых слов.

    В этом случае использование frameElement заблокирован:

    Тогда, я не думаю, что вы можете различать, является ли IFrame песочнице или нет в данном случае. Однако, поскольку использование allow-same-origin в перекрестном iframe не очень полезно, подумайте о том, что iframe не изолирован.

  • Iframes с sandboxed origin browsing context flag

    То есть, плавающие фреймы с атрибутом sandbox, который не содержит ключевое слово allow-same-origin но содержит allow-scripts ключевое слово.

    Как в предыдущем случае, использование frameElement заблокировано.

    Однако вы можете обнаружить этот случай, потому что document.domain будет пустой строкой.

Примечание: 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'; 
} 
+1

Это работает для меня в Firefox, но в Chrome это похоже на попытку доступа к 'window.frameElement' из изолированного iframe исключения. Конечно, ловить исключение должно быть разумной диагностикой само по себе. –

+0

@IlmariKaronen Интересно, w3c говорит, что браузеры должны бросать, но whatwg говорит, что они должны вернуть null. Я уточню свой ответ. – Oriol

+0

Черт, похоже, хорошо работает в Firefox и для другого домена, но только [из-за кэширования] (http://shouldiblamecaching.com/). Извините Chrome за то, что обвинил вас в том, что вы не очень хорошо это делаете. Тогда этот ответ становится несколько лишним. Я подумаю, могу ли я улучшить его каким-либо образом, иначе я могу его удалить. – Oriol

Смежные вопросы