Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/391.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 从网页向chrome扩展发送消息_Javascript_Reactjs_Google Chrome Extension_React Typescript - Fatal编程技术网

Javascript 从网页向chrome扩展发送消息

Javascript 从网页向chrome扩展发送消息,javascript,reactjs,google-chrome-extension,react-typescript,Javascript,Reactjs,Google Chrome Extension,React Typescript,我希望能够将一条消息从我的web应用发送到我的chrome扩展,这样它就更容易使用(发送身份验证令牌,这样用户就不必登录两次)。然而,在看了这本书并阅读了一大堆这样的问题之后,我无法得到任何适合我的东西 下面是我的manifest.json的一些部分: "content_security_policy": "script-src 'self' https://330218550995.ngrok.io; object-src 'self'", "

我希望能够将一条消息从我的web应用发送到我的chrome扩展,这样它就更容易使用(发送身份验证令牌,这样用户就不必登录两次)。然而,在看了这本书并阅读了一大堆这样的问题之后,我无法得到任何适合我的东西

下面是我的
manifest.json
的一些部分:

"content_security_policy": "script-src 'self' https://330218550995.ngrok.io; object-src 'self'",
"background": {
    "scripts": ["background.js"],
    "persistent": false
},
"externally_connectable": {
    "matches": [
        "*://localhost/*",
        "*://*.ngrok.io/*"
    ]
},
"content_scripts": [
  {
    "matches": ["<all_urls>"],
    "exclude_matches": [
      "*://*.olympiatasks.com/*",
      "https://app.olympiatasks.com/*",
      "https://*.olympiatasks.com/*"
  ],
    "css": ["/static/css/main.css"],
    "js": [
      "/static/js/runtime-main.js", 
      "/static/js/2.js", 
      "/static/js/main.js"
    ]
  }
],
网页的内部
我执行以下操作:

const ExtensionID = process.env.REACT_APP_EXTENSION_ID || '';
chrome?.runtime.connect(ExtensionID, { name: 'example' });
chrome?.runtime?.sendMessage('Hi from content script')
const ExtensionID = process.env.REACT_APP_EXTENSION_ID || "";
chrome.runtime.connect(ExtensionID, { name: "example" });
chrome?.runtime?.sendMessage(ExtensionID, "Hi from app");
下面是
background.js
中的侦听器:

chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
    console.log({ request })
});

chrome.runtime.onMessageExternal.addListener((request, sender, sendResponse) => {
    console.log("Received message from " + sender + ": ", request);
    sendResponse({ received: true }); //respond however you like
});
当我打开网站时,扩展被成功注入,在
background.js
页面的开发控制台中,我得到以下信息:

Hello world from background.js

{请求:“来自内容脚本的Hi”}

“hi from app”丢失,这意味着它没有被发送/接收。我使用
ngrok
设置转发到我的应用程序,认为:

  • 正在运行的域
    localhost
  • 该协议不是
    https
可能是个问题,但正如你猜的那样,运气不好

到目前为止,我已经做了以下工作:

  • 在my
    manifest.json中设置my
    External\u connectable
  • background.js
  • 调用
    runtime.sendMessage
    ,扩展ID如图所示
  • 使用
    https
    网站进行安全连接

非常感谢您在这个问题上提供的任何帮助

我们可以使用内容脚本和后台js文件在网站和chrome扩展之间同步身份验证令牌

网页内
我这样做

我不知道你是怎么在
网页上做的

下面是我如何将访问令牌从
网页
发送到
扩展

这是我的
内容脚本
文件

/* eslint-disable no-undef */

const hostScript = () => {
  // ----------------- Function Declarations -----------------

  let listenGetTokenResponseFromWindow = () => {};

  const sendMessagesToExtension = (msg, callback = null) => {
    chrome.runtime.sendMessage(msg);
  };

  const sendMessagesToWindow = (msg, callback = null) => {
    const { type } = msg;
    
    switch (type) {
      case ExtensionMessagesTypes.GetTokenFromWindow:
        // Can not pass the function with window.postMessage. Only JSON object can be passed.
        // So reset the listener
        window.postMessage(msg, document.location.origin);

        window.removeEventListener("message", listenGetTokenResponseFromWindow);
        listenGetTokenResponseFromWindow = event => {
          if (event.source !== window) return;
          if (event.data.type === ExtensionMessagesTypes.GetTokenFromWindowResponse) {
            const { payload } = event.data;
            !!callback && callback(payload.token);
          }
        };
        window.addEventListener("message", listenGetTokenResponseFromWindow);
        break;
      case ExtensionMessagesTypes.SetWindowToken:
        window.postMessage(msg, document.location.origin);
        !!callback && callback();
        break;
      default:
        break;
    }
  };

  const listenMessagesFromWindow = event => {
    if (event.source !== window) return;

    const msg = event.data;
    
    Object.values(ExtensionMessagesTypes).includes(msg.type) && sendMessagesToExtension(msg);
  };

  const listenMessagesFromExtension = (msg, sender, response) => {
    sendMessagesToWindow(msg, response);
    return true; // means response is async
  };

  // ----------------- Listener Definitions -----------------

  window.removeEventListener("message", listenMessagesFromWindow);
  window.addEventListener("message", listenMessagesFromWindow);

  chrome.runtime.onMessage.removeListener(listenMessagesFromExtension);
  chrome.runtime.onMessage.addListener(listenMessagesFromExtension);

  // Reset extension token as windows token
  sendMessagesToWindow({ type: ExtensionMessagesTypes.GetTokenFromWindow }, token => {
    sendMessagesToExtension({
      type: ExtensionMessagesTypes.SetExtensionToken,
      payload: { token }
    });
  });
};
(() => {
        chrome.runtime.onMessage.addListener((msg, sender, response) => {
            switch (msg.type) {
                case ExtensionMessagesTypes.GetTokens:
                    getAccessTokens(response);
                    break;
                case ExtensionMessagesTypes.SetExtensionToken:
                    !!msg.payload && !!msg.payload.token && setAccessTokenToExtensionLocalStorage(msg.payload.token, response);
                    break;
                case ExtensionMessagesTypes.SetWindowToken:
                    !!msg.payload && !!msg.payload.token && sendMessageFromExtensionToWindow(msg, response);
                    break;
            }
    });
})();

const sendMessageFromExtensionToWindow = (msg, callback = null) => {
    chrome.tabs.query({ currentWindow: true, url: `${HostURL}/*` }, tabs => {
        if (tabs.length < 1) {
            !!callback && callback(null);
            return;
        }

        if (msg.type === ExtensionMessagesTypes.GetTokenFromWindow) {
            chrome.tabs.sendMessage(tabs[0].id, msg, token => {
                !!callback && callback(token);
            });
        } else if (msg.type === ExtensionMessagesTypes.SetWindowToken) {
            chrome.tabs.sendMessage(tabs[0].id, msg, () => {
                !!callback && callback();
            });
        }
    });
};

// Authentication

const setAccessTokenToExtensionLocalStorage = (access_token, callback = null) => {
    chrome.storage.local.set({ access_token }, () => {
        !!callback && callback();
    });
};

const getAccessTokenFromChromeStorage = callback => {
    chrome.storage.local.get(['access_token'], result => {
        !!callback && callback(result.access_token);
    });
};

const getAccessTokens = callback => {
    getAccessTokenFromChromeStorage(accessTokenFromExtension => {
        sendMessageFromExtensionToWindow({ type: ExtensionMessagesTypes.GetTokenFromWindow }, accessTokenFromWindow => {
            callback({
                accessTokenFromExtension: accessTokenFromExtension || '',
                accessTokenFromWindow: accessTokenFromWindow || ''
            });
        });
    });
};

const handleLogin = payload => {
    //TODO: Handling refresh token
    
    const { token } = payload;
    if (!token) return;

    setAccessTokenToExtensionLocalStorage(token);
};

const handleLogout = () => {
    setAccessTokenToExtensionLocalStorage(null);
};
这是
background.js
文件

/* eslint-disable no-undef */

const hostScript = () => {
  // ----------------- Function Declarations -----------------

  let listenGetTokenResponseFromWindow = () => {};

  const sendMessagesToExtension = (msg, callback = null) => {
    chrome.runtime.sendMessage(msg);
  };

  const sendMessagesToWindow = (msg, callback = null) => {
    const { type } = msg;
    
    switch (type) {
      case ExtensionMessagesTypes.GetTokenFromWindow:
        // Can not pass the function with window.postMessage. Only JSON object can be passed.
        // So reset the listener
        window.postMessage(msg, document.location.origin);

        window.removeEventListener("message", listenGetTokenResponseFromWindow);
        listenGetTokenResponseFromWindow = event => {
          if (event.source !== window) return;
          if (event.data.type === ExtensionMessagesTypes.GetTokenFromWindowResponse) {
            const { payload } = event.data;
            !!callback && callback(payload.token);
          }
        };
        window.addEventListener("message", listenGetTokenResponseFromWindow);
        break;
      case ExtensionMessagesTypes.SetWindowToken:
        window.postMessage(msg, document.location.origin);
        !!callback && callback();
        break;
      default:
        break;
    }
  };

  const listenMessagesFromWindow = event => {
    if (event.source !== window) return;

    const msg = event.data;
    
    Object.values(ExtensionMessagesTypes).includes(msg.type) && sendMessagesToExtension(msg);
  };

  const listenMessagesFromExtension = (msg, sender, response) => {
    sendMessagesToWindow(msg, response);
    return true; // means response is async
  };

  // ----------------- Listener Definitions -----------------

  window.removeEventListener("message", listenMessagesFromWindow);
  window.addEventListener("message", listenMessagesFromWindow);

  chrome.runtime.onMessage.removeListener(listenMessagesFromExtension);
  chrome.runtime.onMessage.addListener(listenMessagesFromExtension);

  // Reset extension token as windows token
  sendMessagesToWindow({ type: ExtensionMessagesTypes.GetTokenFromWindow }, token => {
    sendMessagesToExtension({
      type: ExtensionMessagesTypes.SetExtensionToken,
      payload: { token }
    });
  });
};
(() => {
        chrome.runtime.onMessage.addListener((msg, sender, response) => {
            switch (msg.type) {
                case ExtensionMessagesTypes.GetTokens:
                    getAccessTokens(response);
                    break;
                case ExtensionMessagesTypes.SetExtensionToken:
                    !!msg.payload && !!msg.payload.token && setAccessTokenToExtensionLocalStorage(msg.payload.token, response);
                    break;
                case ExtensionMessagesTypes.SetWindowToken:
                    !!msg.payload && !!msg.payload.token && sendMessageFromExtensionToWindow(msg, response);
                    break;
            }
    });
})();

const sendMessageFromExtensionToWindow = (msg, callback = null) => {
    chrome.tabs.query({ currentWindow: true, url: `${HostURL}/*` }, tabs => {
        if (tabs.length < 1) {
            !!callback && callback(null);
            return;
        }

        if (msg.type === ExtensionMessagesTypes.GetTokenFromWindow) {
            chrome.tabs.sendMessage(tabs[0].id, msg, token => {
                !!callback && callback(token);
            });
        } else if (msg.type === ExtensionMessagesTypes.SetWindowToken) {
            chrome.tabs.sendMessage(tabs[0].id, msg, () => {
                !!callback && callback();
            });
        }
    });
};

// Authentication

const setAccessTokenToExtensionLocalStorage = (access_token, callback = null) => {
    chrome.storage.local.set({ access_token }, () => {
        !!callback && callback();
    });
};

const getAccessTokenFromChromeStorage = callback => {
    chrome.storage.local.get(['access_token'], result => {
        !!callback && callback(result.access_token);
    });
};

const getAccessTokens = callback => {
    getAccessTokenFromChromeStorage(accessTokenFromExtension => {
        sendMessageFromExtensionToWindow({ type: ExtensionMessagesTypes.GetTokenFromWindow }, accessTokenFromWindow => {
            callback({
                accessTokenFromExtension: accessTokenFromExtension || '',
                accessTokenFromWindow: accessTokenFromWindow || ''
            });
        });
    });
};

const handleLogin = payload => {
    //TODO: Handling refresh token
    
    const { token } = payload;
    if (!token) return;

    setAccessTokenToExtensionLocalStorage(token);
};

const handleLogout = () => {
    setAccessTokenToExtensionLocalStorage(null);
};
(()=>{
chrome.runtime.onMessage.addListener((消息、发送者、响应)=>{
开关(消息类型){
案例扩展MessageTypes.GetTokens:
getAccessTokens(响应);
打破
案例扩展MessageTypes.SetExtensionToken:
!!msg.payload&!!msg.payload.token&&setAccessTokenToExtensionLocalStorage(msg.payload.token,响应);
打破
案例扩展MessageTypes.SetWindowToken:
!!msg.payload&!!msg.payload.token&&sendMessageFromExtensionWindow(msg,响应);
打破
}
});
})();
const sendMessageFromExtensionWindow=(消息,回调=null)=>{
chrome.tabs.query({currentWindow:true,url:`${HostURL}/*`},tabs=>{
如果(制表符长度<1){
!!回调和回调(null);
返回;
}
if(msg.type==extensionMessageTypes.GetTokenFromWindow){
chrome.tabs.sendMessage(制表符[0]。id、消息、令牌=>{
!!回拨和回拨(令牌);
});
}else if(msg.type==extensionMessageTypes.SetWindowToken){
chrome.tabs.sendMessage(tabs[0].id,msg,()=>{
!!回调和回调();
});
}
});
};
//认证
const setAccessTokenToExtensionLocalStorage=(访问令牌,回调=null)=>{
chrome.storage.local.set({access\u token},()=>{
!!回调和回调();
});
};
const getAccessTokenFromChromeStorage=回调=>{
chrome.storage.local.get(['access\u token',result=>{
!!回调和回调(result.access\u令牌);
});
};
const getAccessTokens=回调=>{
getAccessTokenFromChromeStorage(accessTokenFromExtension=>{
SendMessageFromExtensionWindow({type:ExtensionMessagesTypes.GetTokenFromWindow},accessTokenFromWindow=>{
回拨({
accessTokenFromExtension:accessTokenFromExtension | |“”,
accessTokenFromWindow:accessTokenFromWindow | |“”
});
});
});
};
const handleLogin=有效负载=>{
//TODO:处理刷新令牌
const{token}=有效载荷;
如果(!token)返回;
setAccessTokenToExtensionLocalStorage(令牌);
};
常量handleLogout=()=>{
setAccessTokenToExtensionLocalStorage(null);
};

PS:您不需要manifest.json文件中的
外部可连接
选项。

多亏@wOxxOm注释,我才能够解决这个问题

我引述:


暂时来说,由于ngrok.io在其中,这意味着它基本上类似于com,在外部可连接中是禁止的。尝试为站点使用更具体的模式


我更改了URL以使用更具体的
https://330218550995.ngrok.io/*
现在它暂时可以工作了

,因为ngrok.io在其中,这意味着它基本上类似于
com
,在外部可连接中是禁止的。尝试对站点使用更具体的模式。这是为了在
内容脚本
背景脚本
之间进行通信,但我的JWT令牌来自web应用程序,我想从web应用程序发送到
背景脚本