Commit 31381460 authored by toyoshim@chromium.org's avatar toyoshim@chromium.org

WebSocket Pepper API: in process API implementation

This change enable in process Websocket Pepper API.
For now, some unit tests are disabled because they need external a
WebSocket server.
These disabled tests run manually with external pywebsocket and
--gtest_also_run_disabled_tests flag as follows.
These tests will enabled in a few days.

TBR=dmichael@chromium.org
BUG=87310
TEST=ui_tests --gtest_filter='PPAPITest.WebSocket*'

Review URL: http://codereview.chromium.org/8558017

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@111596 0039d316-1c4b-4281-b951-d872f2087c98
parent 9da4b1b9
...@@ -231,6 +231,17 @@ class PPAPINaClTest : public PPAPITestBase { ...@@ -231,6 +231,17 @@ class PPAPINaClTest : public PPAPITestBase {
RunTestViaHTTP(#test_name); \ RunTestViaHTTP(#test_name); \
} }
// Similar macros that test with WebSocket server
#define TEST_PPAPI_IN_PROCESS_WITH_WS(test_name) \
TEST_F(PPAPITest, test_name) { \
RunTestWithWebSocketServer(#test_name); \
}
#define TEST_PPAPI_OUT_OF_PROCESS_WITH_WS(test_name) \
TEST_F(OutOfProcessPPAPITest, test_name) { \
RunTestWithWebSocketServer(#test_name); \
}
// NaCl based PPAPI tests // NaCl based PPAPI tests
#define TEST_PPAPI_NACL_VIA_HTTP(test_name) \ #define TEST_PPAPI_NACL_VIA_HTTP(test_name) \
...@@ -460,7 +471,9 @@ TEST_PPAPI_OUT_OF_PROCESS(Flash_MessageLoop) ...@@ -460,7 +471,9 @@ TEST_PPAPI_OUT_OF_PROCESS(Flash_MessageLoop)
TEST_PPAPI_OUT_OF_PROCESS(Flash_GetLocalTimeZoneOffset) TEST_PPAPI_OUT_OF_PROCESS(Flash_GetLocalTimeZoneOffset)
TEST_PPAPI_OUT_OF_PROCESS(Flash_GetCommandLineArgs) TEST_PPAPI_OUT_OF_PROCESS(Flash_GetCommandLineArgs)
TEST_PPAPI_IN_PROCESS(WebSocket_Create) TEST_PPAPI_IN_PROCESS(WebSocket_InvalidConnect)
TEST_PPAPI_IN_PROCESS(WebSocket_IsWebSocket) TEST_PPAPI_IN_PROCESS(WebSocket_IsWebSocket)
TEST_PPAPI_IN_PROCESS_WITH_WS(WebSocket_ValidConnect)
TEST_PPAPI_IN_PROCESS_WITH_WS(WebSocket_TextSendReceive)
#endif // ADDRESS_SANITIZER #endif // ADDRESS_SANITIZER
...@@ -4,41 +4,196 @@ ...@@ -4,41 +4,196 @@
#include "ppapi/tests/test_websocket.h" #include "ppapi/tests/test_websocket.h"
#include <string.h>
#include "base/logging.h"
#include "ppapi/c/dev/ppb_websocket_dev.h" #include "ppapi/c/dev/ppb_websocket_dev.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/pp_var.h"
#include "ppapi/c/pp_completion_callback.h"
#include "ppapi/c/ppb_core.h"
#include "ppapi/c/ppb_var.h"
#include "ppapi/cpp/instance.h" #include "ppapi/cpp/instance.h"
#include "ppapi/cpp/module.h" #include "ppapi/cpp/module.h"
#include "ppapi/tests/test_utils.h"
#include "ppapi/tests/testing_instance.h" #include "ppapi/tests/testing_instance.h"
static const char kEchoServerURL[] =
"ws://localhost:8880/websocket/tests/hybi/echo";
REGISTER_TEST_CASE(WebSocket); REGISTER_TEST_CASE(WebSocket);
bool TestWebSocket::Init() { bool TestWebSocket::Init() {
websocket_interface_ = reinterpret_cast<PPB_WebSocket_Dev const*>( websocket_interface_ = static_cast<const PPB_WebSocket_Dev*>(
pp::Module::Get()->GetBrowserInterface(PPB_WEBSOCKET_DEV_INTERFACE)); pp::Module::Get()->GetBrowserInterface(PPB_WEBSOCKET_DEV_INTERFACE));
return !!websocket_interface_; var_interface_ = static_cast<const PPB_Var*>(
pp::Module::Get()->GetBrowserInterface(PPB_VAR_INTERFACE));
core_interface_ = static_cast<const PPB_Core*>(
pp::Module::Get()->GetBrowserInterface(PPB_CORE_INTERFACE));
if (!websocket_interface_ || !var_interface_ || !core_interface_)
return false;
return true;
} }
void TestWebSocket::RunTests(const std::string& filter) { void TestWebSocket::RunTests(const std::string& filter) {
instance_->LogTest("Create", TestCreate()); RUN_TEST(IsWebSocket, filter);
instance_->LogTest("IsWebSocket", TestIsWebSocket()); RUN_TEST(InvalidConnect, filter);
RUN_TEST(ValidConnect, filter);
RUN_TEST(TextSendReceive, filter);
} }
std::string TestWebSocket::TestCreate() { PP_Var TestWebSocket::CreateVar(const char* string) {
PP_Resource rsrc = websocket_interface_->Create(instance_->pp_instance()); return var_interface_->VarFromUtf8(
if (!rsrc) pp::Module::Get()->pp_module(), string, strlen(string));
return "Could not create websocket via C interface"; }
PASS(); void TestWebSocket::ReleaseVar(const PP_Var& var) {
var_interface_->Release(var);
}
bool TestWebSocket::AreEqual(const PP_Var& var, const char* string) {
if (var.type != PP_VARTYPE_STRING)
return false;
uint32_t utf8_length;
const char* utf8 = var_interface_->VarToUtf8(var, &utf8_length);
uint32_t string_length = strlen(string);
if (utf8_length != string_length)
return false;
if (strncmp(utf8, string, utf8_length))
return false;
return true;
}
PP_Resource TestWebSocket::Connect() {
PP_Var protocols[] = { PP_MakeUndefined() };
PP_Resource ws = websocket_interface_->Create(instance_->pp_instance());
if (!ws)
return 0;
PP_Var url = CreateVar(kEchoServerURL);
TestCompletionCallback callback(instance_->pp_instance(), force_async_);
int32_t result = websocket_interface_->Connect(
ws, url, protocols, 0,
static_cast<pp::CompletionCallback>(callback).pp_completion_callback());
ReleaseVar(url);
if (force_async_ && result != PP_OK_COMPLETIONPENDING) {
core_interface_->ReleaseResource(ws);
return 0;
}
if (callback.WaitForResult() != PP_OK) {
core_interface_->ReleaseResource(ws);
return 0;
}
return ws;
} }
std::string TestWebSocket::TestIsWebSocket() { std::string TestWebSocket::TestIsWebSocket() {
// Test that a NULL resource isn't a websocket. // Test that a NULL resource isn't a websocket.
pp::Resource null_resource; pp::Resource null_resource;
if (websocket_interface_->IsWebSocket(null_resource.pp_resource())) PP_Bool result =
return "Null resource was reported as a valid websocket"; websocket_interface_->IsWebSocket(null_resource.pp_resource());
ASSERT_FALSE(result);
PP_Resource ws = websocket_interface_->Create(instance_->pp_instance()); PP_Resource ws = websocket_interface_->Create(instance_->pp_instance());
if (!websocket_interface_->IsWebSocket(ws)) ASSERT_TRUE(ws);
return "websocket was reported as an invalid websocket";
result = websocket_interface_->IsWebSocket(ws);
ASSERT_TRUE(result);
core_interface_->ReleaseResource(ws);
PASS(); PASS();
} }
std::string TestWebSocket::TestInvalidConnect() {
PP_Var protocols[] = { PP_MakeUndefined() };
PP_Resource ws = websocket_interface_->Create(instance_->pp_instance());
ASSERT_TRUE(ws);
TestCompletionCallback callback(instance_->pp_instance(), force_async_);
int32_t result = websocket_interface_->Connect(
ws, PP_MakeUndefined(), protocols, 1,
static_cast<pp::CompletionCallback>(callback).pp_completion_callback());
ASSERT_EQ(PP_ERROR_BADARGUMENT, result);
result = websocket_interface_->Connect(
ws, PP_MakeUndefined(), protocols, 1,
static_cast<pp::CompletionCallback>(callback).pp_completion_callback());
ASSERT_EQ(PP_ERROR_INPROGRESS, result);
core_interface_->ReleaseResource(ws);
const char* invalid_urls[] = {
"http://www.google.com/invalid_scheme",
"ws://www.google.com/invalid#fragment",
"ws://www.google.com:65535/invalid_port",
NULL
};
for (int i = 0; invalid_urls[i]; ++i) {
ws = websocket_interface_->Create(instance_->pp_instance());
ASSERT_TRUE(ws);
PP_Var invalid_url = CreateVar(invalid_urls[i]);
result = websocket_interface_->Connect(
ws, invalid_url, protocols, 0,
static_cast<pp::CompletionCallback>(
callback).pp_completion_callback());
ReleaseVar(invalid_url);
core_interface_->ReleaseResource(ws);
ASSERT_EQ(PP_ERROR_BADARGUMENT, result);
}
// TODO(toyoshim): Add invalid protocols tests
PASS();
}
std::string TestWebSocket::TestValidConnect() {
PP_Resource ws = websocket_interface_->Create(instance_->pp_instance());
PP_Var url = CreateVar(kEchoServerURL);
PP_Var protocols[] = { PP_MakeUndefined() };
TestCompletionCallback callback(instance_->pp_instance(), force_async_);
int32_t result = websocket_interface_->Connect(
ws, url, protocols, 0,
static_cast<pp::CompletionCallback>(callback).pp_completion_callback());
ReleaseVar(url);
ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
result = callback.WaitForResult();
ASSERT_EQ(PP_OK, result);
core_interface_->ReleaseResource(ws);
PASS();
}
// TODO(toyoshim): Add tests to call various interfaces before calling connect.
std::string TestWebSocket::TestTextSendReceive() {
// Connect to test echo server.
PP_Resource ws = Connect();
ASSERT_TRUE(ws);
// Send 'hello pepper' text message.
const char* message = "hello pepper";
PP_Var message_var = CreateVar(message);
int32_t result = websocket_interface_->SendMessage(ws, message_var);
ReleaseVar(message_var);
ASSERT_EQ(PP_OK, result);
// Receive echoed 'hello pepper'.
TestCompletionCallback callback(instance_->pp_instance(), force_async_);
PP_Var received_message;
result = websocket_interface_->ReceiveMessage(ws, &received_message,
static_cast<pp::CompletionCallback>(callback).pp_completion_callback());
ASSERT_FALSE(result != PP_OK && result != PP_OK_COMPLETIONPENDING);
if (result == PP_OK_COMPLETIONPENDING)
result = callback.WaitForResult();
ASSERT_EQ(PP_OK, result);
ASSERT_TRUE(AreEqual(received_message, message));
ReleaseVar(received_message);
core_interface_->ReleaseResource(ws);
PASS();
}
// TODO(toyoshim): Add other function tests.
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
#include "ppapi/tests/test_case.h" #include "ppapi/tests/test_case.h"
struct PPB_Core;
struct PPB_Var;
struct PPB_WebSocket_Dev; struct PPB_WebSocket_Dev;
class TestWebSocket : public TestCase { class TestWebSocket : public TestCase {
...@@ -20,11 +22,21 @@ class TestWebSocket : public TestCase { ...@@ -20,11 +22,21 @@ class TestWebSocket : public TestCase {
virtual void RunTests(const std::string& filter); virtual void RunTests(const std::string& filter);
private: private:
std::string TestCreate(); PP_Var CreateVar(const char* string);
void ReleaseVar(const PP_Var& var);
bool AreEqual(const PP_Var& var, const char* string);
PP_Resource Connect();
std::string TestIsWebSocket(); std::string TestIsWebSocket();
std::string TestInvalidConnect();
std::string TestValidConnect();
std::string TestTextSendReceive();
// Used by the tests that access the C API directly. // Used by the tests that access the C API directly.
const PPB_WebSocket_Dev* websocket_interface_; const PPB_WebSocket_Dev* websocket_interface_;
const PPB_Var* var_interface_;
const PPB_Core* core_interface_;
}; };
#endif // PAPPI_TESTS_TEST_WEBSOCKET_H_ #endif // PAPPI_TESTS_TEST_WEBSOCKET_H_
This diff is collapsed.
...@@ -5,8 +5,22 @@ ...@@ -5,8 +5,22 @@
#ifndef WEBKIT_PLUGINS_PPAPI_PPB_WEBSOCKET_IMPL_H_ #ifndef WEBKIT_PLUGINS_PPAPI_PPB_WEBSOCKET_IMPL_H_
#define WEBKIT_PLUGINS_PPAPI_PPB_WEBSOCKET_IMPL_H_ #define WEBKIT_PLUGINS_PPAPI_PPB_WEBSOCKET_IMPL_H_
#include <queue>
#include "base/memory/scoped_ptr.h"
#include "ppapi/shared_impl/resource.h" #include "ppapi/shared_impl/resource.h"
#include "ppapi/thunk/ppb_websocket_api.h" #include "ppapi/thunk/ppb_websocket_api.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebSocketClient.h"
struct PPB_Var;
namespace ppapi {
class StringVar;
}
namespace WebKit {
class WebSocket;
}
namespace webkit { namespace webkit {
namespace ppapi { namespace ppapi {
...@@ -14,7 +28,8 @@ namespace ppapi { ...@@ -14,7 +28,8 @@ namespace ppapi {
// All implementation is in this class for now. We should move some common // All implementation is in this class for now. We should move some common
// implementation to shared_impl when we implement proxy interfaces. // implementation to shared_impl when we implement proxy interfaces.
class PPB_WebSocket_Impl : public ::ppapi::Resource, class PPB_WebSocket_Impl : public ::ppapi::Resource,
public ::ppapi::thunk::PPB_WebSocket_API { public ::ppapi::thunk::PPB_WebSocket_API,
public ::WebKit::WebSocketClient {
public: public:
explicit PPB_WebSocket_Impl(PP_Instance instance); explicit PPB_WebSocket_Impl(PP_Instance instance);
virtual ~PPB_WebSocket_Impl(); virtual ~PPB_WebSocket_Impl();
...@@ -44,6 +59,41 @@ class PPB_WebSocket_Impl : public ::ppapi::Resource, ...@@ -44,6 +59,41 @@ class PPB_WebSocket_Impl : public ::ppapi::Resource,
virtual PP_WebSocketReadyState_Dev GetReadyState() OVERRIDE; virtual PP_WebSocketReadyState_Dev GetReadyState() OVERRIDE;
virtual PP_Var GetURL() OVERRIDE; virtual PP_Var GetURL() OVERRIDE;
// WebSocketClient implementation.
virtual void didConnect() OVERRIDE;
virtual void didReceiveMessage(const WebKit::WebString& message) OVERRIDE;
virtual void didReceiveBinaryData(
const WebKit::WebData& binaryData) OVERRIDE;
virtual void didReceiveMessageError() OVERRIDE;
virtual void didStartClosingHandshake() OVERRIDE;
virtual void didClose(unsigned long bufferedAmount,
ClosingHandshakeCompletionStatus status,
unsigned short code,
const WebKit::WebString& reason) OVERRIDE;
private:
int32_t DoReceive();
scoped_ptr<WebKit::WebSocket> websocket_;
PP_WebSocketReadyState_Dev state_;
PP_CompletionCallback connect_callback_;
PP_CompletionCallback receive_callback_;
PP_Var* receive_callback_var_;
bool wait_for_receive_;
// TODO(toyoshim): Use std::queue<Var> when it supports binary.
std::queue<PP_Var> received_messages_;
PP_CompletionCallback close_callback_;
uint16_t close_code_;
scoped_refptr< ::ppapi::StringVar> close_reason_;
PP_Bool close_was_clean_;
scoped_refptr< ::ppapi::StringVar> empty_string_;
scoped_refptr< ::ppapi::StringVar> extensions_;
scoped_refptr< ::ppapi::StringVar> protocol_;
scoped_refptr< ::ppapi::StringVar> url_;
DISALLOW_COPY_AND_ASSIGN(PPB_WebSocket_Impl); DISALLOW_COPY_AND_ASSIGN(PPB_WebSocket_Impl);
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment