• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
5var socket = chrome.experimental.socket || chrome.socket;
6
7// Stream encapsulates read/write operations over socket.
8function Stream(delegate, socketId) {
9  this.socketId_ = socketId;
10  this.delegate_ = delegate;
11}
12
13Stream.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|.
62function AutomationServer(connectionHandler) {
63  this.socketInfo = null;
64  this.handler_ = connectionHandler;
65}
66
67AutomationServer.instance_ = null;
68
69AutomationServer.getInstance = function() {
70  if (!AutomationServer.instance_)
71    AutomationServer.instance_ = new AutomationServer(new ConnectionHandler());
72
73  return AutomationServer.instance_;
74}
75
76AutomationServer.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