2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
6 # A simple native messaging host. Shows a Tkinter dialog with incoming messages
7 # that also allows to send message back to the webapp.
20 # Helper function that sends a message to the webapp.
21 def send_message(message):
23 sys.stdout.write(struct.pack('I', len(message)))
24 # Write the message itself.
25 sys.stdout.write(message)
28 # Thread that reads messages from the webapp.
29 def read_thread_func(queue):
32 # Read the message type (first 4 bytes).
33 text_length_bytes = sys.stdin.read(4)
35 if len(text_length_bytes) == 0:
40 # Read the message length (4 bytes).
41 text_length = struct.unpack('i', text_length_bytes)[0]
43 # Read the text (JSON object) of the message.
44 text = sys.stdin.read(text_length).decode('utf-8')
49 # In headless mode just send an echo message back.
50 send_message('{"echo": %s}' % text)
53 class NativeMessagingWindow(Tkinter.Frame):
54 def __init__(self, queue):
57 Tkinter.Frame.__init__(self)
60 self.text = Tkinter.Text(self)
61 self.text.grid(row=0, column=0, padx=10, pady=10, columnspan=2)
62 self.text.config(state=Tkinter.DISABLED, height=10, width=40)
64 self.messageContent = Tkinter.StringVar()
65 self.sendEntry = Tkinter.Entry(self, textvariable=self.messageContent)
66 self.sendEntry.grid(row=1, column=0, padx=10, pady=10)
68 self.sendButton = Tkinter.Button(self, text="Send", command=self.onSend)
69 self.sendButton.grid(row=1, column=1, padx=10, pady=10)
71 self.after(100, self.processMessages)
73 def processMessages(self):
74 while not self.queue.empty():
75 message = self.queue.get_nowait()
79 self.log("Received %s" % message)
81 self.after(100, self.processMessages)
84 text = '{"text": "' + self.messageContent.get() + '"}'
85 self.log('Sending %s' % text)
89 tkMessageBox.showinfo('Native Messaging Example',
90 'Failed to send message.')
93 def log(self, message):
94 self.text.config(state=Tkinter.NORMAL)
95 self.text.insert(Tkinter.END, message + "\n")
96 self.text.config(state=Tkinter.DISABLED)
101 send_message('"Tkinter python module wasn\'t found. Running in headless ' +
102 'mode. Please consider installing Tkinter."')
103 read_thread_func(None)
106 queue = Queue.Queue()
108 main_window = NativeMessagingWindow(queue)
109 main_window.master.title('Native Messaging Example')
111 thread = threading.Thread(target=read_thread_func, args=(queue,))
115 main_window.mainloop()
120 if __name__ == '__main__':