blob: aca1d6fba2f34ee8148602627114c96784444454 [file] [log] [blame]
#!/usr/bin/env python
# Copyright (c) 2012 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.
# A simple native client in python.
# All this client does is echo the text it receives back at the extension.
import argparse
import base64
import json
import os
import platform
import sys
import struct
def WriteMessage(message):
try:
sys.stdout.write(struct.pack("I", len(message)))
sys.stdout.write(message)
sys.stdout.flush()
return True
except IOError:
return False
def ParseArgs():
parser = argparse.ArgumentParser()
parser.add_argument('--parent-window', type=int)
parser.add_argument('--reconnect-command')
parser.add_argument('--native-messaging-connect-id')
parser.add_argument('origin')
return parser.parse_args()
def Main():
message_number = 0
args = ParseArgs()
caller_url = args.origin
if sys.argv[1] != args.origin:
sys.stderr.write(
"URL of the calling application is not specified as the first arg.\n")
return 1
# Verify that the process was started in the correct directory.
cwd = os.getcwd()
script_path = os.path.dirname(os.path.abspath(sys.argv[0]))
if cwd.lower() != script_path.lower():
sys.stderr.write('Native messaging host started in a wrong directory.')
return 1
# Verify that --parent-window parameter is correct.
if platform.system() == 'Windows' and args.parent_window:
import win32gui
if not win32gui.IsWindow(args.parent_window):
sys.stderr.write('Invalid --parent-window.\n')
return 1
reconnect_args = json.loads(base64.b64decode(
args.reconnect_command)) if args.reconnect_command else None
while 1:
# Read the message type (first 4 bytes).
text_length_bytes = sys.stdin.read(4)
if len(text_length_bytes) == 0:
break
# Read the message length (4 bytes).
text_length = struct.unpack('i', text_length_bytes)[0]
# Read the text (JSON object) of the message.
text = json.loads(sys.stdin.read(text_length).decode('utf-8'))
# bigMessage() test sends a special message that is sent to verify that
# chrome rejects messages that are too big. Try sending a message bigger
# than 1MB after receiving a message that contains 'bigMessageTest'.
if 'bigMessageTest' in text:
text = {"key": "x" * 1024 * 1024}
# "stopHostTest" verifies that Chrome properly handles the case when the
# host quits before port is closed. When the test receives response it
# will try sending second message and it should fail becasue the stdin
# pipe will be closed at that point.
if 'stopHostTest' in text:
# Using os.close() here because sys.stdin.close() doesn't really close
# the pipe (it just marks it as closed, but doesn't close the file
# descriptor).
os.close(sys.stdin.fileno())
WriteMessage('{"stopped": true }')
sys.exit(0)
message_number += 1
message = json.dumps({
'id': message_number, 'echo': text, 'caller_url': caller_url,
'args': reconnect_args, 'connect_id': args.native_messaging_connect_id,
}).encode('utf-8')
if not WriteMessage(message):
break
if __name__ == '__main__':
sys.exit(Main())