• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 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 // An implementation of WebSocketStreamHandle.
6 
7 #include "webkit/child/websocketstreamhandle_impl.h"
8 
9 #include <vector>
10 
11 #include "base/compiler_specific.h"
12 #include "base/logging.h"
13 #include "base/memory/ref_counted.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/strings/string16.h"
16 #include "third_party/WebKit/public/platform/WebData.h"
17 #include "third_party/WebKit/public/platform/WebSocketStreamError.h"
18 #include "third_party/WebKit/public/platform/WebSocketStreamHandleClient.h"
19 #include "third_party/WebKit/public/platform/WebURL.h"
20 #include "webkit/child/webkitplatformsupport_impl.h"
21 #include "webkit/child/websocketstreamhandle_bridge.h"
22 #include "webkit/child/websocketstreamhandle_delegate.h"
23 
24 using blink::WebData;
25 using blink::WebSocketStreamError;
26 using blink::WebSocketStreamHandle;
27 using blink::WebSocketStreamHandleClient;
28 using blink::WebURL;
29 
30 namespace webkit_glue {
31 
32 // WebSocketStreamHandleImpl::Context -----------------------------------------
33 
34 class WebSocketStreamHandleImpl::Context
35     : public base::RefCounted<Context>,
36       public WebSocketStreamHandleDelegate {
37  public:
38   explicit Context(WebSocketStreamHandleImpl* handle);
39 
client() const40   WebSocketStreamHandleClient* client() const { return client_; }
set_client(WebSocketStreamHandleClient * client)41   void set_client(WebSocketStreamHandleClient* client) {
42     client_ = client;
43   }
44 
45   void Connect(const WebURL& url, WebKitPlatformSupportImpl* platform);
46   bool Send(const WebData& data);
47   void Close();
48 
49   // Must be called before |handle_| or |client_| is deleted.
50   // Once detached, it never calls |client_| back.
51   void Detach();
52 
53   // WebSocketStreamHandleDelegate methods:
54   virtual void DidOpenStream(WebSocketStreamHandle*, int) OVERRIDE;
55   virtual void DidSendData(WebSocketStreamHandle*, int) OVERRIDE;
56   virtual void DidReceiveData(WebSocketStreamHandle*,
57                               const char*,
58                               int) OVERRIDE;
59   virtual void DidClose(WebSocketStreamHandle*) OVERRIDE;
60   virtual void DidFail(WebSocketStreamHandle*, int, const string16&) OVERRIDE;
61 
62  private:
63   friend class base::RefCounted<Context>;
~Context()64   virtual ~Context() {
65     DCHECK(!handle_);
66     DCHECK(!client_);
67     DCHECK(!bridge_.get());
68   }
69 
70   WebSocketStreamHandleImpl* handle_;
71   WebSocketStreamHandleClient* client_;
72   // |bridge_| is alive from Connect to DidClose, so Context must be alive
73   // in the time period.
74   scoped_refptr<WebSocketStreamHandleBridge> bridge_;
75 
76   DISALLOW_COPY_AND_ASSIGN(Context);
77 };
78 
Context(WebSocketStreamHandleImpl * handle)79 WebSocketStreamHandleImpl::Context::Context(WebSocketStreamHandleImpl* handle)
80     : handle_(handle),
81       client_(NULL) {
82 }
83 
Connect(const WebURL & url,WebKitPlatformSupportImpl * platform)84 void WebSocketStreamHandleImpl::Context::Connect(
85     const WebURL& url,
86     WebKitPlatformSupportImpl* platform) {
87   VLOG(1) << "Connect url=" << url;
88   DCHECK(!bridge_.get());
89   bridge_ = platform->CreateWebSocketStreamBridge(handle_, this);
90   AddRef();  // Will be released by DidClose().
91   bridge_->Connect(url);
92 }
93 
Send(const WebData & data)94 bool WebSocketStreamHandleImpl::Context::Send(const WebData& data) {
95   VLOG(1) << "Send data.size=" << data.size();
96   DCHECK(bridge_.get());
97   return bridge_->Send(
98       std::vector<char>(data.data(), data.data() + data.size()));
99 }
100 
Close()101 void WebSocketStreamHandleImpl::Context::Close() {
102   VLOG(1) << "Close";
103   if (bridge_.get())
104     bridge_->Close();
105 }
106 
Detach()107 void WebSocketStreamHandleImpl::Context::Detach() {
108   handle_ = NULL;
109   client_ = NULL;
110   // If Connect was called, |bridge_| is not NULL, so that this Context closes
111   // the |bridge_| here.  Then |bridge_| will call back DidClose, and will
112   // be released by itself.
113   // Otherwise, |bridge_| is NULL.
114   if (bridge_.get())
115     bridge_->Close();
116 }
117 
DidOpenStream(WebSocketStreamHandle * web_handle,int max_amount_send_allowed)118 void WebSocketStreamHandleImpl::Context::DidOpenStream(
119     WebSocketStreamHandle* web_handle, int max_amount_send_allowed) {
120   VLOG(1) << "DidOpen";
121   if (client_)
122     client_->didOpenStream(handle_, max_amount_send_allowed);
123 }
124 
DidSendData(WebSocketStreamHandle * web_handle,int amount_sent)125 void WebSocketStreamHandleImpl::Context::DidSendData(
126     WebSocketStreamHandle* web_handle, int amount_sent) {
127   if (client_)
128     client_->didSendData(handle_, amount_sent);
129 }
130 
DidReceiveData(WebSocketStreamHandle * web_handle,const char * data,int size)131 void WebSocketStreamHandleImpl::Context::DidReceiveData(
132     WebSocketStreamHandle* web_handle, const char* data, int size) {
133   if (client_)
134     client_->didReceiveData(handle_, WebData(data, size));
135 }
136 
DidClose(WebSocketStreamHandle * web_handle)137 void WebSocketStreamHandleImpl::Context::DidClose(
138     WebSocketStreamHandle* web_handle) {
139   VLOG(1) << "DidClose";
140   bridge_ = NULL;
141   WebSocketStreamHandleImpl* handle = handle_;
142   handle_ = NULL;
143   if (client_) {
144     WebSocketStreamHandleClient* client = client_;
145     client_ = NULL;
146     client->didClose(handle);
147   }
148   Release();
149 }
150 
DidFail(WebSocketStreamHandle * web_handle,int error_code,const string16 & error_msg)151 void WebSocketStreamHandleImpl::Context::DidFail(
152     WebSocketStreamHandle* web_handle,
153     int error_code,
154     const string16& error_msg) {
155   VLOG(1) << "DidFail";
156   if (client_) {
157     client_->didFail(
158         handle_,
159         WebSocketStreamError(error_code, error_msg));
160   }
161 }
162 
163 // WebSocketStreamHandleImpl ------------------------------------------------
164 
WebSocketStreamHandleImpl(WebKitPlatformSupportImpl * platform)165 WebSocketStreamHandleImpl::WebSocketStreamHandleImpl(
166     WebKitPlatformSupportImpl* platform)
167     : context_(new Context(this)),
168       platform_(platform) {
169 }
170 
~WebSocketStreamHandleImpl()171 WebSocketStreamHandleImpl::~WebSocketStreamHandleImpl() {
172   // We won't receive any events from |context_|.
173   // |context_| is ref counted, and will be released when it received
174   // DidClose.
175   context_->Detach();
176 }
177 
connect(const WebURL & url,WebSocketStreamHandleClient * client)178 void WebSocketStreamHandleImpl::connect(
179     const WebURL& url, WebSocketStreamHandleClient* client) {
180   VLOG(1) << "connect url=" << url;
181   DCHECK(!context_->client());
182   context_->set_client(client);
183 
184   context_->Connect(url, platform_);
185 }
186 
send(const WebData & data)187 bool WebSocketStreamHandleImpl::send(const WebData& data) {
188   return context_->Send(data);
189 }
190 
close()191 void WebSocketStreamHandleImpl::close() {
192   context_->Close();
193 }
194 
195 }  // namespace webkit_glue
196