Skip to content

Commit

Permalink
Websocket should fire 'error' event if no server available
Browse files Browse the repository at this point in the history
Implement OnError virtual function, when network is down, OnError can be invoked.
Send error code to render process from browser process through IPC.

This patch depends on Blink side patch which can be found from https://codereview.chromium.org/14071008/ 


BUG=128057
TEST=

Review URL: https://chromiumcodereview.appspot.com/10668018

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@196728 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
li.yin@intel.com committed Apr 26, 2013
1 parent 92e9182 commit 35a16a2
Show file tree
Hide file tree
Showing 13 changed files with 97 additions and 11 deletions.
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -245,3 +245,4 @@ Sathish Kuppuswamy <sathish.kuppuswamy@intel.com>
Joone Hur <joone.hur@intel.com>
Sudarsana Babu Nagineni <sudarsana.nagineni@intel.com>
Jared Shumway <jaredshumway94@gmail.com>
Li Yin <li.yin@intel.com>
17 changes: 17 additions & 0 deletions content/browser/renderer_host/socket_stream_dispatcher_host.cc
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,23 @@ void SocketStreamDispatcherHost::OnClose(net::SocketStream* socket) {
DeleteSocketStreamHost(socket_id);
}

void SocketStreamDispatcherHost::OnError(const net::SocketStream* socket,
int error) {
int socket_id = SocketStreamHost::SocketIdFromSocketStream(socket);
DVLOG(1) << "SocketStreamDispatcherHost::OnError socket_id=" << socket_id;
if (socket_id == content::kNoSocketId) {
LOG(ERROR) << "NoSocketId in OnError";
return;
}
// SocketStream::Delegate::OnError() events are handled as WebSocket error
// event when user agent was required to fail WebSocket connection or the
// WebSocket connection is closed with prejudice.
if (!Send(new SocketStreamMsg_Failed(socket_id, error))) {
LOG(ERROR) << "SocketStreamMsg_Failed failed.";
DeleteSocketStreamHost(socket_id);
}
}

void SocketStreamDispatcherHost::OnSSLCertificateError(
net::SocketStream* socket, const net::SSLInfo& ssl_info, bool fatal) {
int socket_id = SocketStreamHost::SocketIdFromSocketStream(socket);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ class SocketStreamDispatcherHost
virtual void OnReceivedData(net::SocketStream* socket,
const char* data, int len) OVERRIDE;
virtual void OnClose(net::SocketStream* socket) OVERRIDE;
virtual void OnError(const net::SocketStream* socket, int error) OVERRIDE;
virtual void OnSSLCertificateError(net::SocketStream* socket,
const net::SSLInfo& ssl_info,
bool fatal) OVERRIDE;
Expand Down
3 changes: 2 additions & 1 deletion content/browser/renderer_host/socket_stream_host.cc
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ SocketStreamHost::SocketStreamHost(
}

/* static */
int SocketStreamHost::SocketIdFromSocketStream(net::SocketStream* socket) {
int SocketStreamHost::SocketIdFromSocketStream(
const net::SocketStream* socket) {
net::SocketStream::UserData* d = socket->GetUserData(kSocketIdKey);
if (d) {
SocketStreamId* socket_stream_id = static_cast<SocketStreamId*>(d);
Expand Down
2 changes: 1 addition & 1 deletion content/browser/renderer_host/socket_stream_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class SocketStreamHost {
~SocketStreamHost();

// Gets socket_id associated with |socket|.
static int SocketIdFromSocketStream(net::SocketStream* socket);
static int SocketIdFromSocketStream(const net::SocketStream* socket);

int render_view_id() const { return render_view_id_; }
int socket_id() const { return socket_id_; }
Expand Down
22 changes: 22 additions & 0 deletions content/common/socket_stream_dispatcher.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,14 @@
#include "base/lazy_instance.h"
#include "base/memory/ref_counted.h"
#include "base/message_loop.h"
#include "base/string16.h"
#include "base/utf_string_conversions.h"
#include "content/common/child_thread.h"
#include "content/common/socket_stream.h"
#include "content/common/socket_stream_handle_data.h"
#include "content/common/socket_stream_messages.h"
#include "googleurl/src/gurl.h"
#include "net/base/net_errors.h"
#include "webkit/glue/websocketstreamhandle_bridge.h"
#include "webkit/glue/websocketstreamhandle_delegate.h"

Expand Down Expand Up @@ -48,6 +51,7 @@ class IPCWebSocketStreamHandleBridge
void OnSentData(int amount_sent);
void OnReceivedData(const std::vector<char>& data);
void OnClosed();
void OnFailed(int error_code, const char* error_msg);

private:
virtual ~IPCWebSocketStreamHandleBridge();
Expand Down Expand Up @@ -159,6 +163,14 @@ void IPCWebSocketStreamHandleBridge::OnClosed() {
Release();
}

void IPCWebSocketStreamHandleBridge::OnFailed(int error_code,
const char* error_msg) {
DVLOG(1) << "Bridge #" << socket_id_ << " OnFailed (error_code=" << error_code
<< ")";
if (delegate_)
delegate_->DidFail(handle_, error_code, ASCIIToUTF16(error_msg));
}

void IPCWebSocketStreamHandleBridge::DoConnect(const GURL& url) {
DCHECK(child_thread_);
DCHECK_EQ(socket_id_, kNoSocketId);
Expand Down Expand Up @@ -207,6 +219,7 @@ bool SocketStreamDispatcher::OnMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_HANDLER(SocketStreamMsg_SentData, OnSentData)
IPC_MESSAGE_HANDLER(SocketStreamMsg_ReceivedData, OnReceivedData)
IPC_MESSAGE_HANDLER(SocketStreamMsg_Closed, OnClosed)
IPC_MESSAGE_HANDLER(SocketStreamMsg_Failed, OnFailed)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
Expand Down Expand Up @@ -261,4 +274,13 @@ void SocketStreamDispatcher::OnClosed(int socket_id) {
DLOG(ERROR) << "No bridge for socket_id=" << socket_id;
}

void SocketStreamDispatcher::OnFailed(int socket_id, int error_code) {
IPCWebSocketStreamHandleBridge* bridge =
IPCWebSocketStreamHandleBridge::FromSocketId(socket_id);
if (bridge)
bridge->OnFailed(error_code, net::ErrorToString(error_code));
else
DLOG(ERROR) << "No bridge for socket_id=" << socket_id;
}

} // namespace content
1 change: 1 addition & 0 deletions content/common/socket_stream_dispatcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class SocketStreamDispatcher : public IPC::Listener {
void OnSentData(int socket_id, int amount_sent);
void OnReceivedData(int socket_id, const std::vector<char>& data);
void OnClosed(int socket_id);
void OnFailed(int socket_id, int error_code);

DISALLOW_COPY_AND_ASSIGN(SocketStreamDispatcher);
};
Expand Down
5 changes: 5 additions & 0 deletions content/common/socket_stream_messages.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,8 @@ IPC_MESSAGE_CONTROL2(SocketStreamMsg_SentData,
// The Socket Stream is closed.
IPC_MESSAGE_CONTROL1(SocketStreamMsg_Closed,
int /* socket_id */)

// The Socket Stream is failed.
IPC_MESSAGE_CONTROL2(SocketStreamMsg_Failed,
int /* socket_id */,
int /* error_code */)
3 changes: 2 additions & 1 deletion net/socket_stream/socket_stream.cc
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,8 @@ void SocketStream::Finish(int result) {
Delegate* delegate = delegate_;
delegate_ = NULL;
if (delegate) {
delegate->OnError(this, result);
if (result != ERR_CONNECTION_CLOSED)
delegate->OnError(this, result);
if (result != ERR_PROTOCOL_SWITCHED)
delegate->OnClose(this);
}
Expand Down
12 changes: 4 additions & 8 deletions net/socket_stream/socket_stream_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ TEST_F(SocketStreamTest, CloseFlushPendingWrite) {
test_callback.WaitForResult();

const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents();
ASSERT_EQ(8U, events.size());
ASSERT_EQ(7U, events.size());

EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION,
events[0].event_type);
Expand All @@ -365,9 +365,7 @@ TEST_F(SocketStreamTest, CloseFlushPendingWrite) {
EXPECT_EQ(SocketStreamEvent::EVENT_RECEIVED_DATA, events[3].event_type);
EXPECT_EQ(SocketStreamEvent::EVENT_SENT_DATA, events[4].event_type);
EXPECT_EQ(SocketStreamEvent::EVENT_SENT_DATA, events[5].event_type);
EXPECT_EQ(SocketStreamEvent::EVENT_ERROR, events[6].event_type);
EXPECT_EQ(ERR_CONNECTION_CLOSED, events[6].error_code);
EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[7].event_type);
EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[6].event_type);
}

TEST_F(SocketStreamTest, ExceedMaxPendingSendAllowed) {
Expand Down Expand Up @@ -645,7 +643,7 @@ TEST_F(SocketStreamTest, IOPending) {
EXPECT_EQ(OK, test_callback.WaitForResult());

const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents();
ASSERT_EQ(8U, events.size());
ASSERT_EQ(7U, events.size());

EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION,
events[0].event_type);
Expand All @@ -654,9 +652,7 @@ TEST_F(SocketStreamTest, IOPending) {
EXPECT_EQ(SocketStreamEvent::EVENT_RECEIVED_DATA, events[3].event_type);
EXPECT_EQ(SocketStreamEvent::EVENT_SENT_DATA, events[4].event_type);
EXPECT_EQ(SocketStreamEvent::EVENT_SENT_DATA, events[5].event_type);
EXPECT_EQ(SocketStreamEvent::EVENT_ERROR, events[6].event_type);
EXPECT_EQ(ERR_CONNECTION_CLOSED, events[6].error_code);
EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[7].event_type);
EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[6].event_type);
}

TEST_F(SocketStreamTest, SwitchToSpdy) {
Expand Down
5 changes: 5 additions & 0 deletions webkit/glue/websocketstreamhandle_delegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#ifndef WEBKIT_GLUE_WEBSOCKETSTREAMHANDLE_DELEGATE_H_
#define WEBKIT_GLUE_WEBSOCKETSTREAMHANDLE_DELEGATE_H_

#include "base/string16.h"

class GURL;

namespace WebKit {
Expand All @@ -29,6 +31,9 @@ class WebSocketStreamHandleDelegate {
virtual void DidReceiveData(WebKit::WebSocketStreamHandle* handle,
const char* data, int len) {}
virtual void DidClose(WebKit::WebSocketStreamHandle*) {}
virtual void DidFail(WebKit::WebSocketStreamHandle* handle,
int error_code,
const string16& error_msg) {}

protected:
virtual ~WebSocketStreamHandleDelegate() {}
Expand Down
16 changes: 16 additions & 0 deletions webkit/glue/websocketstreamhandle_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,17 @@
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/string16.h"
#include "third_party/WebKit/Source/Platform/chromium/public/WebData.h"
#include "third_party/WebKit/Source/Platform/chromium/public/WebSocketStreamError.h"
#include "third_party/WebKit/Source/Platform/chromium/public/WebSocketStreamHandleClient.h"
#include "third_party/WebKit/Source/Platform/chromium/public/WebURL.h"
#include "webkit/glue/webkitplatformsupport_impl.h"
#include "webkit/glue/websocketstreamhandle_bridge.h"
#include "webkit/glue/websocketstreamhandle_delegate.h"

using WebKit::WebData;
using WebKit::WebSocketStreamError;
using WebKit::WebSocketStreamHandle;
using WebKit::WebSocketStreamHandleClient;
using WebKit::WebURL;
Expand Down Expand Up @@ -54,6 +57,7 @@ class WebSocketStreamHandleImpl::Context
const char*,
int) OVERRIDE;
virtual void DidClose(WebSocketStreamHandle*) OVERRIDE;
virtual void DidFail(WebSocketStreamHandle*, int, const string16&);

private:
friend class base::RefCounted<Context>;
Expand Down Expand Up @@ -145,6 +149,18 @@ void WebSocketStreamHandleImpl::Context::DidClose(
Release();
}

void WebSocketStreamHandleImpl::Context::DidFail(
WebSocketStreamHandle* web_handle,
int error_code,
const string16& error_msg) {
VLOG(1) << "DidFail";
if (client_) {
client_->didFail(
handle_,
WebSocketStreamError(error_code, error_msg));
}
}

// WebSocketStreamHandleImpl ------------------------------------------------

WebSocketStreamHandleImpl::WebSocketStreamHandleImpl(
Expand Down
20 changes: 20 additions & 0 deletions webkit/tools/test_shell/simple_socket_stream_bridge.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "base/bind.h"
#include "base/memory/ref_counted.h"
#include "base/message_loop.h"
#include "base/utf_string_conversions.h"
#include "googleurl/src/gurl.h"
#include "net/socket_stream/socket_stream_job.h"
#include "net/websockets/websocket_job.h"
Expand Down Expand Up @@ -48,6 +49,7 @@ class WebSocketStreamHandleBridgeImpl
virtual void OnReceivedData(net::SocketStream* req,
const char* data, int len) OVERRIDE;
virtual void OnClose(net::SocketStream* req) OVERRIDE;
virtual void OnError(const net::SocketStream* req, int error_code) OVERRIDE;

private:
virtual ~WebSocketStreamHandleBridgeImpl();
Expand All @@ -62,6 +64,7 @@ class WebSocketStreamHandleBridgeImpl
void DoOnSentData(int amount_sent);
void DoOnReceivedData(std::vector<char>* data);
void DoOnClose();
void DoOnError(int error_code, const char* error_msg);

int socket_id_;
MessageLoop* message_loop_;
Expand Down Expand Up @@ -154,6 +157,15 @@ void WebSocketStreamHandleBridgeImpl::OnClose(net::SocketStream* socket) {
base::Bind(&WebSocketStreamHandleBridgeImpl::DoOnClose, this));
}

void WebSocketStreamHandleBridgeImpl::OnError(
const net::SocketStream* socket, int error_code) {
base::subtle::NoBarrier_AtomicIncrement(&num_pending_tasks_, 1);
message_loop_->PostTask(
FROM_HERE,
base::Bind(&WebSocketStreamHandleBridgeImpl::DoOnError, this,
error_code, net::ErrorToString(error_code)));
}

void WebSocketStreamHandleBridgeImpl::DoConnect(const GURL& url) {
DCHECK(MessageLoop::current() == g_io_thread);
socket_ = net::SocketStreamJob::CreateSocketStreamJob(
Expand Down Expand Up @@ -217,6 +229,14 @@ void WebSocketStreamHandleBridgeImpl::DoOnClose() {
Release();
}

void WebSocketStreamHandleBridgeImpl::DoOnError(
int error_code, const char* error_msg) {
DCHECK(MessageLoop::current() == message_loop_);
base::subtle::NoBarrier_AtomicIncrement(&num_pending_tasks_, -1);
if (delegate_)
delegate_->DidFail(handle_, error_code, ASCIIToUTF16(error_msg));
}

} // namespace

/* static */
Expand Down

0 comments on commit 35a16a2

Please sign in to comment.