在Chrome扩展程序中使用YouTube iframe APi的问题

时间:2019-03-26 17:50:02

标签: javascript iframe google-chrome-extension youtube

我正在尝试开发将在youtube.com上运行的Chrome扩展程序,因此我需要访问iframe播放器api。 我本来以为是跨源问题,但源是youtube.com,所以不确定是不是这个问题。

恼人的是,另一个名为TubeBuddy的扩展似乎完全可以满足我的要求,所以我知道这是可能的!

TubeBuddy Iframe API

尝试1 我已尝试实现以下文档中的youtube iframe api:https://developers.google.com/youtube/player_parameters

我的清单中有以下内容:

{
  "short_name": "Test app",
  "name": "TestApp",
  "manifest_version": 2,
  "description": "description",
  "background":
  {
    "page": "./background_scripts/background.html",
    "persistent": true
  },
  "chrome_url_overrides":
  {
    "newtab": "./new_tab/newtab.html"
  },
  "content_scripts": [
  {
    "matches": [
      "http://*/*",
      "https://*/*",
      "file:///*"
    ],
    "all_frames": true,
    "js": [
      "./inject_scripts/react_inject.js",
      "./inject_scripts/bundle.js",
      "./libraries/jquery.min.js",
      "./libraries/jquery-ui.min.js",
      "./inject_scripts/inject.js"
    ],
    "css": [
      "./inject_scripts/inject.css",
      "./libraries/jquery-ui.min.css"
    ]
  }],
  "permissions": [
    "https://*.youtube.com/*",
    "chrome://favicon/",
    "clipboardRead",
    "clipboardWrite",
    "cookies",
    "idle",
    "notifications",
    "tabs",
    "topSites",
    "bookmarks",
    "identity",
    "identity.email",
    "storage",
    "unlimitedStorage",
    "management",
    "tts",
    "tabs",
    "power",
    "activeTab"
  ],
  "externally_connectable":
  {
    "matches": ["*://*.youtube.com/*"]
  },
  "content_security_policy": "script-src 'self' https://www.youtube.com/ https://s.ytimg.com; object-src 'self'; child-src https://www.youtube.com/ https://s.ytimg.com",
  "options_ui":
  {
    "page": "./options/options.html",
    "open_in_tab": false
  },
  "web_accessible_resources": [
    "assets/img/*.svg",
    "assets/img/*.png",
    "https://www.youtube.com/"
  ],
  "version": "2.2.3"
}

其中bundle.js包含用于创建脚本标签的代码,该脚本标签应调用iframe_api

   const tag = document.createElement('script');
      tag.src = 'https://www.youtube.com/iframe_api';
      const firstScriptTag = document.getElementsByTagName('script')[0];
      firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
      window.onYouTubeIframeAPIReady = function onYouTubeIframeAPIReady() {
        player = new YT.Player('wb-player', {
          height: '390',
          width: '640',
          videoId: 'M7lc1UVf-VE',
          events: {
            'onReady': onPlayerReady,
            'onStateChange': onPlayerStateChange
          }
        });
      };

我可以观察到脚本标记是在页面上的DOM中创建的,但是从未调用window.onYoutubeIframeAPIReady,这是因为chrome扩展程序无法访问window对象。

我试图遵循以下答案无济于事:

Youtube player API in Chrome extension

youtube video in chrome extension content script

Detect youtube video events with Chrome extension content script

Youtube iframe API: OnReady not firing for Chrome extension

尝试2 我已经尝试过使用sendMessage API将YT对象注入到content_scripts中,但是由于JSON序列化,由于sendResponse回调剥离了方法和函数,因此这也不起作用。

background.js:

chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
  if (request.message === 'youtube_api') {
    const tag = document.createElement('script');
    tag.src = 'https://www.youtube.com/iframe_api';
    const firstScriptTag = document.getElementsByTagName('script')[0];
    firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
    // sendResponse('ready');
    window.onYouTubeIframeAPIReady = function onYouTubeIframeAPIReady() {
      setTimeout(() => {
        sendResponse(YT); // strips methods and functions as sendResponse gets JSON serialized
      }, 0)
    }
  }
})

尝试3

我也尝试按照此答案Chrome extension - retrieving global variable from webpage

的建议将脚本注入dom。

在inject.js中,我有以下内容:

var s = document.createElement('script');
s.src = chrome.extension.getURL('./inject_scripts/youtube_api.js');
(document.head || document.documentElement).appendChild(s);
s.onload = function() {
  console.log(window.YT);
  s.remove();
};

和youtube_api.js中的

(() => {
  const tag = document.createElement('script');
  tag.src = 'https://www.youtube.com/iframe_api';
  const firstScriptTag = document.getElementsByTagName('script')[0];
  firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
  // sendResponse('ready');
  window.onYouTubeIframeAPIReady = function onYouTubeIframeAPIReady() {
    console.log('player ready'); // called as it should be
    console.log(YT); // defined as it should be

    });

    setTimeout(() => {
      const event = new CustomEvent('RW759_connectExtension', {
        detail: YT, // null
      });
      window.dispatchEvent(event);
    }, 1000);
  }
})();

以及在我的bundle.js中:

 window.addEventListener('RW759_connectExtension', function(e) {
        console.log('e.youtubeLoaded', e); // null
        console.log('window.YT', window.YT); // null
      });

我希望事件侦听器返回YT对象,但它返回为null。

如果有人有任何建议或问题,请询问:)非常感谢您的帮助

0 个答案:

没有答案