summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/test/ui/ppapi_uitest.cc5
-rw-r--r--ppapi/cpp/private/flash_tcp_socket.cc7
-rw-r--r--ppapi/cpp/private/flash_tcp_socket.h7
-rw-r--r--ppapi/ppapi_cpp.gypi2
-rw-r--r--ppapi/ppapi_tests.gypi2
-rw-r--r--ppapi/tests/test_tcp_socket_private.cc217
-rw-r--r--ppapi/tests/test_tcp_socket_private.h42
7 files changed, 276 insertions, 6 deletions
diff --git a/chrome/test/ui/ppapi_uitest.cc b/chrome/test/ui/ppapi_uitest.cc
index 054285b..10e93c9 100644
--- a/chrome/test/ui/ppapi_uitest.cc
+++ b/chrome/test/ui/ppapi_uitest.cc
@@ -311,3 +311,8 @@ TEST_F(OutOfProcessPPAPITest, FAILS_UMA) {
TEST_PPAPI_IN_PROCESS(NetAddressPrivate)
TEST_PPAPI_OUT_OF_PROCESS(NetAddressPrivate)
+
+// PPB_TCPSocket_Private currently isn't supported in-process.
+TEST_F(OutOfProcessPPAPITest, TCPSocketPrivate) {
+ RunTestViaHTTP("TCPSocketPrivate");
+}
diff --git a/ppapi/cpp/private/flash_tcp_socket.cc b/ppapi/cpp/private/flash_tcp_socket.cc
index 0dec218..18c865f 100644
--- a/ppapi/cpp/private/flash_tcp_socket.cc
+++ b/ppapi/cpp/private/flash_tcp_socket.cc
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// TODO(yzshen): See the comment in corresponding .h file.
-
#include "ppapi/cpp/private/flash_tcp_socket.h"
#include "ppapi/c/pp_bool.h"
@@ -32,6 +30,11 @@ TCPSocket::TCPSocket(Instance* instance) {
}
}
+// static
+bool TCPSocket::IsAvailable() {
+ return has_interface<PPB_Flash_TCPSocket>();
+}
+
int32_t TCPSocket::Connect(const char* host,
uint16_t port,
const CompletionCallback& callback) {
diff --git a/ppapi/cpp/private/flash_tcp_socket.h b/ppapi/cpp/private/flash_tcp_socket.h
index 41d21c0..7d68abb 100644
--- a/ppapi/cpp/private/flash_tcp_socket.h
+++ b/ppapi/cpp/private/flash_tcp_socket.h
@@ -2,10 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// TODO(yzshen): This (and the .cc file) contain C++ wrappers for things
-// in ppapi/c/private/ppb_flash_tcp_socket.h. This is currently not used in
-// (or even compiled with) Chromium.
-
#ifndef PPAPI_CPP_PRIVATE_FLASH_TCP_SOCKET_H_
#define PPAPI_CPP_PRIVATE_FLASH_TCP_SOCKET_H_
@@ -24,6 +20,9 @@ class TCPSocket : public Resource {
public:
explicit TCPSocket(Instance* instance);
+ // Returns true if the required interface is available.
+ static bool IsAvailable();
+
int32_t Connect(const char* host,
uint16_t port,
const CompletionCallback& callback);
diff --git a/ppapi/ppapi_cpp.gypi b/ppapi/ppapi_cpp.gypi
index 918c659..0f0a88d 100644
--- a/ppapi/ppapi_cpp.gypi
+++ b/ppapi/ppapi_cpp.gypi
@@ -249,6 +249,8 @@
# Private interfaces.
'cpp/private/flash_fullscreen.cc',
'cpp/private/flash_fullscreen.h',
+ 'cpp/private/flash_tcp_socket.cc',
+ 'cpp/private/flash_tcp_socket.h',
'cpp/private/instance_private.cc',
'cpp/private/instance_private.h',
'cpp/private/net_address_private.cc',
diff --git a/ppapi/ppapi_tests.gypi b/ppapi/ppapi_tests.gypi
index 9b17c5d..48f6745 100644
--- a/ppapi/ppapi_tests.gypi
+++ b/ppapi/ppapi_tests.gypi
@@ -121,6 +121,8 @@
'tests/test_scrollbar.cc',
'tests/test_scrollbar.h',
'tests/test_struct_sizes.c',
+ 'tests/test_tcp_socket_private.cc',
+ 'tests/test_tcp_socket_private.h',
'tests/test_uma.cc',
'tests/test_uma.h',
'tests/test_url_loader.cc',
diff --git a/ppapi/tests/test_tcp_socket_private.cc b/ppapi/tests/test_tcp_socket_private.cc
new file mode 100644
index 0000000..c2ef676
--- /dev/null
+++ b/ppapi/tests/test_tcp_socket_private.cc
@@ -0,0 +1,217 @@
+// Copyright (c) 2011 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.
+
+#include "ppapi/tests/test_tcp_socket_private.h"
+
+#include <stdlib.h>
+
+#include "base/string_split.h"
+#include "ppapi/c/dev/ppb_url_util_dev.h"
+#include "ppapi/cpp/dev/url_util_dev.h"
+#include "ppapi/cpp/private/flash_tcp_socket.h"
+#include "ppapi/cpp/var.h"
+#include "ppapi/tests/testing_instance.h"
+#include "ppapi/tests/test_utils.h"
+
+namespace {
+
+// Validates the first line of an HTTP response.
+bool ValidateHttpResponse(const std::string& s) {
+ // Just check that it begins with "HTTP/" and ends with a "\r\n".
+ return s.size() >= 5 &&
+ s.substr(0, 5) == "HTTP/" &&
+ s.substr(s.size() - 2) == "\r\n";
+}
+
+} // namespace
+
+REGISTER_TEST_CASE(TCPSocketPrivate);
+
+TestTCPSocketPrivate::TestTCPSocketPrivate(TestingInstance* instance)
+ : TestCase(instance) {
+}
+
+bool TestTCPSocketPrivate::Init() {
+ if (!TCPSocketPrivate::IsAvailable())
+ return false;
+
+ // This test currently only works out-of-process (since the API is really only
+ // implemented in that case).
+ const PPB_Testing_Dev* testing = GetTestingInterface();
+ if (!testing)
+ return false;
+ if (!testing->IsOutOfProcess())
+ return false;
+
+ // We need something to connect to, so we connect to the HTTP server whence we
+ // came. Grab the host and port.
+ if (!EnsureRunningOverHTTP())
+ return false;
+
+ PP_URLComponents_Dev components;
+ pp::Var pp_url = pp::URLUtil_Dev::Get()->GetDocumentURL(*instance_,
+ &components);
+ if (!pp_url.is_string())
+ return false;
+ std::string url = pp_url.AsString();
+
+ // Double-check that we're running on HTTP.
+ if (components.scheme.len < 0)
+ return false;
+ if (url.substr(components.scheme.begin, components.scheme.len) != "http")
+ return false;
+
+ // Get host.
+ if (components.host.len < 0)
+ return false;
+ host_ = url.substr(components.host.begin, components.host.len);
+
+ // Get port (it's optional).
+ port_ = 80; // Default value.
+ if (components.port.len > 0) {
+ int i = atoi(url.substr(components.port.begin,
+ components.port.len).c_str());
+ if (i < 0 || i > 65535)
+ return false;
+ port_ = static_cast<uint16_t>(i);
+ }
+
+ return true;
+}
+
+void TestTCPSocketPrivate::RunTest() {
+ RUN_TEST_FORCEASYNC_AND_NOT(Basic);
+ RUN_TEST_FORCEASYNC_AND_NOT(ReadWrite);
+ RUN_TEST_FORCEASYNC_AND_NOT(ConnectAddress);
+}
+
+std::string TestTCPSocketPrivate::TestBasic() {
+ TCPSocketPrivate socket(instance_);
+ TestCompletionCallback cb(instance_->pp_instance(), force_async_);
+
+ int32_t rv = socket.Connect(host_.c_str(), port_, cb);
+ ASSERT_TRUE(!force_async_ || rv == PP_OK_COMPLETIONPENDING);
+ if (rv == PP_OK_COMPLETIONPENDING)
+ rv = cb.WaitForResult();
+ ASSERT_EQ(PP_OK, rv);
+
+ PP_NetAddress_Private unused;
+ // TODO(viettrungluu): check the values somehow.
+ ASSERT_TRUE(socket.GetLocalAddress(&unused));
+ ASSERT_TRUE(socket.GetRemoteAddress(&unused));
+
+ socket.Disconnect();
+
+ PASS();
+}
+
+std::string TestTCPSocketPrivate::TestReadWrite() {
+ TCPSocketPrivate socket(instance_);
+ TestCompletionCallback cb(instance_->pp_instance(), force_async_);
+
+ int32_t rv = socket.Connect(host_.c_str(), port_, cb);
+ ASSERT_TRUE(!force_async_ || rv == PP_OK_COMPLETIONPENDING);
+ if (rv == PP_OK_COMPLETIONPENDING)
+ rv = cb.WaitForResult();
+ ASSERT_EQ(PP_OK, rv);
+
+ ASSERT_EQ(PP_OK, WriteStringToSocket(&socket, "GET / HTTP/1.0\r\n\r\n"));
+
+ // Read up to the first \n and check that it looks like valid HTTP response.
+ std::string s;
+ ASSERT_EQ(PP_OK, ReadFirstLineFromSocket(&socket, &s));
+ ASSERT_TRUE(ValidateHttpResponse(s));
+
+ socket.Disconnect();
+
+ PASS();
+}
+
+std::string TestTCPSocketPrivate::TestConnectAddress() {
+ PP_NetAddress_Private address;
+
+ // First, bring up a connection and grab the address.
+ {
+ TCPSocketPrivate socket(instance_);
+ TestCompletionCallback cb(instance_->pp_instance(), force_async_);
+ int32_t rv = socket.Connect(host_.c_str(), port_, cb);
+ ASSERT_TRUE(!force_async_ || rv == PP_OK_COMPLETIONPENDING);
+ if (rv == PP_OK_COMPLETIONPENDING)
+ rv = cb.WaitForResult();
+ ASSERT_EQ(PP_OK, rv);
+ ASSERT_TRUE(socket.GetRemoteAddress(&address));
+ // Omit the |Disconnect()| here to make sure we don't crash if we just let
+ // the resource be destroyed.
+ }
+
+ // Connect to that address.
+ TCPSocketPrivate socket(instance_);
+ TestCompletionCallback cb(instance_->pp_instance(), force_async_);
+ int32_t rv = socket.ConnectWithNetAddress(&address, cb);
+ ASSERT_TRUE(!force_async_ || rv == PP_OK_COMPLETIONPENDING);
+ if (rv == PP_OK_COMPLETIONPENDING)
+ rv = cb.WaitForResult();
+ ASSERT_EQ(PP_OK, rv);
+
+ // Make sure we can read/write to it properly (see |TestReadWrite()|).
+ ASSERT_EQ(PP_OK, WriteStringToSocket(&socket, "GET / HTTP/1.0\r\n\r\n"));
+ std::string s;
+ ASSERT_EQ(PP_OK, ReadFirstLineFromSocket(&socket, &s));
+ ASSERT_TRUE(ValidateHttpResponse(s));
+
+ socket.Disconnect();
+
+ PASS();
+}
+
+// TODO(viettrungluu): Try testing SSL somehow.
+
+int32_t TestTCPSocketPrivate::ReadFirstLineFromSocket(TCPSocketPrivate* socket,
+ std::string* s) {
+ char buffer[10000];
+
+ s->clear();
+ // Make sure we don't just hang if |Read()| spews.
+ while (s->size() < 1000000) {
+ TestCompletionCallback cb(instance_->pp_instance(), force_async_);
+ int32_t rv = socket->Read(buffer, sizeof(buffer), cb);
+ if (force_async_ && rv != PP_OK_COMPLETIONPENDING)
+ return PP_ERROR_FAILED;
+ if (rv == PP_OK_COMPLETIONPENDING)
+ rv = cb.WaitForResult();
+ if (rv < 0)
+ return rv;
+ if (rv == 0)
+ return PP_ERROR_FAILED; // Didn't get a \n-terminated line.
+ s->reserve(s->size() + rv);
+ for (int32_t i = 0; i < rv; i++) {
+ s->push_back(buffer[i]);
+ if (buffer[i] == '\n')
+ return PP_OK;
+ }
+ }
+ return PP_ERROR_FAILED;
+}
+
+int32_t TestTCPSocketPrivate::WriteStringToSocket(TCPSocketPrivate* socket,
+ const std::string& s) {
+ const char* buffer = s.data();
+ size_t written = 0;
+ while (written < s.size()) {
+ TestCompletionCallback cb(instance_->pp_instance(), force_async_);
+ int32_t rv = socket->Write(buffer + written, s.size() - written, cb);
+ if (force_async_ && rv != PP_OK_COMPLETIONPENDING)
+ return PP_ERROR_FAILED;
+ if (rv == PP_OK_COMPLETIONPENDING)
+ rv = cb.WaitForResult();
+ if (rv < 0)
+ return rv;
+ if (rv == 0)
+ return PP_ERROR_FAILED;
+ written += rv;
+ }
+ if (written != s.size())
+ return PP_ERROR_FAILED;
+ return PP_OK;
+}
diff --git a/ppapi/tests/test_tcp_socket_private.h b/ppapi/tests/test_tcp_socket_private.h
new file mode 100644
index 0000000..8cc8448
--- /dev/null
+++ b/ppapi/tests/test_tcp_socket_private.h
@@ -0,0 +1,42 @@
+// Copyright (c) 2011 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.
+
+#ifndef PAPPI_TESTS_TEST_TCP_SOCKET_PRIVATE_H_
+#define PAPPI_TESTS_TEST_TCP_SOCKET_PRIVATE_H_
+
+#include <string>
+
+#include "ppapi/c/pp_stdint.h"
+#include "ppapi/tests/test_case.h"
+
+// TODO(viettrungluu): A rename is in progress and this reduces the amount of
+// code that'll have to be changed.
+namespace pp {
+namespace flash {
+class TCPSocket;
+}
+}
+typedef pp::flash::TCPSocket TCPSocketPrivate;
+
+class TestTCPSocketPrivate : public TestCase {
+ public:
+ explicit TestTCPSocketPrivate(TestingInstance* instance);
+
+ // TestCase implementation.
+ virtual bool Init();
+ virtual void RunTest();
+
+ private:
+ std::string TestBasic();
+ std::string TestReadWrite();
+ std::string TestConnectAddress();
+
+ int32_t ReadFirstLineFromSocket(TCPSocketPrivate* socket, std::string* s);
+ int32_t WriteStringToSocket(TCPSocketPrivate* socket, const std::string& s);
+
+ std::string host_;
+ uint16_t port_;
+};
+
+#endif // PAPPI_TESTS_TEST_TCP_SOCKET_PRIVATE_H_