From 3e919cb2ef7aacd8280200a36ef9f9323432caeb Mon Sep 17 00:00:00 2001 From: "toyoshim@chromium.org" Date: Fri, 16 Dec 2011 07:28:21 +0000 Subject: WebSocket Pepper API: C++ bindings implementation. This change contains simple straightforward C++ interfaces. JS like bindings will be implemented as a helper class in another change. BUG=87310 TEST=ui_tests --gtest_filter='PPAPITest.WebSocket_CcInterfaces' Review URL: http://codereview.chromium.org/8821010 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@114779 0039d316-1c4b-4281-b951-d872f2087c98 --- ppapi/api/dev/ppb_websocket_dev.idl | 99 ++++++++++++---------- ppapi/c/dev/ppb_websocket_dev.h | 101 ++++++++++++---------- ppapi/cpp/completion_callback.h | 2 + ppapi/cpp/dev/websocket_dev.cc | 148 ++++++++++++++++++++++++++++++++ ppapi/cpp/dev/websocket_dev.h | 164 +++++++++++++++++++++++------------- ppapi/ppapi_sources.gypi | 2 + ppapi/tests/test_websocket.cc | 62 ++++++++++++++ ppapi/tests/test_websocket.h | 2 + 8 files changed, 431 insertions(+), 149 deletions(-) create mode 100644 ppapi/cpp/dev/websocket_dev.cc (limited to 'ppapi') diff --git a/ppapi/api/dev/ppb_websocket_dev.idl b/ppapi/api/dev/ppb_websocket_dev.idl index 6dd0bd8..cd31296 100644 --- a/ppapi/api/dev/ppb_websocket_dev.idl +++ b/ppapi/api/dev/ppb_websocket_dev.idl @@ -110,14 +110,22 @@ interface PPB_WebSocket_Dev { * protocols. * * @param[in] callback A PP_CompletionCallback which is called - * when the connection is established or an error occurs in establishing + * when a connection is established or an error occurs in establishing * connection. * - * @return In case of immediate failure, returns an error code as follows. - * Returns PP_ERROR_BADARGUMENT corresponding to JavaScript - * SyntaxError and PP_ERROR_NOACCESS corresponding to JavaScript - * SecurityError. Otherwise, returns PP_OK_COMPLETIONPENDING - * and invokes callback later. + * @return An int32_t containing an error code from pp_errors.h. + * Returns PP_ERROR_BADARGUMENT if specified url, + * or protocols contains invalid string as + * The WebSocket API specification defines. It corresponds to + * SyntaxError of the specification. + * Returns PP_ERROR_NOACCESS if the protocol specified in the + * url is not a secure protocol, but the origin of the caller + * has a secure scheme. Also returns it if the port specified in the + * url is a port to which the user agent is configured to block + * access because the port is a well-known port like SMTP. It corresponds to + * SecurityError of the specification. + * Returns PP_ERROR_INPROGRESS if the call is not the first + * time. */ int32_t Connect([in] PP_Resource web_socket, [in] PP_Var url, @@ -140,14 +148,17 @@ interface PPB_WebSocket_Dev { * PP_VARTYPE_STRING. * * @param[in] callback A PP_CompletionCallback which is called - * when the connection is closed or an error occurs in closing connection. - * - * @return In case of immediate failure, returns an error code as follows. - * Returns PP_ERROR_BADARGUMENT corresponding to JavaScript - * SyntaxError and PP_ERROR_NOACCESS corresponding to JavaScript - * InvalidAccessError. Otherwise, returns - * PP_OK_COMPLETIONPENDING and invokes callback - * later. + * when the connection is closed or an error occurs in closing the + * connection. + * + * @return An int32_t containing an error code from pp_errors.h. + * Returns PP_ERROR_BADARGUMENT if reason contains + * an invalid character as a UTF-8 string, or longer than 123 bytes. It + * corresponds to JavaScript SyntaxError of the specification. + * Returns PP_ERROR_NOACCESS if the code is not an integer + * equal to 1000 or in the range 3000 to 4999. It corresponds to + * InvalidAccessError of the specification. Returns + * PP_ERROR_INPROGRESS if the call is not the first time. */ int32_t Close([in] PP_Resource web_socket, [in] uint16_t code, @@ -156,27 +167,26 @@ interface PPB_WebSocket_Dev { /** * ReceiveMessage() receives a message from the WebSocket server. - * This interface only returns bytes of a single message. That is, this - * interface must be called at least N times to receive N messages, no matter - * how small each message is. + * This interface only returns a single message. That is, this interface must + * be called at least N times to receive N messages, no matter how small each + * message is. * * @param[in] web_socket A PP_Resource corresponding to a * WebSocket. * * @param[out] message The received message is copied to provided - * message. + * message. The message must remain valid until + * the ReceiveMessage operation completes. * * @param[in] callback A PP_CompletionCallback which is called - * when the receiving message is completed. It is ignored when the function - * return PP_OK. - * - * @return In case of immediate failure, returns - * PP_ERROR_FAILED. If a message is currently available, returns - * PP_OK. Otherwise, returns - * and invokes callback later. At that case, if GetReadyState() - * returns PP_WEBSOCKETREADYSTATE_OPEN, the received - * message is also copied to procided message. Otherwise, - * the connection is closed and ReceiveMessage() failed to receive a message. + * when the receiving message is completed. It is ignored if ReceiveMessage + * completes synchronously and returns PP_OK. + * + * @return An int32_t containing an error code from pp_errors.h. + * If an error is detected or connection is closed, returns + * PP_ERROR_FAILED after all buffered messages are received. + * Until buffered message become empty, continues to returns + * PP_OK as if connection is still established without errors. */ int32_t ReceiveMessage([in] PP_Resource web_socket, [out] PP_Var message, @@ -192,12 +202,15 @@ interface PPB_WebSocket_Dev { * buffer. So caller can free message safely after returning * from the function. * - * @return In case of immediate failure, returns an error code as follows. - * Returns PP_ERROR_FAILED corresponding to JavaScript - * InvalidStateError and PP_ERROR_BADARGUMENT corresponding to - * JavaScript SyntaxError. Otherwise, return PP_OK. - * PP_OK doesn't necessarily mean that the server received the - * message. + * @return An int32_t containing an error code from pp_errors.h. + * Returns PP_ERROR_FAILED if the ReadyState is + * PP_WEBSOCKETREADYSTATE_CONNECTING_DEV. It corresponds + * JavaScript InvalidStateError of the specification. + * Returns PP_ERROR_BADARGUMENT if provided message + * of string type contains an invalid character as a UTF-8 string. It + * corresponds to JavaScript SyntaxError of the specification. + * Otherwise, returns PP_OK, but it doesn't necessarily mean + * that the server received the message. */ int32_t SendMessage([in] PP_Resource web_socket, [in] PP_Var message); @@ -207,10 +220,6 @@ interface PPB_WebSocket_Dev { * messages that have been queued for the WebSocket connection to send but * have not been transmitted to the network yet. * - * Note: This interface might not be able to return exact bytes in the first - * release. Current WebSocket implementation can not estimate exact protocol - * frame overheads. - * * @param[in] web_socket A PP_Resource corresponding to a * WebSocket. * @@ -236,8 +245,8 @@ interface PPB_WebSocket_Dev { * @param[in] web_socket A PP_Resource corresponding to a * WebSocket. * - * @return Returns a PP_VARTYPE_STRING var. if called before the - * close reason is set, its data is empty string. Returns a + * @return Returns a PP_VARTYPE_STRING var. If called before the + * close reason is set, it contains an empty string. Returns a * PP_VARTYPE_UNDEFINED if called on an invalid resource. */ PP_Var GetCloseReason([in] PP_Resource web_socket); @@ -252,7 +261,7 @@ interface PPB_WebSocket_Dev { * @return Returns PP_FALSE if called before the connection is * closed, or called on an invalid resource. Otherwise, returns * PP_TRUE if the connection was closed cleanly, or returns - * PP_FALSE if the connection was closed by abnormal reasons. + * PP_FALSE if the connection was closed for abnormal reasons. */ PP_Bool GetCloseWasClean([in] PP_Resource web_socket); @@ -264,9 +273,9 @@ interface PPB_WebSocket_Dev { * WebSocket. * * @return Returns a PP_VARTYPE_STRING var. If called before the - * connection is established, its data is empty string. Returns a + * connection is established, its data is an empty string. Returns a * PP_VARTYPE_UNDEFINED if called on an invalid resource. - * Currently its data for valid resources are always empty string. + * Currently its data for valid resources are always an empty string. */ PP_Var GetExtensions([in] PP_Resource web_socket); @@ -278,7 +287,7 @@ interface PPB_WebSocket_Dev { * WebSocket. * * @return Returns a PP_VARTYPE_STRING var. If called before the - * connection is established, its data is empty string. Returns a + * connection is established, it contains the empty string. Returns a * PP_VARTYPE_UNDEFINED if called on an invalid resource. */ PP_Var GetProtocol([in] PP_Resource web_socket); @@ -302,7 +311,7 @@ interface PPB_WebSocket_Dev { * WebSocket. * * @return Returns a PP_VARTYPE_STRING var. If called before the - * connection is established, its data is empty string. Return a + * connection is established, it contains the empty string. Return a * PP_VARTYPE_UNDEFINED if called on an invalid resource. */ PP_Var GetURL([in] PP_Resource web_socket); diff --git a/ppapi/c/dev/ppb_websocket_dev.h b/ppapi/c/dev/ppb_websocket_dev.h index 0e54db1..34bad3b 100644 --- a/ppapi/c/dev/ppb_websocket_dev.h +++ b/ppapi/c/dev/ppb_websocket_dev.h @@ -3,7 +3,7 @@ * found in the LICENSE file. */ -/* From dev/ppb_websocket_dev.idl modified Wed Nov 16 02:46:08 2011. */ +/* From dev/ppb_websocket_dev.idl modified Fri Dec 16 14:25:06 2011. */ #ifndef PPAPI_C_DEV_PPB_WEBSOCKET_DEV_H_ #define PPAPI_C_DEV_PPB_WEBSOCKET_DEV_H_ @@ -128,14 +128,22 @@ struct PPB_WebSocket_Dev { * protocols. * * @param[in] callback A PP_CompletionCallback which is called - * when the connection is established or an error occurs in establishing + * when a connection is established or an error occurs in establishing * connection. * - * @return In case of immediate failure, returns an error code as follows. - * Returns PP_ERROR_BADARGUMENT corresponding to JavaScript - * SyntaxError and PP_ERROR_NOACCESS corresponding to JavaScript - * SecurityError. Otherwise, returns PP_OK_COMPLETIONPENDING - * and invokes callback later. + * @return An int32_t containing an error code from pp_errors.h. + * Returns PP_ERROR_BADARGUMENT if specified url, + * or protocols contains invalid string as + * The WebSocket API specification defines. It corresponds to + * SyntaxError of the specification. + * Returns PP_ERROR_NOACCESS if the protocol specified in the + * url is not a secure protocol, but the origin of the caller + * has a secure scheme. Also returns it if the port specified in the + * url is a port to which the user agent is configured to block + * access because the port is a well-known port like SMTP. It corresponds to + * SecurityError of the specification. + * Returns PP_ERROR_INPROGRESS if the call is not the first + * time. */ int32_t (*Connect)(PP_Resource web_socket, struct PP_Var url, @@ -157,14 +165,17 @@ struct PPB_WebSocket_Dev { * PP_VARTYPE_STRING. * * @param[in] callback A PP_CompletionCallback which is called - * when the connection is closed or an error occurs in closing connection. - * - * @return In case of immediate failure, returns an error code as follows. - * Returns PP_ERROR_BADARGUMENT corresponding to JavaScript - * SyntaxError and PP_ERROR_NOACCESS corresponding to JavaScript - * InvalidAccessError. Otherwise, returns - * PP_OK_COMPLETIONPENDING and invokes callback - * later. + * when the connection is closed or an error occurs in closing the + * connection. + * + * @return An int32_t containing an error code from pp_errors.h. + * Returns PP_ERROR_BADARGUMENT if reason contains + * an invalid character as a UTF-8 string, or longer than 123 bytes. It + * corresponds to JavaScript SyntaxError of the specification. + * Returns PP_ERROR_NOACCESS if the code is not an integer + * equal to 1000 or in the range 3000 to 4999. It corresponds to + * InvalidAccessError of the specification. Returns + * PP_ERROR_INPROGRESS if the call is not the first time. */ int32_t (*Close)(PP_Resource web_socket, uint16_t code, @@ -172,27 +183,26 @@ struct PPB_WebSocket_Dev { struct PP_CompletionCallback callback); /** * ReceiveMessage() receives a message from the WebSocket server. - * This interface only returns bytes of a single message. That is, this - * interface must be called at least N times to receive N messages, no matter - * how small each message is. + * This interface only returns a single message. That is, this interface must + * be called at least N times to receive N messages, no matter how small each + * message is. * * @param[in] web_socket A PP_Resource corresponding to a * WebSocket. * * @param[out] message The received message is copied to provided - * message. + * message. The message must remain valid until + * the ReceiveMessage operation completes. * * @param[in] callback A PP_CompletionCallback which is called - * when the receiving message is completed. It is ignored when the function - * return PP_OK. - * - * @return In case of immediate failure, returns - * PP_ERROR_FAILED. If a message is currently available, returns - * PP_OK. Otherwise, returns - * and invokes callback later. At that case, if GetReadyState() - * returns PP_WEBSOCKETREADYSTATE_OPEN, the received - * message is also copied to procided message. Otherwise, - * the connection is closed and ReceiveMessage() failed to receive a message. + * when the receiving message is completed. It is ignored if ReceiveMessage + * completes synchronously and returns PP_OK. + * + * @return An int32_t containing an error code from pp_errors.h. + * If an error is detected or connection is closed, returns + * PP_ERROR_FAILED after all buffered messages are received. + * Until buffered message become empty, continues to returns + * PP_OK as if connection is still established without errors. */ int32_t (*ReceiveMessage)(PP_Resource web_socket, struct PP_Var* message, @@ -207,12 +217,15 @@ struct PPB_WebSocket_Dev { * buffer. So caller can free message safely after returning * from the function. * - * @return In case of immediate failure, returns an error code as follows. - * Returns PP_ERROR_FAILED corresponding to JavaScript - * InvalidStateError and PP_ERROR_BADARGUMENT corresponding to - * JavaScript SyntaxError. Otherwise, return PP_OK. - * PP_OK doesn't necessarily mean that the server received the - * message. + * @return An int32_t containing an error code from pp_errors.h. + * Returns PP_ERROR_FAILED if the ReadyState is + * PP_WEBSOCKETREADYSTATE_CONNECTING_DEV. It corresponds + * JavaScript InvalidStateError of the specification. + * Returns PP_ERROR_BADARGUMENT if provided message + * of string type contains an invalid character as a UTF-8 string. It + * corresponds to JavaScript SyntaxError of the specification. + * Otherwise, returns PP_OK, but it doesn't necessarily mean + * that the server received the message. */ int32_t (*SendMessage)(PP_Resource web_socket, struct PP_Var message); /** @@ -220,10 +233,6 @@ struct PPB_WebSocket_Dev { * messages that have been queued for the WebSocket connection to send but * have not been transmitted to the network yet. * - * Note: This interface might not be able to return exact bytes in the first - * release. Current WebSocket implementation can not estimate exact protocol - * frame overheads. - * * @param[in] web_socket A PP_Resource corresponding to a * WebSocket. * @@ -247,8 +256,8 @@ struct PPB_WebSocket_Dev { * @param[in] web_socket A PP_Resource corresponding to a * WebSocket. * - * @return Returns a PP_VARTYPE_STRING var. if called before the - * close reason is set, its data is empty string. Returns a + * @return Returns a PP_VARTYPE_STRING var. If called before the + * close reason is set, it contains an empty string. Returns a * PP_VARTYPE_UNDEFINED if called on an invalid resource. */ struct PP_Var (*GetCloseReason)(PP_Resource web_socket); @@ -262,7 +271,7 @@ struct PPB_WebSocket_Dev { * @return Returns PP_FALSE if called before the connection is * closed, or called on an invalid resource. Otherwise, returns * PP_TRUE if the connection was closed cleanly, or returns - * PP_FALSE if the connection was closed by abnormal reasons. + * PP_FALSE if the connection was closed for abnormal reasons. */ PP_Bool (*GetCloseWasClean)(PP_Resource web_socket); /** @@ -273,9 +282,9 @@ struct PPB_WebSocket_Dev { * WebSocket. * * @return Returns a PP_VARTYPE_STRING var. If called before the - * connection is established, its data is empty string. Returns a + * connection is established, its data is an empty string. Returns a * PP_VARTYPE_UNDEFINED if called on an invalid resource. - * Currently its data for valid resources are always empty string. + * Currently its data for valid resources are always an empty string. */ struct PP_Var (*GetExtensions)(PP_Resource web_socket); /** @@ -286,7 +295,7 @@ struct PPB_WebSocket_Dev { * WebSocket. * * @return Returns a PP_VARTYPE_STRING var. If called before the - * connection is established, its data is empty string. Returns a + * connection is established, it contains the empty string. Returns a * PP_VARTYPE_UNDEFINED if called on an invalid resource. */ struct PP_Var (*GetProtocol)(PP_Resource web_socket); @@ -308,7 +317,7 @@ struct PPB_WebSocket_Dev { * WebSocket. * * @return Returns a PP_VARTYPE_STRING var. If called before the - * connection is established, its data is empty string. Return a + * connection is established, it contains the empty string. Return a * PP_VARTYPE_UNDEFINED if called on an invalid resource. */ struct PP_Var (*GetURL)(PP_Resource web_socket); diff --git a/ppapi/cpp/completion_callback.h b/ppapi/cpp/completion_callback.h index e83616e..2e5f38b 100644 --- a/ppapi/cpp/completion_callback.h +++ b/ppapi/cpp/completion_callback.h @@ -179,6 +179,8 @@ CompletionCallback BlockUntilComplete(); /// /// class MyHandler { /// public: +/// // If an compiler warns on following using |this| in the initializer +/// // list, use PP_ALLOW_THIS_IN_INITIALIZER_LIST macro. /// MyHandler() : factory_(this), offset_(0) { /// } /// diff --git a/ppapi/cpp/dev/websocket_dev.cc b/ppapi/cpp/dev/websocket_dev.cc new file mode 100644 index 0000000..52ffdba --- /dev/null +++ b/ppapi/cpp/dev/websocket_dev.cc @@ -0,0 +1,148 @@ +// 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/cpp/dev/websocket_dev.h" + +#include "ppapi/c/pp_errors.h" +#include "ppapi/c/pp_macros.h" +#include "ppapi/cpp/completion_callback.h" +#include "ppapi/cpp/instance.h" +#include "ppapi/cpp/module.h" +#include "ppapi/cpp/module_impl.h" +#include "ppapi/cpp/var.h" + +namespace pp { + +namespace { + +template <> const char* interface_name() { + return PPB_WEBSOCKET_DEV_INTERFACE; +} + +} // namespace + +WebSocket_Dev::WebSocket_Dev(Instance* instance) { + if (!has_interface()) + return; + PassRefFromConstructor(get_interface()->Create( + instance->pp_instance())); +} + +WebSocket_Dev::~WebSocket_Dev() { +} + +int32_t WebSocket_Dev::Connect(const Var& url, const Var protocols[], + uint32_t protocol_count, const CompletionCallback& callback) { + if (!has_interface()) + return PP_ERROR_BADRESOURCE; + + // Convert protocols to C interface. + PP_Var *c_protocols = NULL; + if (protocol_count) { + c_protocols = new PP_Var[protocol_count]; + if (!c_protocols) + return PP_ERROR_NOMEMORY; + } + for (uint32_t i = 0; i < protocol_count; ++i) + c_protocols[i] = protocols[i].pp_var(); + + int32_t result = get_interface()->Connect( + pp_resource(), url.pp_var(), c_protocols, protocol_count, + callback.pp_completion_callback()); + if (c_protocols) + delete[] c_protocols; + return result; +} + +int32_t WebSocket_Dev::Close(uint16_t code, const Var& reason, + const CompletionCallback& callback) { + if (!has_interface()) + return PP_ERROR_BADRESOURCE; + + return get_interface()->Close( + pp_resource(), code, reason.pp_var(), + callback.pp_completion_callback()); +} + +int32_t WebSocket_Dev::ReceiveMessage(Var* message, + const CompletionCallback& callback) { + if (!has_interface()) + return PP_ERROR_BADRESOURCE; + + return get_interface()->ReceiveMessage( + pp_resource(), const_cast(&message->pp_var()), + callback.pp_completion_callback()); +} + +int32_t WebSocket_Dev::SendMessage(const Var& message) { + if (!has_interface()) + return PP_ERROR_BADRESOURCE; + + return get_interface()->SendMessage( + pp_resource(), message.pp_var()); +} + +uint64_t WebSocket_Dev::GetBufferedAmount() { + if (!has_interface()) + return 0; + + return get_interface()->GetBufferedAmount(pp_resource()); +} + +uint16_t WebSocket_Dev::GetCloseCode() { + if (!has_interface()) + return 0; + + return get_interface()->GetCloseCode(pp_resource()); +} + +Var WebSocket_Dev::GetCloseReason() { + if (!has_interface()) + return 0; + + return Var(Var::PassRef(), + get_interface()->GetCloseReason(pp_resource())); +} + +bool WebSocket_Dev::GetCloseWasClean() { + if (!has_interface()) + return false; + + PP_Bool result = + get_interface()->GetCloseWasClean(pp_resource()); + return PP_ToBool(result); +} + +Var WebSocket_Dev::GetExtensions() { + if (!has_interface()) + return Var(); + + return Var(Var::PassRef(), + get_interface()->GetExtensions(pp_resource())); +} + +Var WebSocket_Dev::GetProtocol() { + if (!has_interface()) + return Var(); + + return Var(Var::PassRef(), + get_interface()->GetProtocol(pp_resource())); +} + +PP_WebSocketReadyState_Dev WebSocket_Dev::GetReadyState() { + if (!has_interface()) + return PP_WEBSOCKETREADYSTATE_INVALID_DEV; + + return get_interface()->GetReadyState(pp_resource()); +} + +Var WebSocket_Dev::GetURL() { + if (!has_interface()) + return Var(); + + return Var(Var::PassRef(), + get_interface()->GetURL(pp_resource())); +} + +} // namespace pp diff --git a/ppapi/cpp/dev/websocket_dev.h b/ppapi/cpp/dev/websocket_dev.h index 8b25b8e..42981f6 100644 --- a/ppapi/cpp/dev/websocket_dev.h +++ b/ppapi/cpp/dev/websocket_dev.h @@ -6,20 +6,22 @@ #define PPAPI_CPP_DEV_WEBSOCKET_DEV_H_ #include "ppapi/c/dev/ppb_websocket_dev.h" +#include "ppapi/cpp/resource.h" /// @file /// This file defines the WebSocket_Dev interface. namespace pp { +class CompletionCallback; +class Instance; class Var; /// The WebSocket_Dev class -/// A version that use virtual functions class WebSocket_Dev : public Resource { public: /// Constructs a WebSocket_Dev object. - WebSocket_Dev(); + WebSocket_Dev(Instance* instance); /// Destructs a WebSocket_Dev object. virtual ~WebSocket_Dev(); @@ -27,40 +29,77 @@ class WebSocket_Dev : public Resource { /// Connect() connects to the specified WebSocket server. Caller can call /// this method at most once. /// - /// @param[in] url A PP_Var representing a WebSocket server URL. - /// The PP_VarType must be PP_VARTYPE_STRING. - /// @param[in] protocols A pointer to an array of PP_Var - /// specifying sub-protocols. Each PP_Var represents one - /// sub-protocol and its PP_VarType must be - /// PP_VARTYPE_STRING. This argument can be null only if + /// @param[in] url A Var of string type representing a WebSocket + /// server URL. + /// @param[in] protocols A pointer to an array of string type + /// Var specifying sub-protocols. Each Var + /// represents one sub-protocol. This argument can be null only if /// protocol_count is 0. /// @param[in] protocol_count The number of sub-protocols in /// protocols. + /// @param[in] callback A CompletionCallback which is called + /// when a connection is established or an error occurs in establishing + /// connection. /// - /// @return In case of immediate failure, returns an error code as follows. - /// Returns PP_ERROR_BADARGUMENT corresponding to JavaScript - /// SyntaxError and PP_ERROR_NOACCESS corresponding to - /// JavaScript SecurityError. Otherwise, returns - /// PP_OK_COMPLETIONPENDING and later invokes - /// OnOpen() on success or OnClose() on failure. + /// @return An int32_t containing an error code from + /// pp_errors.h. + /// Returns PP_ERROR_BADARGUMENT if specified url, + /// or protocols contains invalid string as + /// The WebSocket API specification defines. It corresponds to + /// SyntaxError of the specification. + /// Returns PP_ERROR_NOACCESS if the protocol specified in the + /// url is not a secure protocol, but the origin of the caller + /// has a secure scheme. Also returns it if the port specified in the + /// url is a port to which the user agent is configured to block + /// access because the port is a well-known port like SMTP. It corresponds to + /// SecurityError of the specification. + /// Returns PP_ERROR_INPROGRESS if the call is not the first + /// time. int32_t Connect(const Var& url, const Var protocols[], - uint32_t protocol_count); + uint32_t protocol_count, const CompletionCallback& callback); /// Close() closes the specified WebSocket connection by specifying /// code and reason. /// /// @param[in] code The WebSocket close code. Ignored if it is 0. - /// @param[in] reason A PP_Var which represents the WebSocket - /// close reason. Ignored if it is PP_VARTYPE_UNDEFINED. - /// Otherwise, its PP_VarType must be - /// PP_VARTYPE_STRING. - /// - /// @return In case of immediate failure, returns an error code as follows. - /// Returns PP_ERROR_BADARGUMENT corresponding to JavaScript - /// SyntaxError and PP_ERROR_NOACCESS corresponding to - /// JavaScript InvalidAccessError. Otherwise, returns - /// PP_OK_COMPLETIONPENDING and invokes OnClose. - int32_t Close(uint16_t code, const Var& reason); + /// @param[in] reason A Var of string type which represents the + /// WebSocket close reason. Ignored if it is undefined type. + /// @param[in] callback A CompletionCallback which is called + /// when the connection is closed or an error occurs in closing the + /// connection. + /// + /// @return An int32_t containing an error code from + /// pp_errors.h. + /// Returns PP_ERROR_BADARGUMENT if reason contains + /// an invalid character as a UTF-8 string, or longer than 123 bytes. It + /// corresponds to JavaScript SyntaxError of the specification. + /// Returns PP_ERROR_NOACCESS if the code is not an integer + /// equal to 1000 or in the range 3000 to 4999. It corresponds to + /// InvalidAccessError of the specification. Returns + /// PP_ERROR_INPROGRESS if the call is not the first time. + int32_t Close(uint16_t code, const Var& reason, + const CompletionCallback& callback); + + /// ReceiveMessage() receives a message from the WebSocket server. + /// This interface only returns a single message. That is, this interface + /// must be called at least N times to receive N messages, no matter how + /// small each message is. + /// + /// @param[out] message The received message is copied to provided + /// message. The message must remain valid until + /// the ReceiveMessage operation completes. + /// @param[in] callback A CompletionCallback which is called + /// when the receiving message is completed. It is ignored if ReceiveMessage + /// completes synchronously and returns PP_OK. + /// + /// @return An int32_t containing an error code from + /// pp_errors.h. + /// If an error is detected or connection is closed, returns + /// PP_ERROR_FAILED after all buffered messages are received. + /// Until buffered message become empty, continues to returns + /// PP_OK as if connection is still established without errors. + int32_t ReceiveMessage(Var* message, + const CompletionCallback& callback); /// Send() sends a message to the WebSocket server. /// @@ -68,38 +107,61 @@ class WebSocket_Dev : public Resource { /// buffer. So caller can free data safely after returning /// from the function. /// - /// @return In case of immediate failure, returns an error code as follows. - /// Returns PP_ERROR_FAILED corresponding to JavaScript - /// InvalidStateError and PP_ERROR_BADARGUMENT corresponding to - /// JavaScript SyntaxError. Otherwise, return PP_OK. - /// PP_OK doesn't necessarily mean that the server received the - /// message. - int32_t Send(const Var& data); + /// @return An int32_t containing an error code from + /// pp_errors.h. + /// Returns PP_ERROR_FAILED if the ReadyState is + /// PP_WEBSOCKETREADYSTATE_CONNECTING_DEV. It corresponds + /// JavaScript InvalidStateError of the specification. + /// Returns PP_ERROR_BADARGUMENT if provided + /// message of string type contains an invalid character as a + /// UTF-8 string. It corresponds to JavaScript SyntaxError of the + /// specification. + /// Otherwise, returns PP_OK, but it doesn't necessarily mean + /// that the server received the message. + int32_t SendMessage(const Var& message); /// GetBufferedAmount() returns the number of bytes of text and binary /// messages that have been queued for the WebSocket connection to send but /// have not been transmitted to the network yet. /// - /// Note: This interface might not be able to return exact bytes in the first - /// release. Current WebSocket implementation can not estimate exact protocol - /// frame overheads. - /// /// @return Returns the number of bytes. uint64_t GetBufferedAmount(); + /// GetCloseCode() returns the connection close code for the WebSocket + /// connection. + /// + /// @return Returns 0 if called before the close code is set. + uint16_t GetCloseCode(); + + /// GetCloseReason() returns the connection close reason for the WebSocket + /// connection. + /// + /// @return Returns a Var of string type. If called before the + /// close reason is set, it contains an empty string. + Var GetCloseReason(); + + /// GetCloseWasClean() returns if the connection was closed cleanly for the + /// specified WebSocket connection. + /// + /// @return Returns false if called before the connection is + /// closed, or called on an invalid resource. Otherwise, returns + /// true if the connection was closed cleanly, or returns + /// false if the connection was closed for abnormal reasons. + bool GetCloseWasClean(); + /// GetExtensions() returns the extensions selected by the server for the /// specified WebSocket connection. /// - /// @return Returns a PP_VARTYPE_STRING var. If called before - /// the connection is established, its data is empty string. - /// Currently its data is always empty string. + /// @return Returns a Var of string type. If called before the + /// connection is established, its data is an empty string. + /// Currently its data is always an empty string. Var GetExtensions(); /// GetProtocol() returns the sub-protocol chosen by the server for the /// specified WebSocket connection. /// - /// @return Returns a PP_VARTYPE_STRING var. If called before - /// the connection is established, its data is empty string. + /// @return Returns a Var of string type. If called before the + /// connection is established, it contains the empty string. Var GetProtocol(); /// GetReadyState() returns the ready state of the specified WebSocket @@ -111,23 +173,9 @@ class WebSocket_Dev : public Resource { /// GetURL() returns the URL associated with specified WebSocket connection. /// - /// @return Returns a PP_VARTYPE_STRING var. If called before - /// the connection is established, its data is empty string. + /// @return Returns a Var of string type. If called before the + /// connection is established, it contains the empty string. Var GetURL(); - - /// OnOpen() is invoked when the connection is established by Connect(). - virtual void OnOpen() = 0; - - /// OnMessage() is invoked when a message is received. - virtual void OnMessage(Var message) = 0; - - /// OnError() is invoked if the user agent was required to fail the WebSocket - /// connection or the WebSocket connection is closed with prejudice. - /// OnClose() always follows OnError(). - virtual void OnError() = 0; - - /// OnClose() is invoked when the connection is closed by errors or Close(). - virtual void OnClose(bool wasClean, uint16_t code, const Var& reason) = 0; }; } // namespace pp diff --git a/ppapi/ppapi_sources.gypi b/ppapi/ppapi_sources.gypi index e4fb62f..00323d6 100644 --- a/ppapi/ppapi_sources.gypi +++ b/ppapi/ppapi_sources.gypi @@ -211,6 +211,8 @@ 'cpp/dev/video_decoder_client_dev.h', 'cpp/dev/video_decoder_dev.cc', 'cpp/dev/video_decoder_dev.h', + 'cpp/dev/websocket_dev.cc', + 'cpp/dev/websocket_dev.h', 'cpp/dev/widget_client_dev.cc', 'cpp/dev/widget_client_dev.h', 'cpp/dev/widget_dev.cc', diff --git a/ppapi/tests/test_websocket.cc b/ppapi/tests/test_websocket.cc index c990113..ae1db54 100644 --- a/ppapi/tests/test_websocket.cc +++ b/ppapi/tests/test_websocket.cc @@ -5,6 +5,7 @@ #include "ppapi/tests/test_websocket.h" #include +#include #include "ppapi/c/dev/ppb_testing_dev.h" #include "ppapi/c/dev/ppb_websocket_dev.h" @@ -13,6 +14,7 @@ #include "ppapi/c/pp_completion_callback.h" #include "ppapi/c/ppb_core.h" #include "ppapi/c/ppb_var.h" +#include "ppapi/cpp/dev/websocket_dev.h" #include "ppapi/cpp/instance.h" #include "ppapi/cpp/module.h" #include "ppapi/tests/test_utils.h" @@ -21,6 +23,9 @@ const char kEchoServerURL[] = "ws://localhost:8880/websocket/tests/hybi/echo"; +const char kCloseServerURL[] = + "ws://localhost:8880/websocket/tests/hybi/close"; + const char kProtocolTestServerURL[] = "ws://localhost:8880/websocket/tests/hybi/protocol-test?protocol="; @@ -62,6 +67,8 @@ void TestWebSocket::RunTests(const std::string& filter) { RUN_TEST_WITH_REFERENCE_CHECK(ValidClose, filter); RUN_TEST_WITH_REFERENCE_CHECK(GetProtocol, filter); RUN_TEST_WITH_REFERENCE_CHECK(TextSendReceive, filter); + + RUN_TEST_WITH_REFERENCE_CHECK(CcInterfaces, filter); } PP_Var TestWebSocket::CreateVar(const char* string) { @@ -414,3 +421,58 @@ std::string TestWebSocket::TestTextSendReceive() { // TODO(toyoshim): Add tests for didReceiveMessageError(). // TODO(toyoshim): Add other function tests. + +std::string TestWebSocket::TestCcInterfaces() { + // C++ bindings is simple straightforward, then just verifies interfaces work + // as a interface bridge fine. + pp::WebSocket_Dev ws(instance_); + + // Check uninitialized properties access. + ASSERT_EQ(0, ws.GetBufferedAmount()); + ASSERT_EQ(0, ws.GetCloseCode()); + ASSERT_TRUE(AreEqual(ws.GetCloseReason().pp_var(), "")); + ASSERT_EQ(false, ws.GetCloseWasClean()); + ASSERT_TRUE(AreEqual(ws.GetExtensions().pp_var(), "")); + ASSERT_TRUE(AreEqual(ws.GetProtocol().pp_var(), "")); + ASSERT_EQ(PP_WEBSOCKETREADYSTATE_INVALID_DEV, ws.GetReadyState()); + ASSERT_TRUE(AreEqual(ws.GetURL().pp_var(), "")); + + // Check communication interfaces (connect, send, receive, and close). + TestCompletionCallback connect_callback(instance_->pp_instance()); + int32_t result = ws.Connect(pp::Var(std::string(kCloseServerURL)), NULL, 0U, + connect_callback); + ASSERT_EQ(PP_OK_COMPLETIONPENDING, result); + result = connect_callback.WaitForResult(); + ASSERT_EQ(PP_OK, result); + + std::string message("hello C++"); + result = ws.SendMessage(pp::Var(message)); + ASSERT_EQ(PP_OK, result); + + pp::Var receive_var; + TestCompletionCallback receive_callback(instance_->pp_instance()); + result = ws.ReceiveMessage(&receive_var, receive_callback); + if (result == PP_OK_COMPLETIONPENDING) + result = receive_callback.WaitForResult(); + ASSERT_EQ(PP_OK, result); + ASSERT_TRUE(AreEqual(receive_var.pp_var(), message.c_str())); + + TestCompletionCallback close_callback(instance_->pp_instance()); + std::string reason("bye"); + result = ws.Close(kCloseCodeNormalClosure, pp::Var(reason), close_callback); + ASSERT_EQ(PP_OK_COMPLETIONPENDING, result); + result = close_callback.WaitForResult(); + ASSERT_EQ(PP_OK, result); + + // Check initialized properties access. + ASSERT_EQ(0, ws.GetBufferedAmount()); + ASSERT_EQ(kCloseCodeNormalClosure, ws.GetCloseCode()); + ASSERT_TRUE(AreEqual(ws.GetCloseReason().pp_var(), reason.c_str())); + ASSERT_EQ(true, ws.GetCloseWasClean()); + ASSERT_TRUE(AreEqual(ws.GetExtensions().pp_var(), "")); + ASSERT_TRUE(AreEqual(ws.GetProtocol().pp_var(), "")); + ASSERT_EQ(PP_WEBSOCKETREADYSTATE_CLOSED_DEV, ws.GetReadyState()); + ASSERT_TRUE(AreEqual(ws.GetURL().pp_var(), kCloseServerURL)); + + PASS(); +} diff --git a/ppapi/tests/test_websocket.h b/ppapi/tests/test_websocket.h index 6cdf028..4048458 100644 --- a/ppapi/tests/test_websocket.h +++ b/ppapi/tests/test_websocket.h @@ -39,6 +39,8 @@ class TestWebSocket : public TestCase { std::string TestGetProtocol(); std::string TestTextSendReceive(); + std::string TestCcInterfaces(); + // Used by the tests that access the C API directly. const PPB_WebSocket_Dev* websocket_interface_; const PPB_Var* var_interface_; -- cgit v1.1