【问题标题】:Is there a way in javascript to get all iframes that don't violate same-origin-policy with getElementsByTagName?javascript 中有没有办法使用 getElementsByTagName 获取所有不违反同源策略的 iframe?
【发布时间】:2020-02-22 04:12:20
【问题描述】:

我正在编写一个 chrome 扩展程序,它需要在页面上获取 html5 视频元素,但某些视频元素位于 iframe 中。我在函数中添加了搜索 iframe 的功能,但由于与具有不同 src 域的 iframe 相关的 Same-Origin-Policy,我开始收到错误。

在我的函数中,是否有一种简单的方法可以排除违反同源策略的 iframe?或者更好的是(即使可能不可能),有没有办法仍然从主页搜索具有不同 src 域的 iframe?

有问题的函数:

function getVideo() {
    var videos = document.getElementsByTagName("video");
    if (videos.length >= 1) {
        return videos[0];
    }
    var iframes = document.getElementsByTagName("iframe");
    if (iframes.length >= 1) {
        for (const frame of iframes) {
            videos = frame.contentWindow.document.getElementsByTagName("video");
            if (videos.length >= 1) {
                return videos[0];
            }
        }
    }
    return null; // if a video doesn't exist
}

【问题讨论】:

    标签: javascript iframe google-chrome-extension


    【解决方案1】:

    编辑:

    查看当前解决方案的答案底部。


    原答案:

    当您认为自己已经在这里搜索了足够长的时间以提出问题时,您会发现一些真正有用的东西。

    根据this question 的回答,我将代码更新为:

    function getVideo() {
        var videos = document.getElementsByTagName("video");
        if (videos.length >= 1) {
            return [videos[0], "main"];
        }
    
        // Code that will run only inside iframe
        if (parent === top) {
            var videos = document.getElementsByTagName("video");
            if (videos.length >= 1) {
                return [videos[0], "iframe"];
            }
        }
        return [null, null]; // if a video doesn't exist
    }
    

    并将其包含在我的清单中,以便脚本也可以注入 iframe:

    "content_scripts": [{
        "all_frames": true,
        ...
        
        ...
    }],
    

    这行得通,但它确实使我的其他功能非常难看。示例:

    // if a video exists, set it to the speed and give a notification
    function setSpeed(newSpeed) {
        var returnVal = getVideo();
        var video = returnVal[0], type = returnVal[1];
        if (video != null && type === "main") {
            video.playbackRate = newSpeed;
            inWindowAlert("Speed: " + newSpeed, 1000);
            setIcon(newSpeed);
        }
        if (parent === top) {
            if (video != null && type === "iframe") {
                video.playbackRate = newSpeed;
                inWindowAlert("Speed: " + newSpeed, 1000);
                setIcon(newSpeed);
            }
        }
    }
    

    我会尝试提出一个更清洁的解决方案,但目前它可以工作。希望这对任何人都有帮助。


    新解决方案:

    只是想更新一下,说明我完全重写了扩展程序的逻辑以更轻松地处理这个问题。

    新的解决方案允许在每个帧中运行的内容脚本的每个实例独立运行,并简单地收集其上下文中的所有视频。我还将它们收集在Set 中以避免意外重复。

    我仍然想再次检查以消除全局变量的使用,但扩展现在运行良好,因此它可能会保持一段时间。

    新代码:

    function getVideos() {
      let new_videos = document.getElementsByTagName("video");
      if (new_videos.length >= 1) {
        VIDEOS = new Set(new_videos);
        return VIDEOS;
      }
      return new Set();
    }
    

    // set video to the speed and give a notification, restricts available speeds
    function setSpeed(newSpeed, video) {
      //* BUG-FIX: playback rates below 0.07 rather than 0 were causing errors
      newSpeed = newSpeed > 16 ? 16 : newSpeed < 0.07 ? 0 : newSpeed;
      // limit decimal values to 2 digits, + in front truncates 2.00 -> 2
      SPEED = +newSpeed.toFixed(2);
      video.playbackRate = SPEED;
      tempAlert("Speed: " + SPEED, 2000, video);
      setIcon(SPEED);
    }
    

    其中VIDEOSSPEED 是全局变量。

    【讨论】:

    • 如果您在 Manifest.json 中将 all_frames 设置为 false - 那么我认为您不需要检查名望父级 === 顶部。您获得的框架始终是顶部框架(而不是网页中可能存在的所有子框架)。
    • 如果我将all_frames 设置为false,我将如何从页面上的 iframe 中获取视频元素?扩展所作用的大多数视频都在 iframe 中,因为网站经常嵌入来自其他网站的视频。 *注意:我确实完全重写了函数以使其工作不同,但我很好奇你是否有不同的解决方案。
    猜你喜欢
    • 2016-11-13
    • 2011-03-29
    • 1970-01-01
    • 2021-02-20
    • 1970-01-01
    • 2020-08-16
    • 2011-11-08
    • 2017-04-07
    • 2017-07-22
    相关资源
    最近更新 更多