微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在 Chrome 扩展程序清单 v3 中,如何指示 manifest.json 在不使用 activeTab 权限的情况下仅在某些网页上运行我的扩展程序?

如何解决在 Chrome 扩展程序清单 v3 中,如何指示 manifest.json 在不使用 activeTab 权限的情况下仅在某些网页上运行我的扩展程序?

每当我将鼠标悬停在我的 ext 图标上时,我都会收到工具提示“想要访问此站点”,这是错误的,因为它应该只希望在 youtube.com/watch?v=* 上访问(这是另一个与 Manifest 匹配的故事) ' 拒绝接受 https://www.youtube.com/watch?v=* 作为有效 URL)

这是我目前正在做的:

// manifest.json

{
    "name": "YouTube Overlay","version": "0.1","manifest_version" : 3,"description": "Lays overlay on YouTube,can be used for guitar chords/lyrics.","background" : {
        "service_worker" : "bg.js"
    },"action": {},"permissions": ["activeTab","scripting"],"web_accessible_resources": [{
        "resources": ["funcsTBInsertedIntodoM.js"],"matches": ["https://www.youtube.com/*"]
    }]
}

// bg.js

chrome.action.onClicked.addListener(function (tab) {  
    chrome.scripting.executeScript({
            target: {tabId: tab.id},files: ['yt.js'],});
});

yt.js 在上面执行时,将一堆 HTML 元素和 CSS 规则注入到 DOM 中。它还将 funcsTBInsertedIntodoM.js(在上面 manifest.json 中的 web_accessible_resources 中指定)注入 DOM,其中包含注入的 HTML 按钮的函数定义。

所以基本上每当用户点击我的 ext 图标时,bg.js 就会执行,而后者又会执行 yt.js。当用户在 YouTube 视频上单击时,它工作正常。但否则它自然会在控制台中引发错误。那么我如何指示清单仅在 YouTube 视频上执行 bg.js? (它甚至不应该在其他 YouTube 页面上运行,仅当用户在视频页面上时才运行)。

此外,我收到了来自 Google Web Store 的拒绝通知,用于我的扩展程序:

Violation(s):

    Use of Permissions:

        Violation reference ID: Purple Potassium
        Violation: Requesting but not using the following permission(s):
            activeTab
        How to rectify: Remove the above permission(s)

但如果我删除 activeTab 权限,我的扩展程序根本无法使用。

如果有人能提出解决这两个问题的解决方案,我将不胜感激。感谢阅读。

添加额外代码以帮助简化:

这是 yt.ts:

// all global variables are 'var' instead of let or const because the delete command works only on var
var isFullScreen = false;
var extensionActivated = false;
var resCheckerID:number;
var chordsTALeftPaddingNonFS = chordsTALeftPaddingNonFSOnExit;
var chordsTALeftPaddingFS = "0px";
var thisIsThe1stExitAfterFS = true;

var activateExtension = () => { 
  console.log("YouTube Overlay activated.");
  let scriptElemForASBtn = document.createElement("style");
  let innardsForASBtn = styleForAsBtn;
  scriptElemForASBtn.innerHTML = innardsForASBtn;
  document.head.appendChild(scriptElemForASBtn);
  
  const videoElem = document.querySelector("video");
  const vidBottomPanel = document.querySelector(".ytp-chrome-bottom");
  const progBarPadding = document.querySelector(".ytp-progress-bar-padding");
  
  const getIdealChordsDivStyles = (isFullScreen:boolean) => {
    let vidDims = videoElem.getBoundingClientRect();
    let progBarPaddingDims = progBarPadding.getBoundingClientRect();
    if (isFullScreen){
      console.log("fullscreen detected")
      thisIsThe1stExitAfterFS = true;
      chordsTALeftPaddingNonFS = chordsTA.style.paddingLeft; // saving this for next nonFS
      chordsTA.style.paddingLeft = chordsTALeftPaddingFS; // assigning this from prev FS
      return `overflow: hidden; position: absolute; z-index: 1111; width: 100vw; height: ${progBarPaddingDims.y - vidDims.y + (progBarPaddingDims.height/2)}px`;
    } else {
      try {
        if(thisIsThe1stExitAfterFS) 
          chordsTALeftPaddingFS = chordsTA.style.paddingLeft;
          chordsTA.style.paddingLeft = chordsTALeftPaddingNonFS;
          thisIsThe1stExitAfterFS = false;
      } catch {} // saving this for next FS. on first run it obsly won't be able to find chordsTA.
      return `overflow: hidden; position: absolute; z-index: 1111; left: ${vidDims.x}px; top: ${vidDims.y}px; width: ${vidDims.width}px; height: ${progBarPaddingDims.y - vidDims.y + (progBarPaddingDims.height/2)}px`;
    }
  }
    
  
  // creating the chords div 
  let chordsDiv = document.createElement('div');
  chordsDiv.style.csstext = getIdealChordsDivStyles(isFullScreen);
  chordsDiv.setAttribute("id","chordsDiv");

  let htmlInnards = `
  <div id="chordsCtrls" onmouSEOver="unhideChordsCtrls();" onmouSEOut="hideChordsCtrls();" style="z-index: 1112; height: ${vidBottomPanel.getBoundingClientRect().height}px; position: absolute; display: inline-block;">
      <a id="asBtn" onclick="toggleAutoScroll()" class="btn-flip" data-back="Turn on" data-front="Auto-Scroll Off"></a>
      <a id="decTxtSize" class="btn noselect" onclick="decTxtSize();">Tᵀ</a>
      <a id="incTxtSize" class="btn noselect" onclick="incTxtSize();">ᵀT</a>
      <a id="decIndent" class="btn noselect" onclick="decIndent();">¶-</a>
      <a id="incIndent" class="btn noselect" onclick="incIndent();">¶+</a>

  </div>
  <textarea onkeyup="checkTAWidth();" onclick="checkTAWidth();" id="chordsTA" spellcheck="false" style="position:absolute; left:50%; transform: translate(-50%,0); white-space: pre; overflow-wrap: normal; overflow-x: scroll; font-family: Roboto Mono,monospace; background-color: rgba(0,0.35); color: white; height: 100%; min-width:10vw; font-size: ${window.screen.height*0.026}px;" placeholder="\n\nPaste\nyour\nchords/lyrics\nin\nhere!">
  `
  
  chordsDiv.innerHTML = htmlInnards;

  document.body.appendChild(chordsDiv);

  chordsTA.value = lyricsOnExit; // doing in convoluted way because i cant fig it out :S
  if (chordsTA.value === "undefined") chordsTA.value = "";
  chordsTA.scrollTop = lyricslocOnExit;
  chordsTA.style.fontSize = lyricsSizeOnExit;
  chordsTA.style.paddingLeft = chordsTALeftPaddingNonFS;
  console.log("Lyrics reinstated,if any.");

  
  // hiding the scrollbar of chords div & textarea
  let styleForScrollbarHiding = `#chordsDiv::-webkit-scrollbar,#chordsTA::-webkit-scrollbar {height: 0; width: 0;}`;
  let styleSheet = document.createElement("style");
  styleSheet.type = "text/css";
  styleSheet.innerText = styleForScrollbarHiding;
  document.head.appendChild(styleSheet);

  // auto sizing of chords div
function resCheck() {
    let vidDims = videoElem.getBoundingClientRect();
    let chordsDims = chordsDiv.getBoundingClientRect();
    let requisiteHtForChordsDiv =  vidDims.height - vidBottomPanel.getBoundingClientRect().height- (progBarPadding.getBoundingClientRect().height/2);
    if (((chordsDims.x !== vidDims.x || chordsDims.width !== vidDims.width) && chordsDims.x !== 0) || (chordsDims.x === 0 && chordsDims.x !== vidDims.x)) { // base cond's latter gets True when exiting from FS. Base's former's former checks in non fullScn mode if x or width is wrong.
      if (isFullScreen && vidDims.y === 0) return;
      console.log("Video dimensions changed detected,redrawing overlay.");
      isFullScreen = vidDims.y === 0 ? true : false;
      chordsDiv.style.csstext = getIdealChordsDivStyles(isFullScreen);
    }
  }
  resCheckerID = setInterval(resCheck,2000);

  // addding my JS functions to the youtube HTML webpage/DOM
  let s = document.createElement('script');
  // Todo: add "scriptName.js" to web_accessible_resources in manifest.json
  s.src = chrome.runtime.getURL('funcsTBInsertedIntodoM.js');
  (document.head || document.documentElement).appendChild(s);
}


var styleForAsBtn = `
#asBtn {
    opacity: 1;
    outline: 0;
    color: #FFFFFF;
    line-height: 40px;
    position: relative;
    text-align: center;
    letter-spacing: 1px;
    display: inline-block;
    text-decoration: none;
    text-transform: uppercase;
    font-size: small;
    font-weight: bold;
  }
  #asBtn:hover:after {
    opacity: 1;
    transform: translateY(0) rotateX(0);
  }
  #asBtn:hover:before {
    opacity: 0;
    transform: translateY(50%) rotateX(90deg);
  }
  #asBtn:after {
    top: 0;
    left: 0;
    opacity: 0;
    width: 100%;
    color: #000000;
    background: #BCBCBC;
    display: block;
    transition: 0.25s;
    position: absolute;
    content: attr(data-back);
    transform: translateY(-50%) rotateX(90deg);
  }
  #asBtn:before {
    top: 0;
    left: 0;
    opacity: 1;
    color: #FFFFFF;
    background: #323237;
    display: block;
    padding: 0 5px;
    line-height: 40px;
    transition: 0.25s;
    position: relative;
    content: attr(data-front);
    transform: translateY(0) rotateX(0);
  }

  /* CSS for other buttons */
  .btn{
    display: inline-block;
    color: #FFFFFF;
    width: 40px;
    height: 40px;
    line-height: 40px;
    border-radius: 50%;
    text-align: center;
    vertical-align: middle;
    overflow: hidden;
    font-weight: bold;
    background-image: -webkit-linear-gradient(#666666 0%,#323237  100%);
    background-image: linear-gradient(#666666 0%,#323237 100%);
    text-shadow: 1px 1px 1px rgba(255,255,0.66);
    Box-shadow: 0 1px 1px rgba(0,0.28);
    font-size: x-large;
    cursor: pointer;
  }
  .btn:active{
    color: #000000;
  } 
  .btn:hover {
    text-align: center;
    opacity: 1;
    background-image: -webkit-linear-gradient(#999999 0%,#323237 100%);    
    background-image: linear-gradient(#999999 0%,#323237 100%);
  }
  .noselect {
    -webkit-touch-callout: none; /* iOS Safari */
      -webkit-user-select: none; /* Safari */
      -khtml-user-select: none; /* Konqueror HTML */
        -moz-user-select: none; /* Old versions of Firefox */
          -ms-user-select: none; /* Internet Explorer/Edge */
              user-select: none; /* Non-prefixed version,currently
                                    supported by Chrome,Edge,Opera and Firefox */
  }

  #incTxtSize,#decTxtSize{
    font-size: large;
  }

  #chordsCtrls>*{
    transition: transform 0.1s linear;
  }

  textarea::placeholder {
    color: white;
    opacity: 0.8;
    font-size: 4vh;
  }

  #contentContainer.tp-yt-app-drawer[swipe-open].tp-yt-app-drawer::after{
    visibility: hidden;
  }
`
// the last css property above is hiding a thin left side vertical area which otherwise causes chordsCtrls not to show up if mouse is on extreme left. Also causes difficulty clicking SpeedDn button.

if (!document.querySelector("#chordsDiv")){
  activateExtension();
} else {
  console.log("YouTube Overlay deactivated");
  var lyricsOnExit = chordsTA.value;
  var lyricslocOnExit = chordsTA.scrollTop;
  var lyricsSizeOnExit = chordsTA.style.fontSize;
  var chordsTALeftPaddingNonFSOnExit = chordsTA.style.paddingLeft; // won't be possible to save FS padding unless i deactivate extension with an X btn. Due to scope prob.
  document.querySelector("#chordsDiv").remove();
  clearInterval(resCheckerID);
  delete window.resCheckerID;
}

这是 funcsTBInsertedIntodoM.ts:

console.log("Loading essential funcs needed for YouTube Overlay extension.")

clearInterval(asIntervalID); // cannot clear this from yt.ts because yt.ts runs in a sandBox. So need to clear it here,if it exists,on startup. Thankfully doesn't throw error even if doesn't exist.
clearTimeout(hideChordsCtrlsTimeoutID);

var asspeeds = {1: 250,2: 150,3: 100,4: 90,5: 75,6: 60,7: 50,8: 40,9: 30};

var chordsCtrls:HTMLdivelement = document.querySelector("#chordsCtrls");
var chordsTA:HTMLTextAreaElement = document.querySelector("#chordsTA");
var asBtn:HTMLButtonElement = document.querySelector("#asBtn");
var autoScrollSpeed = 250;
var asIntervalID = 0;

function toggleAutoScroll() {
    if(asIntervalID){
        clearInterval(asIntervalID);
        asIntervalID = 0;
        console.log("Stopped autoscroll.");
        document.querySelector("#speedUp").remove(); document.querySelector("#speedDn").remove();
        setAttributes(asBtn,{"data-front": `Auto-Scroll Off`,'data-back': 'Turn On'});
        return;
    }
    
    // create speed + - buttons
    let speedUp = document.createElement("a");
    speedUp.textContent = "+";
    setAttributes(speedUp,{'id': 'speedUp','class': 'btn noselect','onclick': 'speedUpAS();'});
    document.querySelector("#chordsCtrls").insertBefore(speedUp,document.querySelector("#decTxtSize"));
    let speedDn = document.createElement("a");
    speedDn.textContent = "-";
    setAttributes(speedDn,{'id': 'speedDn','onclick': 'speedDnAS();'});
    document.querySelector("#chordsCtrls").insertBefore(speedDn,asBtn);;

    setAttributes(asBtn,{"data-front": `Speed: ${getKeyByValue(asspeeds,autoScrollSpeed)}`,'data-back': 'Turn Off'});

    asIntervalID = setInterval(_=>{chordsTA.scrollBy(0,1)},autoScrollSpeed);
    console.log("Started autoscroll.")
}

var speedUpAS = () => {
    console.log("Speeding up autoscroll")
    let asBtnText = asBtn.getAttribute('data-front');
    let newSpeed:number = parseInt(asBtnText.charat(asBtnText.length - 1))+1;
    if (newSpeed in asspeeds){
        clearInterval(asIntervalID);
        autoScrollSpeed = asspeeds[newSpeed];
        asIntervalID = 0;
        asBtn.setAttribute('data-front',`Speed: ${getKeyByValue(asspeeds,autoScrollSpeed)}`);
        asIntervalID = setInterval(_=>{chordsTA.scrollBy(0,autoScrollSpeed);
    }
}

var speedDnAS = () => {
    console.log("Speeding down autoscroll")
    let asBtnText = asBtn.getAttribute('data-front');
    let newSpeed:number = parseInt(asBtnText.charat(asBtnText.length - 1))-1;
    if (newSpeed in asspeeds){
        clearInterval(asIntervalID);
        autoScrollSpeed = asspeeds[newSpeed];
        asIntervalID = 0;
        asBtn.setAttribute('data-front',autoScrollSpeed);
    }
}  

var incTxtSize = () => {
    let currFontSize = parseFloat(chordsTA.style.fontSize);
    let newFontSize = currFontSize += 1;
    chordsTA.style.fontSize = `${newFontSize}px`;
    qickSizeUp();
}

var decTxtSize = () => {
    let currFontSize = parseFloat(chordsTA.style.fontSize);
    let newFontSize = currFontSize -= 1;
    chordsTA.style.fontSize = `${newFontSize}px`;
    qickSizedn();
}

var unhideChordsCtrls = () => {
    clearTimeout(hideChordsCtrlsTimeoutID);
    let childrenOfchordsCtrlsDiv:any = chordsCtrls.getElementsByTagName("*");
    for (let index = 0; index < childrenOfchordsCtrlsDiv.length; index++) {
        childrenOfchordsCtrlsDiv[index].style.transform = "translate(0,0)";
    }
}

var hideChordsCtrlsTimeoutID = 0;
var hideChordsCtrls = () => {
    hideChordsCtrlsTimeoutID = setTimeout(() => {        
        let childrenOfchordsCtrlsDiv:any = chordsCtrls.getElementsByTagName("*");
        for (let index = 0; index < childrenOfchordsCtrlsDiv.length; index++) {
            childrenOfchordsCtrlsDiv[index].style.transform = "translate(0,-100%)";
        }
    },2000);
}

hideChordsCtrlsTimeoutID = setTimeout(() => { //hide the controls after initially showing them for 4 secs
    hideChordsCtrls();
},4000);

var decIndent = () => {
    let newLeftPadding = (parseInt(chordsTA.style.paddingLeft) - 50);
    if (!newLeftPadding) newLeftPadding = 0; // this catches NaN on first run,as it is not set. Also doesn't allow to go less than 0 somehow,luckily.
    chordsTA.style.paddingLeft = `${newLeftPadding}px`;
}

var incIndent = () => {
    let newLeftPadding = (parseInt(chordsTA.style.paddingLeft) + 50);
    if (!newLeftPadding) newLeftPadding = 50; // this catches NaN on first run,as it is not set. 
    if (newLeftPadding > document.querySelector("#chordsDiv").getBoundingClientRect().width) return;
    chordsTA.style.paddingLeft = `${newLeftPadding}px`;
}

// following funcs stolen from SO for finding a key by its value & setting attributes multiple at a time.
function getKeyByValue(object:object,value:Number) {
    return Object.keys(object).find(key => object[key] === value);
  }

function setAttributes(el:HTMLElement,attrs:object) {
    for(var key in attrs) {
        el.setAttribute(key,attrs[key]);
}
}

或者您可能更喜欢在 GitHub 上阅读代码https://github.com/XtremePwnership/YoutubeOverlay

解决方法

由于 YouTube 视频页面托管在 youtube.com/watch,因此可以在清单中指定:

{
    "name": "YouTube Overlay","version": "0.1","manifest_version" : 3,"description": "Lays overlay on YouTube,can be used for guitar chords/lyrics.","background" : {
        "service_worker" : "bg.js"
    },"action": {},"permissions": ["activeTab","scripting"],"web_accessible_resources": [{
        "resources": ["funcsTBInsertedIntoDOM.js"],"matches": ["https://www.youtube.com/watch?v=*"]
    }]
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?