Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / chrome / test / data / extensions / api_test / sockets_tcp / api / background.js
1 // Copyright 2013 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 // net/tools/testserver/testserver.py is picky about the format of what it
6 // calls its "echo" messages. One might go so far as to mutter to oneself that
7 // it isn't an echo server at all.
8 //
9 // The response is based on the request but obfuscated using a random key.
10 const request = "0100000005320000005hello";
11 var expectedResponsePattern = /0100000005320000005.{11}/;
12 const http_get = "GET test.html HTTP/1.0\r\n\r\n";
13 var expectedHTTPPattern = /HTTP.1.0 200 OK/;
14
15 var tcp_address;
16 var https_address;
17 var bytesSent = 0;
18 var dataAsString;
19 var dataRead = [];
20 var tcp_port = -1;
21 var https_port = -1;
22 var protocol = "none";
23 var tcp_socketId = 0;
24 var https_socketId = 0;
25 var echoDataSent = false;
26 var succeeded = false;
27 var waitCount = 0;
28
29 // Keys are socketIds. Values are inner dictionaries with two keys: onReceive,
30 // onReceiveError. Both are functions.
31 var receive_dispatcher = {}
32
33 // Many thanks to Dennis for his StackOverflow answer: http://goo.gl/UDanx
34 // Since amended to handle BlobBuilder deprecation.
35 function string2ArrayBuffer(string, callback) {
36   var blob = new Blob([string]);
37   var f = new FileReader();
38   f.onload = function(e) {
39     callback(e.target.result);
40   };
41   f.readAsArrayBuffer(blob);
42 }
43
44 function arrayBuffer2String(buf, callback) {
45   var blob = new Blob([new Uint8Array(buf)]);
46   var f = new FileReader();
47   f.onload = function(e) {
48     callback(e.target.result);
49   };
50   f.readAsText(blob);
51 }
52
53 function dispatchSocketReceive(receiveInfo) {
54   if (receive_dispatcher[receiveInfo.socketId] !== undefined) {
55     receive_dispatcher[receiveInfo.socketId].onReceive(receiveInfo);
56   } else {
57     console.log("dispatchSocketReceive: No handler for socket " +
58         receiveInfo.socketId);
59   }
60 }
61
62 function dispatchSocketReceiveError(receiveErrorInfo) {
63   if (receive_dispatcher[receiveErrorInfo.socketId] !== undefined) {
64     receive_dispatcher[receiveErrorInfo.socketId].onReceiveError(
65         receiveErrorInfo);
66   } else {
67     console.log("dispatchSocketReceiveError: No handler for socket " +
68         receiveErrorInfo.socketId);
69   }
70 }
71
72 var testSocketCreation = function() {
73   function onCreate(socketInfo) {
74     function onGetInfo(info) {
75       chrome.test.assertFalse(info.connected);
76
77       if (info.peerAddress || info.peerPort) {
78         chrome.test.fail('Unconnected socket should not have peer');
79       }
80       if (info.localAddress || info.localPort) {
81         chrome.test.fail('Unconnected socket should not have local binding');
82       }
83
84       chrome.sockets.tcp.close(socketInfo.socketId, function() {
85         chrome.sockets.tcp.getInfo(socketInfo.socketId, function(info) {
86           chrome.test.assertEq(undefined, info);
87           chrome.test.succeed();
88         });
89       });
90     }
91
92     chrome.test.assertTrue(socketInfo.socketId > 0);
93
94     // Obtaining socket information before a connect() call should be safe, but
95     // return empty values.
96     chrome.sockets.tcp.getInfo(socketInfo.socketId, onGetInfo);
97   }
98
99   chrome.sockets.tcp.create({}, onCreate);
100 };
101
102 var testSending = function() {
103   dataRead = "";
104   succeeded = false;
105   echoDataSent = false;
106   waitCount = 0;
107
108   setTimeout(waitForBlockingOperation, 1000);
109
110   createSocket();
111
112   function createSocket() {
113     chrome.sockets.tcp.create({
114       "name": "test",
115       "persistent": true,
116       "bufferSize": 104
117     }, onCreateComplete);
118   }
119
120   function onCreateComplete(socketInfo) {
121     console.log("onCreateComplete");
122     tcp_socketId = socketInfo.socketId;
123     chrome.test.assertTrue(tcp_socketId > 0, "failed to create socket");
124
125     console.log("add event listeners");
126     receive_dispatcher[tcp_socketId] = {
127       onReceive: onSocketReceive,
128       onReceiveError: onSocketReceiveError
129     };
130
131     chrome.sockets.tcp.getInfo(tcp_socketId, onGetInfoAfterCreateComplete);
132   }
133
134   function onGetInfoAfterCreateComplete(result) {
135     console.log("onGetInfoAfterCreateComplete");
136     chrome.test.assertTrue(!result.localAddress,
137                            "Socket should not have local address");
138     chrome.test.assertTrue(!result.localPort,
139                            "Socket should not have local port");
140     chrome.test.assertTrue(!result.peerAddress,
141                            "Socket should not have peer address");
142     chrome.test.assertTrue(!result.peerPort,
143                            "Socket should not have peer port");
144     chrome.test.assertFalse(result.connected, "Socket should not be connected");
145
146     chrome.test.assertEq("test", result.name, "Socket name did not persist");
147     chrome.test.assertTrue(result.persistent,
148                            "Socket should be persistent");
149     chrome.test.assertEq(104, result.bufferSize, "Buffer size did not persist");
150     chrome.test.assertFalse(result.paused, "Socket should not be paused");
151
152     chrome.sockets.tcp.update(tcp_socketId, {
153       "name": "test2",
154       "persistent": false,
155       bufferSize: 2048
156     }, onUpdateComplete);
157   }
158
159   function onUpdateComplete() {
160     console.log("onUpdateComplete");
161     chrome.sockets.tcp.getInfo(tcp_socketId, onGetInfoAfterUpdateComplete);
162   }
163
164   function onGetInfoAfterUpdateComplete(result) {
165     console.log("onGetInfoAfterUpdateComplete");
166     chrome.test.assertTrue(!result.localAddress,
167                            "Socket should not have local address");
168     chrome.test.assertTrue(!result.localPort,
169                            "Socket should not have local port");
170     chrome.test.assertTrue(!result.peerAddress,
171                            "Socket should not have peer address");
172     chrome.test.assertTrue(!result.peerPort,
173                            "Socket should not have peer port");
174     chrome.test.assertFalse(result.connected, "Socket should not be connected");
175
176     chrome.test.assertEq("test2", result.name, "Socket name did not persist");
177     chrome.test.assertFalse(result.persistent,
178                            "Socket should not be persistent");
179     chrome.test.assertEq(2048, result.bufferSize,
180                          "Buffer size did not persist");
181     chrome.test.assertFalse(result.paused, "Socket should not be paused");
182
183     chrome.sockets.tcp.connect(tcp_socketId, tcp_address, tcp_port,
184                                onConnectComplete);
185   }
186
187   function onConnectComplete(result) {
188     console.log("onConnectComplete");
189     chrome.test.assertEq(0, result,
190                          "Connect failed with error " + result);
191
192     chrome.sockets.tcp.getInfo(tcp_socketId, onGetInfoAfterConnectComplete);
193   }
194
195   function onGetInfoAfterConnectComplete(result) {
196     console.log("onGetInfoAfterConnectComplete");
197     chrome.test.assertTrue(!!result.localAddress,
198                            "Bound socket should always have local address");
199     chrome.test.assertTrue(!!result.localPort,
200                            "Bound socket should always have local port");
201
202     // NOTE: We're always called with 'localhost', but getInfo will only return
203     // IPs, not names.
204     chrome.test.assertEq(result.peerAddress, "127.0.0.1",
205                          "Peer addresss should be the listen server");
206     chrome.test.assertEq(result.peerPort, tcp_port,
207                          "Peer port should be the listen server");
208     chrome.test.assertTrue(result.connected, "Socket should be connected");
209
210     chrome.sockets.tcp.setPaused(tcp_socketId, true, onSetPausedComplete);
211   }
212
213   function onSetPausedComplete() {
214     console.log("onSetPausedComplete");
215     chrome.sockets.tcp.getInfo(tcp_socketId, onGetInfoAfterSetPausedComplete);
216   }
217
218   function onGetInfoAfterSetPausedComplete(result) {
219     console.log("onGetInfoAfterSetPausedComplete");
220     chrome.test.assertTrue(result.paused, "Socket should be paused");
221     chrome.sockets.tcp.setPaused(tcp_socketId, false, onUnpauseComplete);
222   }
223
224   function onUnpauseComplete() {
225     console.log("onUnpauseComplete");
226     chrome.sockets.tcp.getInfo(tcp_socketId, onGetInfoAfterUnpauseComplete);
227   }
228
229   function onGetInfoAfterUnpauseComplete(result) {
230     console.log("onGetInfoAfterUnpauseComplete");
231     chrome.test.assertFalse(result.paused, "Socket should not be paused");
232     chrome.sockets.tcp.setNoDelay(tcp_socketId, true, onSetNoDelayComplete);
233   }
234
235   function onSetNoDelayComplete(result) {
236     console.log("onSetNoDelayComplete");
237     if (result != 0) {
238       chrome.test.fail("setNoDelay failed for TCP: " +
239           "result=" + result + ", " +
240           "lastError=" + chrome.runtime.lastError.message);
241     }
242     chrome.sockets.tcp.setKeepAlive(
243         tcp_socketId, true, 1000, onSetKeepAliveComplete);
244   }
245
246   function onSetKeepAliveComplete(result) {
247     console.log("onSetKeepAliveComplete");
248     if (result != 0) {
249       chrome.test.fail("setKeepAlive failed for TCP: " +
250           "result=" + result + ", " +
251           "lastError=" + chrome.runtime.lastError.message);
252     }
253
254     string2ArrayBuffer(request, function(arrayBuffer) {
255       echoDataSent = true;
256       chrome.sockets.tcp.send(tcp_socketId, arrayBuffer, onSendComplete);
257     });
258   }
259
260   function onSendComplete(sendInfo) {
261     console.log("onSendComplete: " + sendInfo.bytesSent + " bytes.");
262     chrome.test.assertEq(0, sendInfo.resultCode, "Send failed.");
263     chrome.test.assertTrue(sendInfo.bytesSent > 0,
264         "Send didn't write bytes.");
265     bytesSent += sendInfo.bytesSent;
266   }
267
268   function onSocketReceive(receiveInfo) {
269     console.log("onSocketReceive");
270     chrome.test.assertEq(tcp_socketId, receiveInfo.socketId);
271     arrayBuffer2String(receiveInfo.data, function(s) {
272       dataAsString = s;  // save this for error reporting
273       var match = !!s.match(expectedResponsePattern);
274       chrome.test.assertTrue(match, "Received data does not match.");
275       console.log("echo data received, closing socket");
276       chrome.sockets.tcp.close(tcp_socketId, onCloseComplete);
277     });
278   }
279
280   function onSocketReceiveError(receiveErrorInfo) {
281     // Note: Once we have sent the "echo" message, the echo server sends back
282     // the "echo" response and closes the connection right away. This means
283     // we get a "connection closed" error very quickly after sending our
284     // message. This is why we ignore errors from that point on.
285     if (echoDataSent)
286       return;
287
288     console.log("onSocketReceiveError");
289     chrome.test.fail("Receive error on socket " + receiveErrorInfo.socketId +
290       ": result code=" + receiveErrorInfo.resultCode);
291   }
292
293   function onCloseComplete() {
294     console.log("onCloseComplete");
295     succeeded = true;
296     chrome.test.succeed();
297   }
298
299 };  // testSending()
300
301 var testSecure = function () {
302   var request_sent = false;
303   succeeded = false;
304   dataAsString = "";
305   setTimeout(waitForBlockingOperation, 1000);
306
307   // Run the test a few times. First with misuse_testing=MISUSE_NONE,
308   // to test that the API works correctly when used properly. Then
309   // with different values of misuse_mode, test that the API does
310   // not malfunction when used improperly. Upon success, each misuse
311   // must close the socket and call onCloseComplete().
312   var MISUSE_NONE = 0;
313   var MISUSE_SECURE_PENDING_READ = 1;
314   var MISUSE_LAST = MISUSE_SECURE_PENDING_READ;
315   var misuse_mode = MISUSE_NONE;
316
317   chrome.sockets.tcp.create({}, onCreateComplete);
318
319   function onCreateComplete(socketInfo) {
320     https_socketId = socketInfo.socketId;
321     receive_dispatcher[https_socketId] = {
322       onReceive: onSocketReceive,
323       onReceiveError: onSocketReceiveError
324     };
325
326     chrome.test.assertTrue(https_socketId > 0, "failed to create socket");
327     if (misuse_mode == MISUSE_SECURE_PENDING_READ) {
328       // Don't pause the socket. This will let the sockets runtime
329       // keep a pending read on it.
330       console.log("HTTPS onCreateComplete: in MISUSE_SECURE_PENDING_READ " +
331                   "mode, skipping setPaused(false).");
332       onPausedComplete();
333     } else {
334       chrome.sockets.tcp.setPaused(https_socketId, true, onPausedComplete);
335     }
336   }
337
338   function onPausedComplete() {
339     console.log("HTTPS onPausedComplete. Connecting to " + https_address + ":" +
340         https_port);
341     chrome.sockets.tcp.connect(https_socketId, https_address, https_port,
342                                onConnectComplete);
343   }
344
345   function onConnectComplete(result) {
346     console.log("HTTPS onConnectComplete");
347     chrome.test.assertEq(0, result,
348                          "Connect failed with error " + result);
349     chrome.sockets.tcp.secure(https_socketId, null, onSecureComplete);
350   }
351
352   function onSecureComplete(result) {
353     console.log("HTTPS onSecureComplete(" + result + ")");
354     if (misuse_mode == MISUSE_SECURE_PENDING_READ) {
355       chrome.test.assertFalse(result == 0,
356                               "Secure should have failed when a read " +
357                               "was pending (" + result + ")");
358       chrome.sockets.tcp.close(https_socketId, onCloseComplete);
359     } else {
360       chrome.test.assertEq(0, result,
361                            "Secure failed with error " + result);
362       chrome.sockets.tcp.setPaused(https_socketId, false, onUnpauseComplete);
363     }
364   }
365
366   function onUnpauseComplete() {
367     console.log("HTTPS onUnpauseComplete");
368     string2ArrayBuffer(http_get, function(arrayBuffer) {
369       request_sent = true;
370       chrome.sockets.tcp.send(https_socketId, arrayBuffer, onSendComplete);
371     });
372   }
373
374   function onSendComplete(sendInfo) {
375     console.log("HTTPS onSendComplete: " + sendInfo.bytesSent + " bytes.");
376     chrome.test.assertEq(0, sendInfo.resultCode, "Send failed.");
377     chrome.test.assertTrue(sendInfo.bytesSent > 0,
378         "Send didn't write bytes.");
379     bytesSent += sendInfo.bytesSent;
380   }
381
382   function onSocketReceive(receiveInfo) {
383     console.log("HTTPS onSocketReceive");
384     chrome.test.assertEq(https_socketId, receiveInfo.socketId);
385     arrayBuffer2String(receiveInfo.data, function(s) {
386       // we will get more data than we care about. We only care about the
387       // first segment of data (the HTTP 200 code). Ignore the rest, which
388       // won't match the pattern.
389       if (succeeded == false) {
390         dataAsString = s;  // for waitForBlockingOperation().
391         console.log("HTTPS receive: got " + s);
392         var match = !!s.match(expectedHTTPPattern);
393         chrome.test.assertTrue(match, "Received data does not match.");
394         console.log("HTTPS response received, closing socket.");
395         chrome.sockets.tcp.close(https_socketId, onCloseComplete);
396       }
397       succeeded = true;
398     });
399   }
400
401   function onSocketReceiveError(receiveErrorInfo) {
402     console.log("HTTPS onSocketReceiveError");
403     if (request_sent) {
404       return;
405     }
406     chrome.test.fail("Receive error on socket " + receiveErrorInfo.socketId +
407       ": result code=" + receiveErrorInfo.resultCode);
408   }
409
410   function onCloseComplete() {
411     console.log("HTTPS Test Succeeded");
412     if (misuse_mode == MISUSE_LAST) {
413         // The test has run in all misuse modes.
414         chrome.test.succeed();
415     } else {
416         // Run the test again in the next misuse mode.
417         misuse_mode += 1;
418         chrome.sockets.tcp.create({}, onCreateComplete);
419     }
420   }
421 };  // testSecure()
422
423 function waitForBlockingOperation() {
424   if (++waitCount < 10) {
425     setTimeout(waitForBlockingOperation, 1000);
426   } else {
427     // We weren't able to succeed in the given time.
428     chrome.test.fail("Operations didn't complete after " + waitCount + " " +
429                      "seconds. Response so far was <" + dataAsString + ">.");
430   }
431 }
432
433 var onMessageReply = function(message) {
434   var components = message.split(',');
435   var tests = [];
436   for (var i = 0; i < components.length; ++i) {
437     var parts = components[i].split(":");
438     var test_type = parts[0];
439     if (test_type == 'tcp') {
440       tcp_address = parts[1];
441       tcp_port = parseInt(parts[2]);
442       console.log("Running tests for TCP, echo server " +
443           tcp_address + ":" + tcp_port);
444       tests = tests.concat([testSocketCreation, testSending]);
445     } else if (test_type == 'https') {
446       https_address = parts[1];
447       https_port = parseInt(parts[2]);
448       console.log("Running tests for HTTPS, server " +
449           https_address + ":" + https_port);
450       tests = tests.concat([testSecure]);
451     } else {
452       chrome.test.fail("Invalid test type: " + test_type);
453     }
454   }
455   // Setup the suite-wide event listeners.
456   chrome.sockets.tcp.onReceive.addListener(dispatchSocketReceive);
457   chrome.sockets.tcp.onReceiveError.addListener(dispatchSocketReceiveError);
458
459   chrome.test.runTests(tests);
460 };
461
462 // Find out which protocol we're supposed to test, and which echo server we
463 // should be using, then kick off the tests.
464 chrome.test.sendMessage("info_please", onMessageReply);