Проблема с использованием YouTube iframe APi в расширении Chrome - PullRequest
0 голосов
/ 26 марта 2019

Я пытаюсь разработать расширение для Chrome, которое будет работать на youtube.com, и поэтому мне нужен доступ к API-интерфейсу плеера iframe. Сначала я думал, что это проблема перекрестного происхождения, но источником является youtube.com, поэтому я не уверен, что это проблема.

раздражает то, что другое расширение под названием TubeBuddy, кажется, делает именно то, что я хочу, поэтому я знаю, что это возможно!

TubeBuddy Iframe API

Попытка 1 Я попытался внедрить API-интерфейс iframe YouTube, как показано в документации здесь: 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
          }
        });
      };

Я могу заметить, что тег script создается в DOM на странице, но никогда не вызывается window.onYoutubeIframeAPIReady, что, как я полагаю, связано с тем, что расширение chrome не имеет доступа к объекту окна.

Я пытался следовать этим ответам, но безрезультатно:

API проигрывателя Youtube в расширении Chrome

YouTube видео в расширении Chrome сценарий содержания

Обнаружение видео-событий на YouTube с помощью скрипта с расширением Chrome

API iframe для YouTube: OnReady не запускает расширение Chrome

Попытка 2 Я пытался использовать API sendMessage для внедрения объекта YT в content_scripts, но это не работает, так как обратный вызов sendResponse лишает методы и функции из-за сериализации JSON.

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

Я также попытался внедрить скрипт в dom, как это предлагается в этом ответе Расширение Chrome - получение глобальной переменной со страницы

В 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, но он будет возвращен как ноль.

Если у кого-то есть предложения или вопросы, пожалуйста, задавайте :) Буду очень признателен за помощь с этим

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...