1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
|
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ppapi/utility/websocket/websocket_api.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/pp_macros.h"
#include "ppapi/cpp/instance.h"
#include "ppapi/cpp/module.h"
#include "ppapi/cpp/module_impl.h"
#include "ppapi/cpp/var.h"
#include "ppapi/cpp/websocket.h"
#include "ppapi/utility/completion_callback_factory.h"
#ifdef SendMessage
#undef SendMessage
#endif
namespace pp {
class WebSocketAPI::Implement : public WebSocket {
public:
Implement(Instance* instance, WebSocketAPI* api)
: WebSocket(instance),
api_(api),
callback_factory_(this) {
}
virtual ~Implement() {}
int32_t Connect(const Var& url, const Var protocols[],
uint32_t protocol_count) {
CompletionCallback callback =
callback_factory_.NewOptionalCallback(&Implement::DidConnect);
int32_t result =
WebSocket::Connect(url, protocols, protocol_count, callback);
if (result != PP_OK_COMPLETIONPENDING) {
// In synchronous cases, consumes callback here and invokes callback
// with PP_ERROR_ABORTED instead of result in order to avoid side effects
// in DidConnect. DidConnect ignores this invocation and doesn't call
// any delegate virtual method.
callback.Run(PP_ERROR_ABORTED);
}
return result;
}
int32_t Close(uint16_t code, const Var& reason) {
CompletionCallback callback =
callback_factory_.NewOptionalCallback(&Implement::DidClose);
int32_t result = WebSocket::Close(code, reason, callback);
if (result != PP_OK_COMPLETIONPENDING) {
// In synchronous cases, consumes callback here and invokes callback
// with PP_ERROR_ABORTED instead of result in order to avoid side effects
// in DidConnect. DidConnect ignores this invocation and doesn't call
// any delegate virtual method.
callback.Run(PP_ERROR_ABORTED);
}
return result;
}
void Receive() {
int32_t result;
do {
CompletionCallback callback =
callback_factory_.NewOptionalCallback(&Implement::DidReceive);
result = WebSocket::ReceiveMessage(&receive_message_var_, callback);
if (result != PP_OK_COMPLETIONPENDING)
callback.Run(result);
} while (result == PP_OK);
}
void DidConnect(int32_t result) {
if (result == PP_OK) {
api_->WebSocketDidOpen();
Receive();
} else if (result != PP_ERROR_ABORTED) {
DidClose(result);
}
}
void DidReceive(int32_t result) {
if (result == PP_OK) {
api_->HandleWebSocketMessage(receive_message_var_);
Receive();
} else if (result != PP_ERROR_ABORTED) {
DidClose(result);
}
}
void DidClose(int32_t result) {
if (result == PP_ERROR_ABORTED)
return;
bool was_clean = GetCloseWasClean();
if (!was_clean)
api_->HandleWebSocketError();
api_->WebSocketDidClose(was_clean, GetCloseCode(), GetCloseReason());
}
private:
WebSocketAPI* api_;
CompletionCallbackFactory<Implement> callback_factory_;
Var receive_message_var_;
};
WebSocketAPI::WebSocketAPI(Instance* instance)
: impl_(new Implement(instance, this)) {
}
WebSocketAPI::~WebSocketAPI() {
delete impl_;
}
int32_t WebSocketAPI::Connect(const Var& url, const Var protocols[],
uint32_t protocol_count) {
return impl_->Connect(url, protocols, protocol_count);
}
int32_t WebSocketAPI::Close(uint16_t code, const Var& reason) {
return impl_->Close(code, reason);
}
int32_t WebSocketAPI::Send(const Var& data) {
return impl_->SendMessage(data);
}
uint64_t WebSocketAPI::GetBufferedAmount() {
return impl_->GetBufferedAmount();
}
Var WebSocketAPI::GetExtensions() {
return impl_->GetExtensions();
}
Var WebSocketAPI::GetProtocol() {
return impl_->GetProtocol();
}
PP_WebSocketReadyState WebSocketAPI::GetReadyState() {
return impl_->GetReadyState();
}
Var WebSocketAPI::GetURL() {
return impl_->GetURL();
}
} // namespace pp
|