diff options
-rw-r--r-- | chrome/test/ui/ppapi_uitest.cc | 1 | ||||
-rw-r--r-- | ppapi/api/dev/ppb_websocket_dev.idl | 99 | ||||
-rw-r--r-- | ppapi/c/dev/ppb_websocket_dev.h | 101 | ||||
-rw-r--r-- | ppapi/cpp/completion_callback.h | 2 | ||||
-rw-r--r-- | ppapi/cpp/dev/websocket_dev.cc | 148 | ||||
-rw-r--r-- | ppapi/cpp/dev/websocket_dev.h | 164 | ||||
-rw-r--r-- | ppapi/ppapi_sources.gypi | 2 | ||||
-rw-r--r-- | ppapi/tests/test_websocket.cc | 62 | ||||
-rw-r--r-- | ppapi/tests/test_websocket.h | 2 |
9 files changed, 432 insertions, 149 deletions
diff --git a/chrome/test/ui/ppapi_uitest.cc b/chrome/test/ui/ppapi_uitest.cc index 02a2f2e..60e8490 100644 --- a/chrome/test/ui/ppapi_uitest.cc +++ b/chrome/test/ui/ppapi_uitest.cc @@ -597,6 +597,7 @@ TEST_PPAPI_IN_PROCESS_WITH_WS(WebSocket_InvalidClose) TEST_PPAPI_IN_PROCESS_WITH_WS(WebSocket_ValidClose) TEST_PPAPI_IN_PROCESS_WITH_WS(WebSocket_GetProtocol) TEST_PPAPI_IN_PROCESS_WITH_WS(WebSocket_TextSendReceive) +TEST_PPAPI_IN_PROCESS_WITH_WS(WebSocket_CcInterfaces) TEST_PPAPI_IN_PROCESS(AudioConfig_ValidConfigs) TEST_PPAPI_IN_PROCESS(AudioConfig_InvalidConfigs) 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 { * <code>protocols</code>. * * @param[in] callback A <code>PP_CompletionCallback</code> 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 <code>PP_ERROR_BADARGUMENT</code> corresponding to JavaScript - * SyntaxError and <code>PP_ERROR_NOACCESS</code> corresponding to JavaScript - * SecurityError. Otherwise, returns <code>PP_OK_COMPLETIONPENDING</code> - * and invokes <code>callback</code> later. + * @return An int32_t containing an error code from <code>pp_errors.h</code>. + * Returns <code>PP_ERROR_BADARGUMENT</code> if specified <code>url</code>, + * or <code>protocols</code> contains invalid string as + * <code>The WebSocket API specification</code> defines. It corresponds to + * SyntaxError of the specification. + * Returns <code>PP_ERROR_NOACCESS</code> if the protocol specified in the + * <code>url</code> is not a secure protocol, but the origin of the caller + * has a secure scheme. Also returns it if the port specified in the + * <code>url</code> 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 <code>PP_ERROR_INPROGRESS</code> 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 { * <code>PP_VARTYPE_STRING</code>. * * @param[in] callback A <code>PP_CompletionCallback</code> 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 <code>PP_ERROR_BADARGUMENT</code> corresponding to JavaScript - * SyntaxError and <code>PP_ERROR_NOACCESS</code> corresponding to JavaScript - * InvalidAccessError. Otherwise, returns - * <code>PP_OK_COMPLETIONPENDING</code> and invokes <code>callback</code> - * later. + * when the connection is closed or an error occurs in closing the + * connection. + * + * @return An int32_t containing an error code from <code>pp_errors.h</code>. + * Returns <code>PP_ERROR_BADARGUMENT</code> if <code>reason</code> contains + * an invalid character as a UTF-8 string, or longer than 123 bytes. It + * corresponds to JavaScript SyntaxError of the specification. + * Returns <code>PP_ERROR_NOACCESS</code> 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 + * <code>PP_ERROR_INPROGRESS</code> 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 <code>PP_Resource</code> corresponding to a * WebSocket. * * @param[out] message The received message is copied to provided - * <code>message</code>. + * <code>message</code>. The <code>message</code> must remain valid until + * the ReceiveMessage operation completes. * * @param[in] callback A <code>PP_CompletionCallback</code> which is called - * when the receiving message is completed. It is ignored when the function - * return <code>PP_OK</code>. - * - * @return In case of immediate failure, returns - * <code>PP_ERROR_FAILED</code>. If a message is currently available, returns - * <code>PP_OK</code>. Otherwise, returns <PP_OK_COMPLETIONPENDING</code> - * and invokes <code>callback</code> later. At that case, if GetReadyState() - * returns <code>PP_WEBSOCKETREADYSTATE_OPEN</code>, the received - * message is also copied to procided <code>message</code>. 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 <code>PP_OK</code>. + * + * @return An int32_t containing an error code from <code>pp_errors.h</code>. + * If an error is detected or connection is closed, returns + * <code>PP_ERROR_FAILED</code> after all buffered messages are received. + * Until buffered message become empty, continues to returns + * <code>PP_OK</code> 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 <code>message</code> safely after returning * from the function. * - * @return In case of immediate failure, returns an error code as follows. - * Returns <code>PP_ERROR_FAILED</code> corresponding to JavaScript - * InvalidStateError and <code>PP_ERROR_BADARGUMENT</code> corresponding to - * JavaScript SyntaxError. Otherwise, return <code>PP_OK</code>. - * <code>PP_OK</code> doesn't necessarily mean that the server received the - * message. + * @return An int32_t containing an error code from <code>pp_errors.h</code>. + * Returns <code>PP_ERROR_FAILED</code> if the ReadyState is + * <code>PP_WEBSOCKETREADYSTATE_CONNECTING_DEV</code>. It corresponds + * JavaScript InvalidStateError of the specification. + * Returns <code>PP_ERROR_BADARGUMENT</code> if provided <code>message</code> + * of string type contains an invalid character as a UTF-8 string. It + * corresponds to JavaScript SyntaxError of the specification. + * Otherwise, returns <code>PP_OK</code>, 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 <code>PP_Resource</code> corresponding to a * WebSocket. * @@ -236,8 +245,8 @@ interface PPB_WebSocket_Dev { * @param[in] web_socket A <code>PP_Resource</code> corresponding to a * WebSocket. * - * @return Returns a <code>PP_VARTYPE_STRING</code> var. if called before the - * close reason is set, its data is empty string. Returns a + * @return Returns a <code>PP_VARTYPE_STRING</code> var. If called before the + * close reason is set, it contains an empty string. Returns a * <code>PP_VARTYPE_UNDEFINED</code> if called on an invalid resource. */ PP_Var GetCloseReason([in] PP_Resource web_socket); @@ -252,7 +261,7 @@ interface PPB_WebSocket_Dev { * @return Returns <code>PP_FALSE</code> if called before the connection is * closed, or called on an invalid resource. Otherwise, returns * <code>PP_TRUE</code> if the connection was closed cleanly, or returns - * <code>PP_FALSE</code> if the connection was closed by abnormal reasons. + * <code>PP_FALSE</code> 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 <code>PP_VARTYPE_STRING</code> 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 * <code>PP_VARTYPE_UNDEFINED</code> 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 <code>PP_VARTYPE_STRING</code> 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 * <code>PP_VARTYPE_UNDEFINED</code> 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 <code>PP_VARTYPE_STRING</code> 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 * <code>PP_VARTYPE_UNDEFINED</code> 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 { * <code>protocols</code>. * * @param[in] callback A <code>PP_CompletionCallback</code> 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 <code>PP_ERROR_BADARGUMENT</code> corresponding to JavaScript - * SyntaxError and <code>PP_ERROR_NOACCESS</code> corresponding to JavaScript - * SecurityError. Otherwise, returns <code>PP_OK_COMPLETIONPENDING</code> - * and invokes <code>callback</code> later. + * @return An int32_t containing an error code from <code>pp_errors.h</code>. + * Returns <code>PP_ERROR_BADARGUMENT</code> if specified <code>url</code>, + * or <code>protocols</code> contains invalid string as + * <code>The WebSocket API specification</code> defines. It corresponds to + * SyntaxError of the specification. + * Returns <code>PP_ERROR_NOACCESS</code> if the protocol specified in the + * <code>url</code> is not a secure protocol, but the origin of the caller + * has a secure scheme. Also returns it if the port specified in the + * <code>url</code> 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 <code>PP_ERROR_INPROGRESS</code> 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 { * <code>PP_VARTYPE_STRING</code>. * * @param[in] callback A <code>PP_CompletionCallback</code> 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 <code>PP_ERROR_BADARGUMENT</code> corresponding to JavaScript - * SyntaxError and <code>PP_ERROR_NOACCESS</code> corresponding to JavaScript - * InvalidAccessError. Otherwise, returns - * <code>PP_OK_COMPLETIONPENDING</code> and invokes <code>callback</code> - * later. + * when the connection is closed or an error occurs in closing the + * connection. + * + * @return An int32_t containing an error code from <code>pp_errors.h</code>. + * Returns <code>PP_ERROR_BADARGUMENT</code> if <code>reason</code> contains + * an invalid character as a UTF-8 string, or longer than 123 bytes. It + * corresponds to JavaScript SyntaxError of the specification. + * Returns <code>PP_ERROR_NOACCESS</code> 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 + * <code>PP_ERROR_INPROGRESS</code> 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 <code>PP_Resource</code> corresponding to a * WebSocket. * * @param[out] message The received message is copied to provided - * <code>message</code>. + * <code>message</code>. The <code>message</code> must remain valid until + * the ReceiveMessage operation completes. * * @param[in] callback A <code>PP_CompletionCallback</code> which is called - * when the receiving message is completed. It is ignored when the function - * return <code>PP_OK</code>. - * - * @return In case of immediate failure, returns - * <code>PP_ERROR_FAILED</code>. If a message is currently available, returns - * <code>PP_OK</code>. Otherwise, returns <PP_OK_COMPLETIONPENDING</code> - * and invokes <code>callback</code> later. At that case, if GetReadyState() - * returns <code>PP_WEBSOCKETREADYSTATE_OPEN</code>, the received - * message is also copied to procided <code>message</code>. 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 <code>PP_OK</code>. + * + * @return An int32_t containing an error code from <code>pp_errors.h</code>. + * If an error is detected or connection is closed, returns + * <code>PP_ERROR_FAILED</code> after all buffered messages are received. + * Until buffered message become empty, continues to returns + * <code>PP_OK</code> 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 <code>message</code> safely after returning * from the function. * - * @return In case of immediate failure, returns an error code as follows. - * Returns <code>PP_ERROR_FAILED</code> corresponding to JavaScript - * InvalidStateError and <code>PP_ERROR_BADARGUMENT</code> corresponding to - * JavaScript SyntaxError. Otherwise, return <code>PP_OK</code>. - * <code>PP_OK</code> doesn't necessarily mean that the server received the - * message. + * @return An int32_t containing an error code from <code>pp_errors.h</code>. + * Returns <code>PP_ERROR_FAILED</code> if the ReadyState is + * <code>PP_WEBSOCKETREADYSTATE_CONNECTING_DEV</code>. It corresponds + * JavaScript InvalidStateError of the specification. + * Returns <code>PP_ERROR_BADARGUMENT</code> if provided <code>message</code> + * of string type contains an invalid character as a UTF-8 string. It + * corresponds to JavaScript SyntaxError of the specification. + * Otherwise, returns <code>PP_OK</code>, 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 <code>PP_Resource</code> corresponding to a * WebSocket. * @@ -247,8 +256,8 @@ struct PPB_WebSocket_Dev { * @param[in] web_socket A <code>PP_Resource</code> corresponding to a * WebSocket. * - * @return Returns a <code>PP_VARTYPE_STRING</code> var. if called before the - * close reason is set, its data is empty string. Returns a + * @return Returns a <code>PP_VARTYPE_STRING</code> var. If called before the + * close reason is set, it contains an empty string. Returns a * <code>PP_VARTYPE_UNDEFINED</code> if called on an invalid resource. */ struct PP_Var (*GetCloseReason)(PP_Resource web_socket); @@ -262,7 +271,7 @@ struct PPB_WebSocket_Dev { * @return Returns <code>PP_FALSE</code> if called before the connection is * closed, or called on an invalid resource. Otherwise, returns * <code>PP_TRUE</code> if the connection was closed cleanly, or returns - * <code>PP_FALSE</code> if the connection was closed by abnormal reasons. + * <code>PP_FALSE</code> 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 <code>PP_VARTYPE_STRING</code> 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 * <code>PP_VARTYPE_UNDEFINED</code> 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 <code>PP_VARTYPE_STRING</code> 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 * <code>PP_VARTYPE_UNDEFINED</code> 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 <code>PP_VARTYPE_STRING</code> 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 * <code>PP_VARTYPE_UNDEFINED</code> 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<PPB_WebSocket_Dev>() { + return PPB_WEBSOCKET_DEV_INTERFACE; +} + +} // namespace + +WebSocket_Dev::WebSocket_Dev(Instance* instance) { + if (!has_interface<PPB_WebSocket_Dev>()) + return; + PassRefFromConstructor(get_interface<PPB_WebSocket_Dev>()->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<PPB_WebSocket_Dev>()) + 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<PPB_WebSocket_Dev>()->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<PPB_WebSocket_Dev>()) + return PP_ERROR_BADRESOURCE; + + return get_interface<PPB_WebSocket_Dev>()->Close( + pp_resource(), code, reason.pp_var(), + callback.pp_completion_callback()); +} + +int32_t WebSocket_Dev::ReceiveMessage(Var* message, + const CompletionCallback& callback) { + if (!has_interface<PPB_WebSocket_Dev>()) + return PP_ERROR_BADRESOURCE; + + return get_interface<PPB_WebSocket_Dev>()->ReceiveMessage( + pp_resource(), const_cast<PP_Var*>(&message->pp_var()), + callback.pp_completion_callback()); +} + +int32_t WebSocket_Dev::SendMessage(const Var& message) { + if (!has_interface<PPB_WebSocket_Dev>()) + return PP_ERROR_BADRESOURCE; + + return get_interface<PPB_WebSocket_Dev>()->SendMessage( + pp_resource(), message.pp_var()); +} + +uint64_t WebSocket_Dev::GetBufferedAmount() { + if (!has_interface<PPB_WebSocket_Dev>()) + return 0; + + return get_interface<PPB_WebSocket_Dev>()->GetBufferedAmount(pp_resource()); +} + +uint16_t WebSocket_Dev::GetCloseCode() { + if (!has_interface<PPB_WebSocket_Dev>()) + return 0; + + return get_interface<PPB_WebSocket_Dev>()->GetCloseCode(pp_resource()); +} + +Var WebSocket_Dev::GetCloseReason() { + if (!has_interface<PPB_WebSocket_Dev>()) + return 0; + + return Var(Var::PassRef(), + get_interface<PPB_WebSocket_Dev>()->GetCloseReason(pp_resource())); +} + +bool WebSocket_Dev::GetCloseWasClean() { + if (!has_interface<PPB_WebSocket_Dev>()) + return false; + + PP_Bool result = + get_interface<PPB_WebSocket_Dev>()->GetCloseWasClean(pp_resource()); + return PP_ToBool(result); +} + +Var WebSocket_Dev::GetExtensions() { + if (!has_interface<PPB_WebSocket_Dev>()) + return Var(); + + return Var(Var::PassRef(), + get_interface<PPB_WebSocket_Dev>()->GetExtensions(pp_resource())); +} + +Var WebSocket_Dev::GetProtocol() { + if (!has_interface<PPB_WebSocket_Dev>()) + return Var(); + + return Var(Var::PassRef(), + get_interface<PPB_WebSocket_Dev>()->GetProtocol(pp_resource())); +} + +PP_WebSocketReadyState_Dev WebSocket_Dev::GetReadyState() { + if (!has_interface<PPB_WebSocket_Dev>()) + return PP_WEBSOCKETREADYSTATE_INVALID_DEV; + + return get_interface<PPB_WebSocket_Dev>()->GetReadyState(pp_resource()); +} + +Var WebSocket_Dev::GetURL() { + if (!has_interface<PPB_WebSocket_Dev>()) + return Var(); + + return Var(Var::PassRef(), + get_interface<PPB_WebSocket_Dev>()->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 <code>WebSocket_Dev</code> 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 <code>PP_Var</code> representing a WebSocket server URL. - /// The <code>PP_VarType</code> must be <code>PP_VARTYPE_STRING</code>. - /// @param[in] protocols A pointer to an array of <code>PP_Var</code> - /// specifying sub-protocols. Each <code>PP_Var</code> represents one - /// sub-protocol and its <code>PP_VarType</code> must be - /// <code>PP_VARTYPE_STRING</code>. This argument can be null only if + /// @param[in] url A <code>Var</code> of string type representing a WebSocket + /// server URL. + /// @param[in] protocols A pointer to an array of string type + /// <code>Var</code> specifying sub-protocols. Each <code>Var</code> + /// represents one sub-protocol. This argument can be null only if /// <code>protocol_count</code> is 0. /// @param[in] protocol_count The number of sub-protocols in /// <code>protocols</code>. + /// @param[in] callback A <code>CompletionCallback</code> 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 <code>PP_ERROR_BADARGUMENT</code> corresponding to JavaScript - /// SyntaxError and <code>PP_ERROR_NOACCESS</code> corresponding to - /// JavaScript SecurityError. Otherwise, returns - /// <code>PP_OK_COMPLETIONPENDING</code> and later invokes - /// <code>OnOpen()</code> on success or <code>OnClose()</code> on failure. + /// @return An int32_t containing an error code from + /// <code>pp_errors.h</code>. + /// Returns <code>PP_ERROR_BADARGUMENT</code> if specified <code>url</code>, + /// or <code>protocols</code> contains invalid string as + /// <code>The WebSocket API specification</code> defines. It corresponds to + /// SyntaxError of the specification. + /// Returns <code>PP_ERROR_NOACCESS</code> if the protocol specified in the + /// <code>url</code> is not a secure protocol, but the origin of the caller + /// has a secure scheme. Also returns it if the port specified in the + /// <code>url</code> 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 <code>PP_ERROR_INPROGRESS</code> 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>code</code> and <code>reason</code>. /// /// @param[in] code The WebSocket close code. Ignored if it is 0. - /// @param[in] reason A <code>PP_Var</code> which represents the WebSocket - /// close reason. Ignored if it is <code>PP_VARTYPE_UNDEFINED</code>. - /// Otherwise, its <code>PP_VarType</code> must be - /// <code>PP_VARTYPE_STRING</code>. - /// - /// @return In case of immediate failure, returns an error code as follows. - /// Returns <code>PP_ERROR_BADARGUMENT</code> corresponding to JavaScript - /// SyntaxError and <code>PP_ERROR_NOACCESS</code> corresponding to - /// JavaScript InvalidAccessError. Otherwise, returns - /// <code>PP_OK_COMPLETIONPENDING</code> and invokes <code>OnClose</code>. - int32_t Close(uint16_t code, const Var& reason); + /// @param[in] reason A <code>Var</code> of string type which represents the + /// WebSocket close reason. Ignored if it is undefined type. + /// @param[in] callback A <code>CompletionCallback</code> 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 + /// <code>pp_errors.h</code>. + /// Returns <code>PP_ERROR_BADARGUMENT</code> if <code>reason</code> contains + /// an invalid character as a UTF-8 string, or longer than 123 bytes. It + /// corresponds to JavaScript SyntaxError of the specification. + /// Returns <code>PP_ERROR_NOACCESS</code> 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 + /// <code>PP_ERROR_INPROGRESS</code> 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 + /// <code>message</code>. The <code>message</code> must remain valid until + /// the ReceiveMessage operation completes. + /// @param[in] callback A <code>CompletionCallback</code> which is called + /// when the receiving message is completed. It is ignored if ReceiveMessage + /// completes synchronously and returns <code>PP_OK</code>. + /// + /// @return An int32_t containing an error code from + /// <code>pp_errors.h</code>. + /// If an error is detected or connection is closed, returns + /// <code>PP_ERROR_FAILED</code> after all buffered messages are received. + /// Until buffered message become empty, continues to returns + /// <code>PP_OK</code> 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 <code>data</code> safely after returning /// from the function. /// - /// @return In case of immediate failure, returns an error code as follows. - /// Returns <code>PP_ERROR_FAILED</code> corresponding to JavaScript - /// InvalidStateError and <code>PP_ERROR_BADARGUMENT</code> corresponding to - /// JavaScript SyntaxError. Otherwise, return <code>PP_OK</code>. - /// <code>PP_OK</code> 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 + /// <code>pp_errors.h</code>. + /// Returns <code>PP_ERROR_FAILED</code> if the ReadyState is + /// <code>PP_WEBSOCKETREADYSTATE_CONNECTING_DEV</code>. It corresponds + /// JavaScript InvalidStateError of the specification. + /// Returns <code>PP_ERROR_BADARGUMENT</code> if provided + /// <code>message</code> of string type contains an invalid character as a + /// UTF-8 string. It corresponds to JavaScript SyntaxError of the + /// specification. + /// Otherwise, returns <code>PP_OK</code>, 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 <code>Var</code> 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 <code>false</code> if called before the connection is + /// closed, or called on an invalid resource. Otherwise, returns + /// <code>true</code> if the connection was closed cleanly, or returns + /// <code>false</code> 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 <code>PP_VARTYPE_STRING</code> var. If called before - /// the connection is established, its data is empty string. - /// Currently its data is always empty string. + /// @return Returns a <code>Var</code> 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 <code>PP_VARTYPE_STRING</code> var. If called before - /// the connection is established, its data is empty string. + /// @return Returns a <code>Var</code> 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 <code>PP_VARTYPE_STRING</code> var. If called before - /// the connection is established, its data is empty string. + /// @return Returns a <code>Var</code> 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 <string.h> +#include <vector> #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_; |