#!/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 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 Main():
  message_number = 0

  caller_url = None
  parent_window = None

  if len(sys.argv) < 2:
    sys.stderr.write("URL of the calling application is not specified.\n")
    return 1
  # TODO(sergeyu): Use argparse module to parse the arguments (not available in
  # Python 2.6).
  for arg in sys.argv[1:]:
    if arg.startswith('--'):
      if arg.startswith('--parent-window='):
        parent_window = long(arg[len('--parent-window='):])
    elif caller_url == None:
      caller_url = arg

  if platform.system() == 'Windows':
    import win32gui
    if parent_window and not win32gui.IsWindow(parent_window):
      sys.stderr.write('Invalid --parent-window.\n')
      return 1

  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 = 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 = '{{"id": {0}, "echo": {1}, "caller_url": "{2}"}}'.format(
          message_number, text, caller_url).encode('utf-8')
    if not WriteMessage(message):
      break

if __name__ == '__main__':
  sys.exit(Main())
