| Index: net/websockets/websocket_stream.cc
|
| diff --git a/net/websockets/websocket_stream.cc b/net/websockets/websocket_stream.cc
|
| index 1bd6640ed3fbc79c03ca56275ffc93df8d3e850c..be2bc16f6564a0498e0515588c161eb393a1715b 100644
|
| --- a/net/websockets/websocket_stream.cc
|
| +++ b/net/websockets/websocket_stream.cc
|
| @@ -8,6 +8,8 @@
|
| #include "base/memory/scoped_ptr.h"
|
| #include "base/metrics/histogram.h"
|
| #include "base/metrics/sparse_histogram.h"
|
| +#include "base/time/time.h"
|
| +#include "base/timer/timer.h"
|
| #include "net/base/load_flags.h"
|
| #include "net/http/http_request_headers.h"
|
| #include "net/http/http_response_headers.h"
|
| @@ -27,6 +29,12 @@
|
| namespace net {
|
| namespace {
|
|
|
| +// The timeout duration of WebSocket handshake.
|
| +// It is defined as the same value as the TCP connection timeout value in
|
| +// net/socket/websocket_transport_client_socket_pool.cc to make it hard for
|
| +// JavaScript programs to recognize the timeout cause.
|
| +const int kHandshakeTimeoutIntervalInSeconds = 240;
|
| +
|
| class StreamRequestImpl;
|
|
|
| class Delegate : public URLRequest::Delegate {
|
| @@ -112,22 +120,36 @@ class StreamRequestImpl : public WebSocketStreamRequest {
|
| // and so terminates the handshake if it is incomplete.
|
| virtual ~StreamRequestImpl() {}
|
|
|
| - void Start() {
|
| + void Start(scoped_ptr<base::Timer> timer) {
|
| + DCHECK(timer);
|
| + TimeDelta timeout(TimeDelta::FromSeconds(
|
| + kHandshakeTimeoutIntervalInSeconds));
|
| + timer_ = timer.Pass();
|
| + timer_->Start(FROM_HERE, timeout,
|
| + base::Bind(&StreamRequestImpl::OnTimeout,
|
| + base::Unretained(this)));
|
| url_request_->Start();
|
| }
|
|
|
| void PerformUpgrade() {
|
| + DCHECK(timer_);
|
| + timer_->Stop();
|
| connect_delegate_->OnSuccess(create_helper_->Upgrade());
|
| }
|
|
|
| void ReportFailure() {
|
| + DCHECK(timer_);
|
| + timer_->Stop();
|
| if (failure_message_.empty()) {
|
| switch (url_request_->status().status()) {
|
| case URLRequestStatus::SUCCESS:
|
| case URLRequestStatus::IO_PENDING:
|
| break;
|
| case URLRequestStatus::CANCELED:
|
| - failure_message_ = "WebSocket opening handshake was canceled";
|
| + if (url_request_->status().error() == ERR_TIMED_OUT)
|
| + failure_message_ = "WebSocket opening handshake timed out";
|
| + else
|
| + failure_message_ = "WebSocket opening handshake was canceled";
|
| break;
|
| case URLRequestStatus::FAILED:
|
| failure_message_ =
|
| @@ -154,6 +176,10 @@ class StreamRequestImpl : public WebSocketStreamRequest {
|
| return connect_delegate_.get();
|
| }
|
|
|
| + void OnTimeout() {
|
| + url_request_->CancelWithError(ERR_TIMED_OUT);
|
| + }
|
| +
|
| private:
|
| // |delegate_| needs to be declared before |url_request_| so that it gets
|
| // initialised first.
|
| @@ -170,6 +196,9 @@ class StreamRequestImpl : public WebSocketStreamRequest {
|
|
|
| // The failure message supplied by WebSocketBasicHandshakeStream, if any.
|
| std::string failure_message_;
|
| +
|
| + // A timer for handshake timeout.
|
| + scoped_ptr<base::Timer> timer_;
|
| };
|
|
|
| class SSLErrorCallbacks : public WebSocketEventInterface::SSLErrorCallbacks {
|
| @@ -286,7 +315,7 @@ scoped_ptr<WebSocketStreamRequest> WebSocketStream::CreateAndConnectStream(
|
| origin,
|
| connect_delegate.Pass(),
|
| create_helper.Pass()));
|
| - request->Start();
|
| + request->Start(scoped_ptr<base::Timer>(new base::Timer(false, false)));
|
| return request.PassAs<WebSocketStreamRequest>();
|
| }
|
|
|
| @@ -297,14 +326,15 @@ scoped_ptr<WebSocketStreamRequest> CreateAndConnectStreamForTesting(
|
| const url::Origin& origin,
|
| URLRequestContext* url_request_context,
|
| const BoundNetLog& net_log,
|
| - scoped_ptr<WebSocketStream::ConnectDelegate> connect_delegate) {
|
| + scoped_ptr<WebSocketStream::ConnectDelegate> connect_delegate,
|
| + scoped_ptr<base::Timer> timer) {
|
| scoped_ptr<StreamRequestImpl> request(
|
| new StreamRequestImpl(socket_url,
|
| url_request_context,
|
| origin,
|
| connect_delegate.Pass(),
|
| create_helper.Pass()));
|
| - request->Start();
|
| + request->Start(timer.Pass());
|
| return request.PassAs<WebSocketStreamRequest>();
|
| }
|
|
|
|
|