Chrome Extension Nativemessaging 'connectnative' Undefined
Solution 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. 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. 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. 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.
How to install the sample extension and native host application
- Download and unzip the nativeMessaging.zip file.
- Install the Chrome extension
- In Chrome enter
chrome://extensions/
in the address bar - Click the “Load unpacked extension...” button
- Navigate to the unzipped
nativeMessaging
directory and select theapp
directory for import
- In Chrome enter
- Install the native messaging host application
- For OS X and Linux you’ll need to add execute permission to some of the files. Run the command:
chmod a+rx nativeMessaging/host/install_host.sh nativeMessaging/host/native-messaging-example-host nativeMessaging/host/uninstall_host.sh
- For OS X you’ll need to fix some bugs in
nativeMessaging/host/install_host.sh
andnativeMessaging/host/uninstall_host.sh
. See below for the corrected scripts. - For OS X, Linux and Windows follow the instructions in
nativeMessaging/README.txt
- For OS X and Linux you’ll need to add execute permission to some of the files. Run the command:
- Run the Chrome extension
- In Chrome enter
chrome://apps/
in the address bar - Click on the Native Messaging Example app icon
- After the app loads you should see a single button named “Connect.” Click that button and you should see the native messaging host application launch automatically.
- In Chrome enter
Corrected 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' ]; thenif [ "$(whoami)" == "root" ]; then
TARGET_DIR="/Library/Google/Chrome/NativeMessagingHosts"else
TARGET_DIR="$HOME/Library/Application Support/Google/Chrome/NativeMessagingHosts"fielseif [ "$(whoami)" == "root" ]; then
TARGET_DIR="/etc/opt/chrome/native-messaging-hosts"else
TARGET_DIR="$HOME/.config/google-chrome/NativeMessagingHosts"fifi
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
#!/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' ]; thenif [ "$(whoami)" == "root" ]; then
TARGET_DIR="/Library/Google/Chrome/NativeMessagingHosts"else
TARGET_DIR="$HOME/Library/Application Support/Google/Chrome/NativeMessagingHosts"fielseif [ "$(whoami)" == "root" ]; then
TARGET_DIR="/etc/opt/chrome/native-messaging-hosts"else
TARGET_DIR="$HOME/.config/google-chrome/NativeMessagingHosts"fifi
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.
Solution 2:
I would like to provide a python 3 version of the script to replace native-messaging-example-host. It is tested with Chrome v86 and works as expected. 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). I added a command exit to be send from chrome app to stop thread's waiting for another stdin. After receiving it, python won't crash on exit.
Python 3 version (tested with 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.defsend_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.defread_thread_func(queue):
message_number = 0while1:
# Read the message length (first 4 bytes).
text_length_bytes = sys.stdin.buffer.read(4)
iflen(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"}':
breakif queue:
queue.put(text)
else:
# In headless mode just send an echo message back.
send_message('{"echo": %s}' % text)
if Tkinter:
classNativeMessagingWindow(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)
defprocessMessages(self):
whilenot self.queue.empty():
message = self.queue.get_nowait()
if message == None:
self.quit()
return
self.log("Received %s" % message)
self.after(100, self.processMessages)
defonSend(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)
deflog(self, message):
self.text.config(state=tkinter.NORMAL)
self.text.insert(tkinter.END, message + "\n")
self.text.config(state=tkinter.DISABLED)
defMain():
ifnot 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).
Post a Comment for "Chrome Extension Nativemessaging 'connectnative' Undefined"