[英]Chrome Extension NativeMessaging 'connectNative' undefined
I am trying to implement a chrome extension using runtime.connectNative and postMessage.我正在尝试使用 runtime.connectNative 和 postMessage 实现一个 chrome 扩展。 I am following the chrome documentation , downloaded the native messaging example which I'm trying to run without any changes, while the code for the native host application can be found here .
我正在关注chrome 文档,下载了我试图在没有任何更改的情况下运行的本机消息传递示例,而本机主机应用程序的代码可以在这里找到。
However, I'm getting the error: Uncaught TypeError: Cannot read property 'connectNative' of undefined.但是,我收到错误:未捕获的类型错误:无法读取未定义的属性“connectNative”。
The error is being triggered from the javascript extension file, in this line:错误是从 javascript 扩展文件触发的,在这一行:
port = chrome.runtime.connectNative(hostName);端口 = chrome.runtime.connectNative(hostName);
while the extension is being loaded from the manifest like so:当从清单加载扩展时,如下所示:
"app": {
"launch": {
"local_path": "main.html"
}
}
Any ideas how to solve the problem please?任何想法如何解决问题?
Chrome version 34, tested on windows 7, 8.1 Chrome 版本 34,在 Windows 7、8.1 上测试
The immediate problem is that you are not running the sample code correctly.直接的问题是您没有正确运行示例代码。 The larger problem is that Google has not provided comprehensive documentation on how to use this sample code.
更大的问题是谷歌没有提供关于如何使用这个示例代码的全面文档。
The Native Messaging example you referenced only links to the sample code for the Chrome extension.您引用的本机消息传递示例仅链接到 Chrome 扩展程序的示例代码。 After searching around I was able to find related sample code for the native messaging host application.
四处搜索后,我找到了本机消息传递主机应用程序的相关示例代码。 To get the sample code for both the Chrome extension and native messaging host application together you'll want to download nativeMessaging.zip .
要同时获取 Chrome 扩展程序和本机消息传递主机应用程序的示例代码,您需要下载nativeMessaging.zip 。 In that zip file you'll also find some brief instructions on how to install the native messaging host on Windows, Linux and Mac OS X. I'll tell you right now that the instructions are incomplete as they do not tell you how to install the Chrome extension.
在该 zip 文件中,您还会找到一些关于如何在 Windows、Linux 和 Mac OS X 上安装本机消息传递主机的简要说明。我现在告诉您这些说明不完整,因为它们没有告诉您如何安装Chrome 扩展程序。 Additionally the scripts for installing and uninstalling the native messaging host do not work as-is on OS X. See below for my installation instructions and corrected scripts.
此外,用于安装和卸载本机消息传递主机的脚本在 OS X 上无法按原样运行。有关我的安装说明和更正脚本,请参见下文。
How to install the sample extension and native host application如何安装示例扩展和本机主机应用程序
chrome://extensions/
in the address barchrome://extensions/
nativeMessaging
directory and select the app
directory for importnativeMessaging
目录并选择要导入的app
目录chmod a+rx nativeMessaging/host/install_host.sh nativeMessaging/host/native-messaging-example-host nativeMessaging/host/uninstall_host.sh
chmod a+rx nativeMessaging/host/install_host.sh nativeMessaging/host/native-messaging-example-host nativeMessaging/host/uninstall_host.sh
nativeMessaging/host/install_host.sh
and nativeMessaging/host/uninstall_host.sh
.nativeMessaging/host/install_host.sh
和nativeMessaging/host/uninstall_host.sh
一些错误。 See below for the corrected scripts.nativeMessaging/README.txt
nativeMessaging/README.txt
的说明进行nativeMessaging/README.txt
chrome://apps/
in the address barchrome://apps/
Corrected nativeMessaging/host/install_host.sh
更正了
nativeMessaging/host/install_host.sh
#!/bin/sh
# Copyright 2013 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
set -e
DIR="$( cd "$( dirname "$0" )" && pwd )"
if [ $(uname -s) == 'Darwin' ]; then
if [ "$(whoami)" == "root" ]; then
TARGET_DIR="/Library/Google/Chrome/NativeMessagingHosts"
else
TARGET_DIR="$HOME/Library/Application Support/Google/Chrome/NativeMessagingHosts"
fi
else
if [ "$(whoami)" == "root" ]; then
TARGET_DIR="/etc/opt/chrome/native-messaging-hosts"
else
TARGET_DIR="$HOME/.config/google-chrome/NativeMessagingHosts"
fi
fi
HOST_NAME=com.google.chrome.example.echo
# Create directory to store native messaging host.
mkdir -p "$TARGET_DIR"
# Copy native messaging host manifest.
cp "$DIR/$HOST_NAME.json" "$TARGET_DIR"
# Update host path in the manifest.
HOST_PATH="$DIR/native-messaging-example-host"
ESCAPED_HOST_PATH=${HOST_PATH////\\/}
sed -i -e "s/HOST_PATH/$ESCAPED_HOST_PATH/" "$TARGET_DIR/$HOST_NAME.json"
# Set permissions for the manifest so that all users can read it.
chmod o+r "$TARGET_DIR/$HOST_NAME.json"
echo Native messaging host $HOST_NAME has been installed.
Corrected nativeMessaging/host/uninstall_host.sh
更正了
nativeMessaging/host/uninstall_host.sh
#!/bin/sh
# Copyright 2013 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
set -e
if [ $(uname -s) == 'Darwin' ]; then
if [ "$(whoami)" == "root" ]; then
TARGET_DIR="/Library/Google/Chrome/NativeMessagingHosts"
else
TARGET_DIR="$HOME/Library/Application Support/Google/Chrome/NativeMessagingHosts"
fi
else
if [ "$(whoami)" == "root" ]; then
TARGET_DIR="/etc/opt/chrome/native-messaging-hosts"
else
TARGET_DIR="$HOME/.config/google-chrome/NativeMessagingHosts"
fi
fi
HOST_NAME=com.google.chrome.example.echo
rm "$TARGET_DIR/com.google.chrome.example.echo.json"
echo Native messaging host $HOST_NAME has been uninstalled.
I would like to provide a python 3 version of the script to replace native-messaging-example-host .我想提供一个 python 3 版本的脚本来替换native-messaging-example-host 。 It is tested with Chrome v86 and works as expected.
它已使用 Chrome v86 进行测试并按预期工作。 Note that python kernel crashes when tkinter window is closed - this is because of binary data exchange inside threading which causes thread to be hard locked (more info here ).
请注意,当 tkinter 窗口关闭时,python 内核会崩溃 - 这是因为线程内部的二进制数据交换导致线程被硬锁定(更多信息在这里)。 I added a command exit to be send from chrome app to stop thread's waiting for another stdin.
我添加了一个从 chrome 应用程序发送的命令退出,以停止线程等待另一个标准输入。 After receiving it, python won't crash on exit.
收到后,python 不会在退出时崩溃。
Python 3 version (tested with 3.7.4): Python 3 版本(使用 3.7.4 测试):
# A simple native messaging host. Shows a Tkinter dialog with incoming messages
# that also allows to send message back to the webapp.
import struct
import sys
import threading
import queue as Queue
try:
import tkinter as Tkinter
import tkinter.messagebox
except ImportError:
Tkinter = None
# On Windows, the default I/O mode is O_TEXT. Set this to O_BINARY
# to avoid unwanted modifications of the input/output streams.
if sys.platform == "win32":
import os, msvcrt
msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
# Helper function that sends a message to the webapp.
def send_message(message):
# Write message size.
sys.stdout.buffer.write(struct.pack('I', len(message)))
# Write the message itself.
sys.stdout.write(message)
sys.stdout.flush()
# Thread that reads messages from the webapp.
def read_thread_func(queue):
message_number = 0
while 1:
# Read the message length (first 4 bytes).
text_length_bytes = sys.stdin.buffer.read(4)
if len(text_length_bytes) == 0:
if queue:
queue.put(None)
sys.exit(0)
# Unpack message length as 4 byte integer.
text_length = struct.unpack('@I', text_length_bytes)[0]
# Read the text (JSON object) of the message.
text = sys.stdin.buffer.read(text_length).decode('utf-8')
if text == '{"text":"exit"}':
break
if queue:
queue.put(text)
else:
# In headless mode just send an echo message back.
send_message('{"echo": %s}' % text)
if Tkinter:
class NativeMessagingWindow(tkinter.Frame):
def __init__(self, queue):
self.queue = queue
tkinter.Frame.__init__(self)
self.pack()
self.text = tkinter.Text(self)
self.text.grid(row=0, column=0, padx=10, pady=10, columnspan=2)
self.text.config(state=tkinter.DISABLED, height=10, width=40)
self.messageContent = tkinter.StringVar()
self.sendEntry = tkinter.Entry(self, textvariable=self.messageContent)
self.sendEntry.grid(row=1, column=0, padx=10, pady=10)
self.sendButton = tkinter.Button(self, text="Send", command=self.onSend)
self.sendButton.grid(row=1, column=1, padx=10, pady=10)
self.after(100, self.processMessages)
def processMessages(self):
while not self.queue.empty():
message = self.queue.get_nowait()
if message == None:
self.quit()
return
self.log("Received %s" % message)
self.after(100, self.processMessages)
def onSend(self):
text = '{"text": "' + self.messageContent.get() + '"}'
self.log('Sending %s' % text)
try:
send_message(text)
except IOError:
tkinter.messagebox.showinfo('Native Messaging Example',
'Failed to send message.')
sys.exit(1)
def log(self, message):
self.text.config(state=tkinter.NORMAL)
self.text.insert(tkinter.END, message + "\n")
self.text.config(state=tkinter.DISABLED)
def Main():
if not Tkinter:
send_message('"Tkinter python module wasn\'t found. Running in headless ' +
'mode. Please consider installing Tkinter."')
read_thread_func(None)
sys.exit(0)
queue = Queue.Queue()
main_window = NativeMessagingWindow(queue)
main_window.master.title('Native Messaging Example')
thread = threading.Thread(target=read_thread_func, args=(queue,))
thread.daemon = True
thread.start()
main_window.mainloop()
sys.exit(0)
if __name__ == '__main__':
Main()
Disclaimer: I used 2to3 utility for initial conversion to python 3. I also adopted changes from a webextensions (firefox) version of the nativeMessage API example (it is simplified and not using tkinter gui).免责声明:我使用2to3实用程序初始转换为 python 3。我还采用了webextensions (firefox) 版本的 nativeMessage API 示例的更改(它已简化且不使用 tkinter gui)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.