Home | History | Annotate | Download | only in child
      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 WebKit::WebData;
     25 using WebKit::WebSocketStreamError;
     26 using WebKit::WebSocketStreamHandle;
     27 using WebKit::WebSocketStreamHandleClient;
     28 using WebKit::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 
     40   WebSocketStreamHandleClient* client() const { return 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>;
     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 
     79 WebSocketStreamHandleImpl::Context::Context(WebSocketStreamHandleImpl* handle)
     80     : handle_(handle),
     81       client_(NULL) {
     82 }
     83 
     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->CreateWebSocketBridge(handle_, this);
     90   AddRef();  // Will be released by DidClose().
     91   bridge_->Connect(url);
     92 }
     93 
     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 
    101 void WebSocketStreamHandleImpl::Context::Close() {
    102   VLOG(1) << "Close";
    103   if (bridge_.get())
    104     bridge_->Close();
    105 }
    106 
    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 
    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 
    125 void WebSocketStreamHandleImpl::Context::DidSendData(
    126     WebSocketStreamHandle* web_handle, int amount_sent) {
    127   if (client_)
    128     client_->didSendData(handle_, amount_sent);
    129 }
    130 
    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 
    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 
    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 
    165 WebSocketStreamHandleImpl::WebSocketStreamHandleImpl(
    166     WebKitPlatformSupportImpl* platform)
    167     : context_(new Context(this)),
    168       platform_(platform) {
    169 }
    170 
    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 
    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 
    187 bool WebSocketStreamHandleImpl::send(const WebData& data) {
    188   return context_->Send(data);
    189 }
    190 
    191 void WebSocketStreamHandleImpl::close() {
    192   context_->Close();
    193 }
    194 
    195 }  // namespace webkit_glue
    196