Greasy Fork is available in English.

Tartışmalar » Geliştirme

Access Iframe Content

§
Gönderildi: 06.04.2019

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:
        }

    });
wOxxOmMod
§
Gönderildi: 06.04.2019

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) {}
    }
  });

}
§
Gönderildi: 06.04.2019

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.

Cevap paylaş

Yanıt göndermek için oturum açın.