Này người xa lạ!

Còn chờ gì nữa mà không mau đăng nhập hoặc đăng ký để cùng tham gia thảo luận với cộng đồng!

Access Iframe Content

I'm trying to access a video inside an iframe, but I am getting the error "Permission denied to access property x on cross-origin object" for the innerDoc video. The iframe is youtube, so I have this as my userscript property:

// @include https://original-website.com/*
// @match *.youtube.com/*

And here is my javascript:

    var video, mode, iframe, innerDoc;

    $('.speed-control button').on('click', (evt) => {

        mode = $(event.target).attr('class').match(/speed-control-(.*)/)[1];        
        iframe = document.getElementById('videoPlayer_Youtube_api');
        innerDoc = (iframe.contentWindow || iframe.contentDocument);
        video = innerDoc.querySelectorAll('video');

        switch(mode){
            case 'slow':
                video.playbackRate  = 0.5;
                break;
            case 'normal':
                video.playbackRate  = 1;
                break;
            case 'fast':
                video.playbackRate  = 2;
                break;
            default:
        }

    });

Bình luận

  • Modern browsers can't access a cross-domain iframe contents directly. Since your userscript runs both on the main page and inside the iframe you can use cross-window messaging:

    const MSG_PREFIX = GM_info.script.name + '\n';
    
    if (window === top) {
    
      $('.speed-control button').on('click', function () {
        const payload = JSON.stringify({
          action: 'speedControl',
          data: this.className.match(/speed-control-(.*)/)[1],
        });
        const iframe = document.getElementById('videoPlayer_Youtube_api');
        iframe.contentWindow.postMessage(MSG_PREFIX + payload, '*');
      });
    
    } else if (location.hostname.endsWith('youtube.com')) {
    
      const ACTIONS = {
        speedControl(mode) {
          switch (mode) {
            case 'slow':
              video.playbackRate = 0.5;
              break;
            case 'normal':
              video.playbackRate = 1;
              break;
            case 'fast':
              video.playbackRate = 2;
              break;
            default:
          }
        },
      };
    
      window.addEventListener('message', e => {
        if (typeof e.data === 'string' && e.data.startsWith(MSG_PREFIX)) {
          try {
            const payload = e.data.slice(MSG_PREFIX.length);
            const {action, data} = JSON.parse(payload);
            if (ACTIONS.hasOwnProperty(action)) {
              ACTIONS[action](data);
            }
          }
          catch (ex) {}
        }
      });
    
    }
    
  • Thank you so much! I just had to define the video variable but other than that, your code works really well. Gonna look into postMessage more to understand it better.

Đăng nhập hoặc Đăng ký để gửi bình luận.