OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "ppapi/cpp/dev/websocket_dev.h" | |
6 | |
7 #include <set> | |
8 | |
9 #include "ppapi/c/pp_errors.h" | |
10 #include "ppapi/cpp/completion_callback.h" | |
11 #include "ppapi/cpp/instance.h" | |
12 #include "ppapi/cpp/module.h" | |
13 #include "ppapi/cpp/module_impl.h" | |
14 #include "ppapi/cpp/var.h" | |
15 | |
16 namespace pp { | |
17 | |
18 namespace { | |
19 | |
20 template <> const char* interface_name<PPB_WebSocket_Dev>() { | |
21 return PPB_WEBSOCKET_DEV_INTERFACE; | |
22 } | |
23 | |
24 } // namespace | |
25 | |
26 class WebSocket_Dev::WebSocketPrivate { | |
27 public: | |
28 WebSocketPrivate(WebSocket_Dev* ws) | |
29 : connect_callback_(new CompletionCallback(DidConnectCallback, this, | |
dmichael (off chromium)
2011/12/07 23:31:28
You'll probably need PP_ALLOW_THIS_IN_INITIALIZER_
Takashi Toyoshima
2011/12/08 14:40:10
Done.
| |
30 PP_COMPLETIONCALLBACK_FLAG_OPTIONAL)), | |
31 close_callback_(new CompletionCallback(DidCloseCallback, this)), | |
32 receive_callback_(new CompletionCallback(DidReceiveCallback, this)), | |
33 ws_(ws) {} | |
34 ~WebSocketPrivate() { | |
35 delete connect_callback_; | |
36 delete close_callback_; | |
37 delete receive_callback_; | |
38 } | |
39 void Receive() { | |
40 int32_t result; | |
41 do { | |
42 result = get_interface<PPB_WebSocket_Dev>()->ReceiveMessage( | |
43 ws_->pp_resource(), | |
44 &receive_message_var_, | |
45 receive_callback_->pp_completion_callback()); | |
46 if (result == PP_OK) | |
47 ws_->OnMessage(Var(Var::PassRef(), receive_message_var_)); | |
48 } while (result == PP_OK); | |
49 if (result == PP_OK_COMPLETIONPENDING) | |
50 return; | |
51 if (result == PP_ERROR_BADARGUMENT) | |
52 return; | |
53 DidClose(result); | |
54 } | |
55 void DidConnect(int32_t result) { | |
56 if (result == PP_OK) { | |
57 ws_->OnOpen(); | |
58 Receive(); | |
59 } else { | |
60 DidClose(result); | |
61 } | |
62 } | |
63 void DidReceive(int32_t result) { | |
64 if (result == PP_OK) { | |
65 ws_->OnMessage(Var(Var::PassRef(), receive_message_var_)); | |
66 Receive(); | |
67 } else { | |
68 DidClose(result); | |
69 } | |
70 } | |
71 void DidClose(int32_t result) { | |
72 PP_Resource resource = ws_->pp_resource(); | |
73 PP_Bool was_clean = | |
74 get_interface<PPB_WebSocket_Dev>()->GetCloseWasClean(resource); | |
75 uint16_t code = | |
76 get_interface<PPB_WebSocket_Dev>()->GetCloseCode(resource); | |
77 Var reason = Var(Var::PassRef(), | |
78 get_interface<PPB_WebSocket_Dev>()->GetCloseReason(resource)); | |
79 bool was_fully_clean = was_clean == PP_TRUE && result == PP_OK; | |
80 ws_->OnClose(was_fully_clean, code, reason); | |
81 } | |
82 static void DidConnectCallback(void* user_data, int32_t result) { | |
83 WebSocketPrivate* instance = FindLiveInstance(user_data); | |
84 if (instance) | |
85 instance->DidConnect(result); | |
86 } | |
87 static void DidCloseCallback(void* user_data, int32_t result) { | |
88 WebSocketPrivate* instance = FindLiveInstance(user_data); | |
89 if (instance) | |
90 instance->DidClose(result); | |
91 } | |
92 static void DidReceiveCallback(void* user_data, int32_t result) { | |
93 WebSocketPrivate* instance = FindLiveInstance(user_data); | |
94 if (instance) | |
95 instance->DidReceive(result); | |
96 } | |
97 static void AddLiveInstance(WebSocketPrivate* instance) { | |
98 instance_set_.insert(instance); | |
99 } | |
100 static void RemoveLiveInstance(WebSocketPrivate* instance) { | |
101 instance_set_.erase(instance); | |
102 } | |
103 static WebSocketPrivate* FindLiveInstance(void* user_data) { | |
104 WebSocketPrivate* instance = static_cast<WebSocketPrivate*>(user_data); | |
105 if (!instance || instance_set_.find(instance) == instance_set_.end()) | |
106 return NULL; | |
107 return instance; | |
108 } | |
109 | |
110 CompletionCallback* connect_callback_; | |
111 CompletionCallback* close_callback_; | |
112 CompletionCallback* receive_callback_; | |
113 | |
114 private: | |
115 WebSocket_Dev* ws_; | |
116 PP_Var receive_message_var_; | |
117 | |
118 static std::set<WebSocketPrivate*> instance_set_; | |
119 }; | |
120 | |
121 std::set<WebSocket_Dev::WebSocketPrivate*> | |
122 WebSocket_Dev::WebSocketPrivate::instance_set_; | |
123 | |
124 WebSocket_Dev::WebSocket_Dev(Instance* instance) | |
125 : impl(new WebSocketPrivate(this)) { | |
126 WebSocketPrivate::AddLiveInstance(impl); | |
127 if (!has_interface<PPB_WebSocket_Dev>()) | |
128 return; | |
129 PassRefFromConstructor(get_interface<PPB_WebSocket_Dev>()->Create( | |
130 instance->pp_instance())); | |
131 } | |
132 | |
133 WebSocket_Dev::~WebSocket_Dev() { | |
134 WebSocketPrivate::RemoveLiveInstance(impl); | |
135 delete impl; | |
136 } | |
137 | |
138 int32_t WebSocket_Dev::Connect(const Var& url, const Var protocols[], | |
139 uint32_t protocol_count) { | |
140 if (!has_interface<PPB_WebSocket_Dev>()) | |
141 return PP_ERROR_BADRESOURCE; | |
142 | |
143 // Convert protocols to C interface. | |
144 uint32_t allocation_protocol_count = protocol_count ? protocol_count : 1; | |
145 PP_Var *c_protocols = new PP_Var[allocation_protocol_count]; | |
146 if (!c_protocols) | |
147 return PP_ERROR_NOMEMORY; | |
148 for (uint32_t i = 0; i < protocol_count; ++i) | |
149 c_protocols[i] = protocols[i].pp_var(); | |
150 | |
151 int32_t result = get_interface<PPB_WebSocket_Dev>()->Connect( | |
152 pp_resource(), url.pp_var(), c_protocols, protocol_count, | |
153 impl->connect_callback_->pp_completion_callback()); | |
154 delete[] c_protocols; | |
155 return result; | |
156 } | |
157 | |
158 int32_t WebSocket_Dev::Close(uint16_t code, const Var& reason) { | |
159 if (!has_interface<PPB_WebSocket_Dev>()) | |
160 return PP_ERROR_BADRESOURCE; | |
161 | |
162 return get_interface<PPB_WebSocket_Dev>()->Close( | |
163 pp_resource(), code, reason.pp_var(), | |
164 impl->close_callback_->pp_completion_callback()); | |
165 } | |
166 | |
167 int32_t WebSocket_Dev::Send(const Var& data) { | |
168 if (!has_interface<PPB_WebSocket_Dev>()) | |
169 return PP_ERROR_BADRESOURCE; | |
170 | |
171 return get_interface<PPB_WebSocket_Dev>()->SendMessage( | |
172 pp_resource(), data.pp_var()); | |
173 } | |
174 | |
175 uint64_t WebSocket_Dev::GetBufferedAmount() { | |
176 if (!has_interface<PPB_WebSocket_Dev>()) | |
177 return PP_ERROR_BADRESOURCE; | |
178 | |
179 return get_interface<PPB_WebSocket_Dev>()->GetBufferedAmount(pp_resource()); | |
180 } | |
181 | |
182 Var WebSocket_Dev::GetExtensions() { | |
183 if (!has_interface<PPB_WebSocket_Dev>()) | |
184 return Var(); | |
185 | |
186 return Var(Var::PassRef(), | |
187 get_interface<PPB_WebSocket_Dev>()->GetExtensions(pp_resource())); | |
188 } | |
189 | |
190 Var WebSocket_Dev::GetProtocol() { | |
191 if (!has_interface<PPB_WebSocket_Dev>()) | |
192 return Var(); | |
193 | |
194 return Var(Var::PassRef(), | |
195 get_interface<PPB_WebSocket_Dev>()->GetProtocol(pp_resource())); | |
196 } | |
197 | |
198 PP_WebSocketReadyState_Dev WebSocket_Dev::GetReadyState() { | |
199 if (!has_interface<PPB_WebSocket_Dev>()) | |
200 return PP_WEBSOCKETREADYSTATE_INVALID_DEV; | |
201 | |
202 return get_interface<PPB_WebSocket_Dev>()->GetReadyState(pp_resource()); | |
203 } | |
204 | |
205 Var WebSocket_Dev::GetURL() { | |
206 if (!has_interface<PPB_WebSocket_Dev>()) | |
207 return Var(); | |
208 | |
209 return Var(Var::PassRef(), | |
210 get_interface<PPB_WebSocket_Dev>()->GetURL(pp_resource())); | |
211 } | |
212 | |
213 } // namespace pp | |
OLD | NEW |