YouTube嵌入:尝试访问框架的不安全JavaScript

56
我们有一个Wicket应用程序,其中包含一个嵌入的Youtube视频的页面。视频可以嵌入和播放,但显然它会导致页面上未渲染的DOM元素不显示,尽管在标记中存在。
在Chrome中查看错误控制台会显示:
“不安全的JavaScript尝试访问 包含URL的帧 http://example.com/detail/COMMUNICATION/search/com-sonyericsson-hanashi 来自帧的URL http://www.youtube.com/embed/eJY7_De5opI?enablejsapi=1&autohide=1&showinfo=1。 域、协议和端口必须匹配。”
我已经通过谷歌搜索了很多,人们似乎在说这是无害的并且可以忽略它。这听起来就是错误的,在我们的情况下它实际上破坏了页面。
如果我们更改应用程序,使视频通过ajax回调动态嵌入(用户点击Wicket AjaxLink),我们仍然会在控制台中收到错误,但至少页面会完全呈现。不幸的是,这对我们来说行不通,因为我们需要视频在用户第一次访问页面时默认加载。
编辑:我应该补充说明,虽然错误消息来自Chrome控制台,但该错误似乎影响我尝试过的每个浏览器:Chrome、Safari和Firefox。

2
我知道这是一个旧的问题,但你有没有看过 Facebook 是如何做的?他们并不总是会出现错误。他们使用旧的<embed>标签,但它们是在 Facebook 的 iFrame 中实现的(我相信这些都是正确的)。 - ThePrimeagen
对我来说似乎并不无害。直到我从<iframe>切换到<embed>代码后,我的JavaScript API调用才能正常工作。 - Brad Koch
5个回答

24

安全错误不太可能破坏您的页面。看起来错误是发生在YouTube框架内部,这意味着在最坏的情况下,框架的内容将会被弄乱。

来自外部页面的框架/iframe除非它们来自相同的域名和端口号,否则无论在任何情况下都无法影响父文档的内容。这是浏览器安全性的硬性规定之一。

错误应该出现在您的标记中的其他位置。有没有看到一些示例标记的机会?

[编辑]

错误也可能出现在嵌入代码标记中。或者,如果直接在页面中包含任何脚本标记(而不是在iframe中),那么错误可能就在那里。

通常,当出现此类问题时,是因为某个标记未关闭,但也可能是JavaScript引起的。


26
这可能听起来很糟糕,因为它不太符合直觉。但是,如果要与大多数浏览器兼容,iframes无法内联关闭。因此,您需要使用 ></iframe> 而不是 /> - Andrew Curioso
2
哇,我简直不敢相信就是这个问题。我应该更明智:几天前我写了这个,而且本质上是同样的问题:https://dev59.com/d1fUa4cB1Zd3GeqPLdC7#6207343。非常感谢,安德鲁。 - George Armhold
2
不用谢。我从来没明白为什么<iframe>不能内联关闭 :) 这是我最讨厌的之一。 - Andrew Curioso
15
iframes不会自我关闭,因为它们可以包含需要在无法呈现iframes的浏览器中显示的内容,类似于noscript标签。自我关闭的标签在xhtml中很常见,但要注意 - xhtml不依赖于文档类型,而是依赖于内容类型。如果您的头文件设置为提供text/html,则浏览器将其解释为html而不是xhtml,并可能导致渲染错误。 - James Alday
我的脚本: String html = "<iframe class="youtube-player" style="border: 0; width: 100%; height: 95%; padding:0px; margin:0px" id="ytplayer" type="text/html" src="https://www.youtube.com/embed/1J0aXDbjiUE?autoplay=1" + "?fs=0" frameborder="0">\n" + "</iframe>";mWebView.loadData(html, "text/html", null); 我仍然收到“不安全的JavaScript…”错误。 - Bagusflyer
显示剩余5条评论

7

如果你在解决JavaScript错误时遇到问题,可以尝试使用YouTube的旧嵌入代码。在点击嵌入后,每个YouTube视频都有这个选项。它不使用iframes,因此您将不会遇到该错误。代码可能如下所示:

<object width="560" height="315">
    <param name="movie" value="http://www.youtube.com/v/9DXL9vIUbWg?version=3&amp;hl=en_US&amp;rel=0"></param>
    <param name="allowFullScreen" value="true"></param>
    <param name="allowscriptaccess" value="always"></param>
    <embed src="http://www.youtube.com/v/9DXL9vIUbWg?version=3&amp;hl=en_US&amp;rel=0" type="application/x-shockwave-flash" width="560" height="315" allowscriptaccess="always" allowfullscreen="true"></embed>
</object>

希望这能帮到您。

这在移动浏览器上并不总是与响应式设计兼容。 - Pedery
使用<object>方法进行加法运算时,您可能会遇到很多错误,例如:.PPAPIContext: GL ERROR :GL_INVALID_VALUE : glTexSubImage2D: bad dimensions. - Jeffz

5

我投票支持Jonathan Torres的回答,因为他的代码能够停止Javascript警告。但是当我验证该代码时,发现了错误。

我的回答是这样的...

在使用YouTube的嵌入代码时勾选“使用旧版嵌入代码”复选框,以免使用iframe。

为了使代码验证通过,您需要添加...

type="movie"

并且

data="http://SAME YOUTUBE URL USED IN THE FIRST PARAM ELEMENT/"

PARAM 元素自闭合(但不包括 EMBED 元素),并添加到 OBJECT 元素。这将使您的 YouTube 代码看起来像这样...
<object width="560" height="315" type="movie" data="http://www.youtube.com/v/9DXL9vIUbWg?version=3&amp;hl=en_US&amp;rel=0">
<param name="movie" value="http://www.youtube.com/v/9DXL9vIUbWg?version=3&amp;hl=en_US&amp;rel=0"></param><param name="allowFullScreen" value="true" />
<param name="allowscriptaccess" value="always" />
<embed src="http://www.youtube.com/v/9DXL9vIUbWg?version=3&amp;hl=en_US&amp;rel=0" type="application/x-shockwave-flash" width="560" height="315" allowscriptaccess="always" allowfullscreen="true"></embed>
</object>

然后您不应该收到JavaScript警告,您的代码应该验证通过。


感谢您抽出时间来解决并发布这个问题!对我有用。 - robnardo

2
Unsafe JavaScript attempt to access frame 错误与你的页面未渲染无关。损坏的标记(例如缺失 </iframe>)是最可能的原因。
至于 Unsafe JavaScript attempt to access frame 错误,你有几个选择:
  1. 最简单的解决方案是使用IFrame Player API而不是手动添加 iframe 标记。该API是一段JavaScript代码,可以 生成 iframe 标记并为其添加参数,这将(或应该)消除框架访问错误。以下是使用IFrame播放器API加载播放器的说明。

  2. 手动解决方法是构建 <iframe> 标记,并将 &origin=http://example.com 参数附加到URL上。引用:

作为额外的安全措施,您还应在URL中包含 origin 参数,将主机页面的URL方案(http://或https://)和完整域指定为参数值。虽然 origin 是可选的,但包括它可以防止恶意第三方 JavaScript 被注入到您的页面中并劫持您的YouTube播放器。


1
尝试了第二种方法,但效果不好。仍然收到控制台警告。谢谢。 - Dimitry
1
这仍然会引起问题。 - Chris Nicola

0

对我来说,使用这里的代码可以解决问题: https://developers.google.com/youtube/iframe_api_reference#Loading_a_Video_Player

我修改的行中,将带有两个星号 ** 的单词标记为 market:code:

修改前:

var tag = document.createElement('script');
          tag.src = "**http://www.youtube.com/player_api**";
          var firstScriptTag = document.getElementsByTagName('script')[0];
          firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
          var players = new Array();
          function **onYouTubePlayerAPIReady()** {

        var ids = $('div.video div');

        for(var i=0; i < ids.length; i++) {
            players.push(new YT.Player('**yt**'+i, {
                height: '400',
                width: '596',
                videoId: $(ids[i]).attr('rel'),
                events: {
                    'onReady': onPlayerReady,
                    'onStateChange': onPlayerStateChange
                }
            }));
        }

      }

转换为:

var tag = document.createElement('script');
  tag.src = "**https://www.youtube.com/iframe_api**";
  var firstScriptTag = document.getElementsByTagName('script')[0];
  firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
  var players = new Array();
  function **onYouTubeIframeAPIReady()** {

    var ids = $('div.video div');

    for(var i=0; i < ids.length; i++) {
        players.push(new YT.Player('**player**'+i, {
            height: '400',
            width: '596',
            videoId: $(ids[i]).attr('rel'),
            events: {
                'onReady': onPlayerReady,
                'onStateChange': onPlayerStateChange
            }
        }));
    }

  }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接