我正在尝试开发将在youtube.com上运行的Chrome扩展程序,因此我需要访问iframe播放器api。 我本来以为是跨源问题,但源是youtube.com,所以不确定是不是这个问题。
恼人的是,另一个名为TubeBuddy的扩展似乎完全可以满足我的要求,所以我知道这是可能的!
尝试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。
如果有人有任何建议或问题,请询问:)非常感谢您的帮助