12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#!/usr/bin/env python
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)# Copyright 2013 The Chromium Authors. All rights reserved.
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)# found in the LICENSE file.
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)"""This is a python sync server used for testing Chrome Sync.
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)By default, it listens on an ephemeral port and xmpp_port and sends the port
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)numbers back to the originating process over a pipe. The originating process can
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)specify an explicit port and xmpp_port if necessary.
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)"""
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import asyncore
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import BaseHTTPServer
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import errno
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import os
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import select
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import socket
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import sys
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import urlparse
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import chromiumsync
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import echo_message
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import testserver_base
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import xmppserver
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class SyncHTTPServer(testserver_base.ClientRestrictingServerMixIn,
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     testserver_base.BrokenPipeHandlerMixIn,
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     testserver_base.StoppableHTTPServer):
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  """An HTTP server that handles sync commands."""
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def __init__(self, server_address, xmpp_port, request_handler_class):
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    testserver_base.StoppableHTTPServer.__init__(self,
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                 server_address,
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                 request_handler_class)
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self._sync_handler = chromiumsync.TestServer()
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self._xmpp_socket_map = {}
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self._xmpp_server = xmppserver.XmppServer(
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      self._xmpp_socket_map, ('localhost', xmpp_port))
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.xmpp_port = self._xmpp_server.getsockname()[1]
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.authenticated = True
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def GetXmppServer(self):
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return self._xmpp_server
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def HandleCommand(self, query, raw_request):
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return self._sync_handler.HandleCommand(query, raw_request)
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def HandleRequestNoBlock(self):
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    """Handles a single request.
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Copied from SocketServer._handle_request_noblock().
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    """
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    try:
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      request, client_address = self.get_request()
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    except socket.error:
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if self.verify_request(request, client_address):
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      try:
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        self.process_request(request, client_address)
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      except Exception:
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        self.handle_error(request, client_address)
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        self.close_request(request)
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def SetAuthenticated(self, auth_valid):
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.authenticated = auth_valid
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def GetAuthenticated(self):
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return self.authenticated
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def serve_forever(self):
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    """This is a merge of asyncore.loop() and SocketServer.serve_forever().
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    """
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def HandleXmppSocket(fd, socket_map, handler):
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      """Runs the handler for the xmpp connection for fd.
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Adapted from asyncore.read() et al.
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      """
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      xmpp_connection = socket_map.get(fd)
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      # This could happen if a previous handler call caused fd to get
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      # removed from socket_map.
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if xmpp_connection is None:
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      try:
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        handler(xmpp_connection)
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      except (asyncore.ExitNow, KeyboardInterrupt, SystemExit):
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        raise
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      except:
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        xmpp_connection.handle_error()
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    while True:
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      read_fds = [ self.fileno() ]
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      write_fds = []
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      exceptional_fds = []
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      for fd, xmpp_connection in self._xmpp_socket_map.items():
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        is_r = xmpp_connection.readable()
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        is_w = xmpp_connection.writable()
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if is_r:
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          read_fds.append(fd)
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if is_w:
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          write_fds.append(fd)
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if is_r or is_w:
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          exceptional_fds.append(fd)
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      try:
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        read_fds, write_fds, exceptional_fds = (
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          select.select(read_fds, write_fds, exceptional_fds))
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      except select.error, err:
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if err.args[0] != errno.EINTR:
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          raise
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        else:
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          continue
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      for fd in read_fds:
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if fd == self.fileno():
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          self.HandleRequestNoBlock()
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          continue
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        HandleXmppSocket(fd, self._xmpp_socket_map,
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         asyncore.dispatcher.handle_read_event)
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      for fd in write_fds:
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        HandleXmppSocket(fd, self._xmpp_socket_map,
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         asyncore.dispatcher.handle_write_event)
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      for fd in exceptional_fds:
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        HandleXmppSocket(fd, self._xmpp_socket_map,
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         asyncore.dispatcher.handle_expt_event)
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class SyncPageHandler(testserver_base.BasePageHandler):
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  """Handler for the main HTTP sync server."""
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def __init__(self, request, client_address, sync_http_server):
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    get_handlers = [self.ChromiumSyncTimeHandler,
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    self.ChromiumSyncMigrationOpHandler,
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    self.ChromiumSyncCredHandler,
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    self.ChromiumSyncXmppCredHandler,
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    self.ChromiumSyncDisableNotificationsOpHandler,
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    self.ChromiumSyncEnableNotificationsOpHandler,
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    self.ChromiumSyncSendNotificationOpHandler,
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    self.ChromiumSyncBirthdayErrorOpHandler,
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    self.ChromiumSyncTransientErrorOpHandler,
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    self.ChromiumSyncErrorOpHandler,
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    self.ChromiumSyncSyncTabFaviconsOpHandler,
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    self.ChromiumSyncCreateSyncedBookmarksOpHandler,
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    self.ChromiumSyncEnableKeystoreEncryptionOpHandler,
152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                    self.ChromiumSyncRotateKeystoreKeysOpHandler,
153ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                    self.ChromiumSyncEnableManagedUserAcknowledgementHandler,
154ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                    self.ChromiumSyncEnablePreCommitGetUpdateAvoidanceHandler]
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    post_handlers = [self.ChromiumSyncCommandHandler,
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     self.ChromiumSyncTimeHandler]
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    testserver_base.BasePageHandler.__init__(self, request, client_address,
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                             sync_http_server, [], get_handlers,
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                             [], post_handlers, [])
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def ChromiumSyncTimeHandler(self):
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    """Handle Chromium sync .../time requests.
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    The syncer sometimes checks server reachability by examining /time.
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    """
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    test_name = "/chromiumsync/time"
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if not self._ShouldHandleRequest(test_name):
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return False
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    # Chrome hates it if we send a response before reading the request.
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if self.headers.getheader('content-length'):
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      length = int(self.headers.getheader('content-length'))
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      _raw_request = self.rfile.read(length)
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.send_response(200)
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.send_header('Content-Type', 'text/plain')
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.end_headers()
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.wfile.write('0123456789')
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return True
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def ChromiumSyncCommandHandler(self):
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    """Handle a chromiumsync command arriving via http.
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    This covers all sync protocol commands: authentication, getupdates, and
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    commit.
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    """
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    test_name = "/chromiumsync/command"
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if not self._ShouldHandleRequest(test_name):
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return False
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    length = int(self.headers.getheader('content-length'))
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    raw_request = self.rfile.read(length)
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    http_response = 200
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    raw_reply = None
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if not self.server.GetAuthenticated():
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      http_response = 401
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      challenge = 'GoogleLogin realm="http://%s", service="chromiumsync"' % (
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        self.server.server_address[0])
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    else:
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      http_response, raw_reply = self.server.HandleCommand(
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          self.path, raw_request)
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ### Now send the response to the client. ###
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.send_response(http_response)
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if http_response == 401:
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      self.send_header('www-Authenticate', challenge)
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.end_headers()
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.wfile.write(raw_reply)
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return True
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def ChromiumSyncMigrationOpHandler(self):
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    test_name = "/chromiumsync/migrate"
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if not self._ShouldHandleRequest(test_name):
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return False
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    http_response, raw_reply = self.server._sync_handler.HandleMigrate(
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        self.path)
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.send_response(http_response)
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.send_header('Content-Type', 'text/html')
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.send_header('Content-Length', len(raw_reply))
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.end_headers()
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.wfile.write(raw_reply)
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return True
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def ChromiumSyncCredHandler(self):
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    test_name = "/chromiumsync/cred"
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if not self._ShouldHandleRequest(test_name):
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return False
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    try:
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      query = urlparse.urlparse(self.path)[4]
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      cred_valid = urlparse.parse_qs(query)['valid']
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if cred_valid[0] == 'True':
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        self.server.SetAuthenticated(True)
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      else:
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        self.server.SetAuthenticated(False)
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    except Exception:
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      self.server.SetAuthenticated(False)
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    http_response = 200
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    raw_reply = 'Authenticated: %s ' % self.server.GetAuthenticated()
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.send_response(http_response)
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.send_header('Content-Type', 'text/html')
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.send_header('Content-Length', len(raw_reply))
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.end_headers()
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.wfile.write(raw_reply)
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return True
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def ChromiumSyncXmppCredHandler(self):
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    test_name = "/chromiumsync/xmppcred"
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if not self._ShouldHandleRequest(test_name):
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return False
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    xmpp_server = self.server.GetXmppServer()
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    try:
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      query = urlparse.urlparse(self.path)[4]
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      cred_valid = urlparse.parse_qs(query)['valid']
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if cred_valid[0] == 'True':
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        xmpp_server.SetAuthenticated(True)
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      else:
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        xmpp_server.SetAuthenticated(False)
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    except:
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      xmpp_server.SetAuthenticated(False)
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    http_response = 200
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    raw_reply = 'XMPP Authenticated: %s ' % xmpp_server.GetAuthenticated()
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.send_response(http_response)
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.send_header('Content-Type', 'text/html')
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.send_header('Content-Length', len(raw_reply))
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.end_headers()
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.wfile.write(raw_reply)
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return True
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def ChromiumSyncDisableNotificationsOpHandler(self):
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    test_name = "/chromiumsync/disablenotifications"
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if not self._ShouldHandleRequest(test_name):
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return False
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.server.GetXmppServer().DisableNotifications()
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    result = 200
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    raw_reply = ('<html><title>Notifications disabled</title>'
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 '<H1>Notifications disabled</H1></html>')
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.send_response(result)
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.send_header('Content-Type', 'text/html')
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.send_header('Content-Length', len(raw_reply))
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.end_headers()
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.wfile.write(raw_reply)
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return True
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def ChromiumSyncEnableNotificationsOpHandler(self):
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    test_name = "/chromiumsync/enablenotifications"
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if not self._ShouldHandleRequest(test_name):
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return False
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.server.GetXmppServer().EnableNotifications()
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    result = 200
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    raw_reply = ('<html><title>Notifications enabled</title>'
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 '<H1>Notifications enabled</H1></html>')
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.send_response(result)
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.send_header('Content-Type', 'text/html')
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.send_header('Content-Length', len(raw_reply))
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.end_headers()
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.wfile.write(raw_reply)
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return True
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def ChromiumSyncSendNotificationOpHandler(self):
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    test_name = "/chromiumsync/sendnotification"
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if not self._ShouldHandleRequest(test_name):
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return False
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    query = urlparse.urlparse(self.path)[4]
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    query_params = urlparse.parse_qs(query)
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    channel = ''
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    data = ''
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if 'channel' in query_params:
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      channel = query_params['channel'][0]
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if 'data' in query_params:
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      data = query_params['data'][0]
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.server.GetXmppServer().SendNotification(channel, data)
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    result = 200
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    raw_reply = ('<html><title>Notification sent</title>'
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 '<H1>Notification sent with channel "%s" '
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 'and data "%s"</H1></html>'
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 % (channel, data))
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.send_response(result)
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.send_header('Content-Type', 'text/html')
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.send_header('Content-Length', len(raw_reply))
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.end_headers()
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.wfile.write(raw_reply)
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return True
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def ChromiumSyncBirthdayErrorOpHandler(self):
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    test_name = "/chromiumsync/birthdayerror"
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if not self._ShouldHandleRequest(test_name):
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return False
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    result, raw_reply = self.server._sync_handler.HandleCreateBirthdayError()
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.send_response(result)
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.send_header('Content-Type', 'text/html')
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.send_header('Content-Length', len(raw_reply))
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.end_headers()
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.wfile.write(raw_reply)
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return True
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def ChromiumSyncTransientErrorOpHandler(self):
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    test_name = "/chromiumsync/transienterror"
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if not self._ShouldHandleRequest(test_name):
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return False
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    result, raw_reply = self.server._sync_handler.HandleSetTransientError()
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.send_response(result)
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.send_header('Content-Type', 'text/html')
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.send_header('Content-Length', len(raw_reply))
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.end_headers()
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.wfile.write(raw_reply)
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return True
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def ChromiumSyncErrorOpHandler(self):
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    test_name = "/chromiumsync/error"
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if not self._ShouldHandleRequest(test_name):
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return False
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    result, raw_reply = self.server._sync_handler.HandleSetInducedError(
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        self.path)
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.send_response(result)
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.send_header('Content-Type', 'text/html')
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.send_header('Content-Length', len(raw_reply))
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.end_headers()
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.wfile.write(raw_reply)
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return True
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def ChromiumSyncSyncTabFaviconsOpHandler(self):
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    test_name = "/chromiumsync/synctabfavicons"
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if not self._ShouldHandleRequest(test_name):
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return False
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    result, raw_reply = self.server._sync_handler.HandleSetSyncTabFavicons()
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.send_response(result)
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.send_header('Content-Type', 'text/html')
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.send_header('Content-Length', len(raw_reply))
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.end_headers()
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.wfile.write(raw_reply)
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return True
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def ChromiumSyncCreateSyncedBookmarksOpHandler(self):
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    test_name = "/chromiumsync/createsyncedbookmarks"
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if not self._ShouldHandleRequest(test_name):
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return False
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    result, raw_reply = self.server._sync_handler.HandleCreateSyncedBookmarks()
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.send_response(result)
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.send_header('Content-Type', 'text/html')
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.send_header('Content-Length', len(raw_reply))
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.end_headers()
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.wfile.write(raw_reply)
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return True
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def ChromiumSyncEnableKeystoreEncryptionOpHandler(self):
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    test_name = "/chromiumsync/enablekeystoreencryption"
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if not self._ShouldHandleRequest(test_name):
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return False
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    result, raw_reply = (
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        self.server._sync_handler.HandleEnableKeystoreEncryption())
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.send_response(result)
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.send_header('Content-Type', 'text/html')
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.send_header('Content-Length', len(raw_reply))
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.end_headers()
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.wfile.write(raw_reply)
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return True
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def ChromiumSyncRotateKeystoreKeysOpHandler(self):
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    test_name = "/chromiumsync/rotatekeystorekeys"
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if not self._ShouldHandleRequest(test_name):
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return False
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    result, raw_reply = (
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        self.server._sync_handler.HandleRotateKeystoreKeys())
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.send_response(result)
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.send_header('Content-Type', 'text/html')
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.send_header('Content-Length', len(raw_reply))
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.end_headers()
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.wfile.write(raw_reply)
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return True
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
418868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  def ChromiumSyncEnableManagedUserAcknowledgementHandler(self):
419868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    test_name = "/chromiumsync/enablemanageduseracknowledgement"
420868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if not self._ShouldHandleRequest(test_name):
421868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return False
422868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    result, raw_reply = (
423868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        self.server._sync_handler.HandleEnableManagedUserAcknowledgement())
424868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    self.send_response(result)
425868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    self.send_header('Content-Type', 'text/html')
426868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    self.send_header('Content-Length', len(raw_reply))
427868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    self.end_headers()
428868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    self.wfile.write(raw_reply)
429868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return True
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
431ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  def ChromiumSyncEnablePreCommitGetUpdateAvoidanceHandler(self):
432ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    test_name = "/chromiumsync/enableprecommitgetupdateavoidance"
433ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    if not self._ShouldHandleRequest(test_name):
434ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      return False
435ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    result, raw_reply = (
436ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        self.server._sync_handler.HandleEnablePreCommitGetUpdateAvoidance())
437ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    self.send_response(result)
438ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    self.send_header('Content-Type', 'text/html')
439ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    self.send_header('Content-Length', len(raw_reply))
440ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    self.end_headers()
441ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    self.wfile.write(raw_reply)
442ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return True
443ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class SyncServerRunner(testserver_base.TestServerRunner):
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  """TestServerRunner for the net test servers."""
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def __init__(self):
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    super(SyncServerRunner, self).__init__()
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def create_server(self, server_data):
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    port = self.options.port
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    host = self.options.host
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    xmpp_port = self.options.xmpp_port
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    server = SyncHTTPServer((host, port), xmpp_port, SyncPageHandler)
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    print 'Sync HTTP server started on port %d...' % server.server_port
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    print 'Sync XMPP server started on port %d...' % server.xmpp_port
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    server_data['port'] = server.server_port
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    server_data['xmpp_port'] = server.xmpp_port
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return server
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def run_server(self):
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    testserver_base.TestServerRunner.run_server(self)
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def add_options(self):
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    testserver_base.TestServerRunner.add_options(self)
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.option_parser.add_option('--xmpp-port', default='0', type='int',
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  help='Port used by the XMPP server. If '
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  'unspecified, the XMPP server will listen on '
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  'an ephemeral port.')
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    # Override the default logfile name used in testserver.py.
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.option_parser.set_defaults(log_file='sync_testserver.log')
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)if __name__ == '__main__':
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  sys.exit(SyncServerRunner().main())
475