Home | History | Annotate | Download | only in auto_provider
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 var socket = chrome.experimental.socket || chrome.socket;
      6 
      7 // Stream encapsulates read/write operations over socket.
      8 function Stream(delegate, socketId) {
      9   this.socketId_ = socketId;
     10   this.delegate_ = delegate;
     11 }
     12 
     13 Stream.prototype = {
     14   stringToUint8Array_: function(string) {
     15     var utf8string = unescape(encodeURIComponent(string));
     16     var buffer = new ArrayBuffer(utf8string.length);
     17     var view = new Uint8Array(buffer);
     18     for(var i = 0; i < utf8string.length; i++) {
     19       view[i] = utf8string.charCodeAt(i);
     20     }
     21     return view;
     22   },
     23 
     24   read: function(callback) {
     25     socket.read(this.socketId_, function(readInfo) {
     26       callback(this, readInfo);
     27     }.bind(this));
     28   },
     29 
     30   write: function(output) {
     31     var header = this.stringToUint8Array_(output + '\n\n');
     32     var outputBuffer = new ArrayBuffer(header.byteLength);
     33     var view = new Uint8Array(outputBuffer);
     34     view.set(header, 0);
     35     socket.write(this.socketId_, outputBuffer, function(writeInfo) {
     36       if (writeInfo.bytesWritten < 0)
     37         this.delegate_.onStreamError(this);
     38     }.bind(this));
     39   },
     40 
     41   writeError: function(errorCode, description) {
     42     var content = JSON.stringify({'type': 'error',
     43                                   'code': errorCode,
     44                                   'description': description});
     45     var buffer = this.stringToUint8Array_(content + "\n\n");
     46     var outputBuffer = new ArrayBuffer(buffer.byteLength);
     47     var view = new Uint8Array(outputBuffer);
     48     view.set(buffer, 0);
     49     socket.write(this.socketId_, outputBuffer, function(writeInfo) {
     50       this.terminateConnection_();
     51     }.bind(this));
     52   },
     53 
     54   terminateConnection_: function() {
     55     this.delegate_.onStreamTerminated(this);
     56     socket.destroy(this.socketId_);
     57   }
     58 };
     59 
     60 // Automation server listens socket and passed its processing to
     61 // |connectionHandler|.
     62 function AutomationServer(connectionHandler) {
     63   this.socketInfo = null;
     64   this.handler_ = connectionHandler;
     65 }
     66 
     67 AutomationServer.instance_ = null;
     68 
     69 AutomationServer.getInstance = function() {
     70   if (!AutomationServer.instance_)
     71     AutomationServer.instance_ = new AutomationServer(new ConnectionHandler());
     72 
     73   return AutomationServer.instance_;
     74 }
     75 
     76 AutomationServer.prototype = {
     77   onAccept_: function(acceptInfo) {
     78     console.log("Accepting socket " + acceptInfo.socketId);
     79     socket.setNoDelay(acceptInfo.socketId, true, function(result) {
     80       this.handler_.readRequest_(new Stream(this.handler_,
     81                                             acceptInfo.socketId));
     82       socket.accept(this.socketInfo.socketId, this.onAccept_.bind(this));
     83     }.bind(this));
     84   },
     85 
     86   start: function() {
     87     socket.create("tcp", {}, function(_socketInfo) {
     88       this.socketInfo = _socketInfo;
     89       socket.listen(this.socketInfo.socketId, "127.0.0.1", 8666, 20,
     90         function(result) {
     91           console.log("LISTENING:", result);
     92           socket.accept(this.socketInfo.socketId, this.onAccept_.bind(this));
     93         }.bind(this));
     94     }.bind(this));
     95   }
     96 };
     97