Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / net / websockets / websocket_stream.cc
1 // Copyright 2013 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 "net/websockets/websocket_stream.h"
6
7 #include "base/logging.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "net/http/http_request_headers.h"
10 #include "net/http/http_status_code.h"
11 #include "net/url_request/url_request.h"
12 #include "net/url_request/url_request_context.h"
13 #include "net/websockets/websocket_errors.h"
14 #include "net/websockets/websocket_handshake_constants.h"
15 #include "net/websockets/websocket_handshake_stream_base.h"
16 #include "net/websockets/websocket_handshake_stream_create_helper.h"
17 #include "net/websockets/websocket_test_util.h"
18 #include "url/gurl.h"
19
20 namespace net {
21 namespace {
22
23 class StreamRequestImpl;
24
25 class Delegate : public URLRequest::Delegate {
26  public:
27   explicit Delegate(StreamRequestImpl* owner) : owner_(owner) {}
28   virtual ~Delegate() {}
29
30   // Implementation of URLRequest::Delegate methods.
31   virtual void OnResponseStarted(URLRequest* request) OVERRIDE;
32
33   virtual void OnAuthRequired(URLRequest* request,
34                               AuthChallengeInfo* auth_info) OVERRIDE;
35
36   virtual void OnCertificateRequested(URLRequest* request,
37                                       SSLCertRequestInfo* cert_request_info)
38       OVERRIDE;
39
40   virtual void OnSSLCertificateError(URLRequest* request,
41                                      const SSLInfo& ssl_info,
42                                      bool fatal) OVERRIDE;
43
44   virtual void OnReadCompleted(URLRequest* request, int bytes_read) OVERRIDE;
45
46  private:
47   StreamRequestImpl* owner_;
48 };
49
50 class StreamRequestImpl : public WebSocketStreamRequest {
51  public:
52   StreamRequestImpl(
53       const GURL& url,
54       const URLRequestContext* context,
55       scoped_ptr<WebSocketStream::ConnectDelegate> connect_delegate,
56       WebSocketHandshakeStreamCreateHelper* create_helper)
57       : delegate_(new Delegate(this)),
58         url_request_(url, DEFAULT_PRIORITY, delegate_.get(), context),
59         connect_delegate_(connect_delegate.Pass()),
60         create_helper_(create_helper) {}
61
62   // Destroying this object destroys the URLRequest, which cancels the request
63   // and so terminates the handshake if it is incomplete.
64   virtual ~StreamRequestImpl() {}
65
66   URLRequest* url_request() { return &url_request_; }
67
68   void PerformUpgrade() {
69     connect_delegate_->OnSuccess(create_helper_->stream()->Upgrade());
70   }
71
72   void ReportFailure() {
73     std::string failure_message;
74     if (create_helper_->stream()) {
75       failure_message = create_helper_->stream()->GetFailureMessage();
76     } else {
77       switch (url_request_.status().status()) {
78         case URLRequestStatus::SUCCESS:
79         case URLRequestStatus::IO_PENDING:
80           break;
81         case URLRequestStatus::CANCELED:
82           failure_message = "WebSocket opening handshake was canceled";
83           break;
84         case URLRequestStatus::FAILED:
85           failure_message =
86               std::string("Error in connection establishment: ") +
87               ErrorToString(url_request_.status().error());
88           break;
89       }
90     }
91     connect_delegate_->OnFailure(failure_message);
92   }
93
94  private:
95   // |delegate_| needs to be declared before |url_request_| so that it gets
96   // initialised first.
97   scoped_ptr<Delegate> delegate_;
98
99   // Deleting the StreamRequestImpl object deletes this URLRequest object,
100   // cancelling the whole connection.
101   URLRequest url_request_;
102
103   scoped_ptr<WebSocketStream::ConnectDelegate> connect_delegate_;
104
105   // Owned by the URLRequest.
106   WebSocketHandshakeStreamCreateHelper* create_helper_;
107 };
108
109 void Delegate::OnResponseStarted(URLRequest* request) {
110   switch (request->GetResponseCode()) {
111     case HTTP_SWITCHING_PROTOCOLS:
112       owner_->PerformUpgrade();
113       return;
114
115     case HTTP_UNAUTHORIZED:
116     case HTTP_PROXY_AUTHENTICATION_REQUIRED:
117       return;
118
119     default:
120       owner_->ReportFailure();
121   }
122 }
123
124 void Delegate::OnAuthRequired(URLRequest* request,
125                               AuthChallengeInfo* auth_info) {
126   request->CancelAuth();
127 }
128
129 void Delegate::OnCertificateRequested(URLRequest* request,
130                                       SSLCertRequestInfo* cert_request_info) {
131   request->ContinueWithCertificate(NULL);
132 }
133
134 void Delegate::OnSSLCertificateError(URLRequest* request,
135                                      const SSLInfo& ssl_info,
136                                      bool fatal) {
137   request->Cancel();
138 }
139
140 void Delegate::OnReadCompleted(URLRequest* request, int bytes_read) {
141   NOTREACHED();
142 }
143
144 // Internal implementation of CreateAndConnectStream and
145 // CreateAndConnectStreamForTesting.
146 scoped_ptr<WebSocketStreamRequest> CreateAndConnectStreamWithCreateHelper(
147     const GURL& socket_url,
148     scoped_ptr<WebSocketHandshakeStreamCreateHelper> create_helper,
149     const GURL& origin,
150     URLRequestContext* url_request_context,
151     const BoundNetLog& net_log,
152     scoped_ptr<WebSocketStream::ConnectDelegate> connect_delegate) {
153   scoped_ptr<StreamRequestImpl> request(
154       new StreamRequestImpl(socket_url,
155                             url_request_context,
156                             connect_delegate.Pass(),
157                             create_helper.get()));
158   HttpRequestHeaders headers;
159   headers.SetHeader(websockets::kUpgrade, websockets::kWebSocketLowercase);
160   headers.SetHeader(HttpRequestHeaders::kConnection, websockets::kUpgrade);
161   headers.SetHeader(HttpRequestHeaders::kOrigin, origin.spec());
162   // TODO(ricea): Move the version number to websocket_handshake_constants.h
163   headers.SetHeader(websockets::kSecWebSocketVersion,
164                     websockets::kSupportedVersion);
165   request->url_request()->SetExtraRequestHeaders(headers);
166   request->url_request()->SetUserData(
167       WebSocketHandshakeStreamBase::CreateHelper::DataKey(),
168       create_helper.release());
169   request->url_request()->SetLoadFlags(LOAD_DISABLE_CACHE |
170                                        LOAD_BYPASS_CACHE |
171                                        LOAD_DO_NOT_PROMPT_FOR_LOGIN);
172   request->url_request()->Start();
173   return request.PassAs<WebSocketStreamRequest>();
174 }
175
176 }  // namespace
177
178 WebSocketStreamRequest::~WebSocketStreamRequest() {}
179
180 WebSocketStream::WebSocketStream() {}
181 WebSocketStream::~WebSocketStream() {}
182
183 WebSocketStream::ConnectDelegate::~ConnectDelegate() {}
184
185 scoped_ptr<WebSocketStreamRequest> WebSocketStream::CreateAndConnectStream(
186     const GURL& socket_url,
187     const std::vector<std::string>& requested_subprotocols,
188     const GURL& origin,
189     URLRequestContext* url_request_context,
190     const BoundNetLog& net_log,
191     scoped_ptr<ConnectDelegate> connect_delegate) {
192   scoped_ptr<WebSocketHandshakeStreamCreateHelper> create_helper(
193       new WebSocketHandshakeStreamCreateHelper(connect_delegate.get(),
194                                                requested_subprotocols));
195   return CreateAndConnectStreamWithCreateHelper(socket_url,
196                                                 create_helper.Pass(),
197                                                 origin,
198                                                 url_request_context,
199                                                 net_log,
200                                                 connect_delegate.Pass());
201 }
202
203 // This is declared in websocket_test_util.h.
204 scoped_ptr<WebSocketStreamRequest> CreateAndConnectStreamForTesting(
205       const GURL& socket_url,
206       scoped_ptr<WebSocketHandshakeStreamCreateHelper> create_helper,
207       const GURL& origin,
208       URLRequestContext* url_request_context,
209       const BoundNetLog& net_log,
210       scoped_ptr<WebSocketStream::ConnectDelegate> connect_delegate) {
211   return CreateAndConnectStreamWithCreateHelper(socket_url,
212                                                 create_helper.Pass(),
213                                                 origin,
214                                                 url_request_context,
215                                                 net_log,
216                                                 connect_delegate.Pass());
217 }
218
219 }  // namespace net