Single-purpose extensions policy FAQ
[chromium-blink-merge.git] / net / websockets / websocket_stream.cc
blob399b8f0b0911e23c1c1a2acbfa8a5ac90cf22349
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.
5 #include "net/websockets/websocket_stream.h"
7 #include "base/logging.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/metrics/histogram.h"
10 #include "net/http/http_request_headers.h"
11 #include "net/http/http_status_code.h"
12 #include "net/url_request/url_request.h"
13 #include "net/url_request/url_request_context.h"
14 #include "net/websockets/websocket_errors.h"
15 #include "net/websockets/websocket_handshake_constants.h"
16 #include "net/websockets/websocket_handshake_stream_base.h"
17 #include "net/websockets/websocket_handshake_stream_create_helper.h"
18 #include "net/websockets/websocket_test_util.h"
19 #include "url/gurl.h"
20 #include "url/origin.h"
22 namespace net {
23 namespace {
25 class StreamRequestImpl;
27 class Delegate : public URLRequest::Delegate {
28 public:
29 enum HandshakeResult {
30 INCOMPLETE,
31 CONNECTED,
32 FAILED,
33 NUM_HANDSHAKE_RESULT_TYPES,
36 explicit Delegate(StreamRequestImpl* owner)
37 : owner_(owner), result_(INCOMPLETE) {}
38 virtual ~Delegate() {
39 UMA_HISTOGRAM_ENUMERATION(
40 "Net.WebSocket.HandshakeResult", result_, NUM_HANDSHAKE_RESULT_TYPES);
43 // Implementation of URLRequest::Delegate methods.
44 virtual void OnResponseStarted(URLRequest* request) OVERRIDE;
46 virtual void OnAuthRequired(URLRequest* request,
47 AuthChallengeInfo* auth_info) OVERRIDE;
49 virtual void OnCertificateRequested(URLRequest* request,
50 SSLCertRequestInfo* cert_request_info)
51 OVERRIDE;
53 virtual void OnSSLCertificateError(URLRequest* request,
54 const SSLInfo& ssl_info,
55 bool fatal) OVERRIDE;
57 virtual void OnReadCompleted(URLRequest* request, int bytes_read) OVERRIDE;
59 private:
60 StreamRequestImpl* owner_;
61 HandshakeResult result_;
64 class StreamRequestImpl : public WebSocketStreamRequest {
65 public:
66 StreamRequestImpl(
67 const GURL& url,
68 const URLRequestContext* context,
69 scoped_ptr<WebSocketStream::ConnectDelegate> connect_delegate,
70 WebSocketHandshakeStreamCreateHelper* create_helper)
71 : delegate_(new Delegate(this)),
72 url_request_(url, DEFAULT_PRIORITY, delegate_.get(), context),
73 connect_delegate_(connect_delegate.Pass()),
74 create_helper_(create_helper) {}
76 // Destroying this object destroys the URLRequest, which cancels the request
77 // and so terminates the handshake if it is incomplete.
78 virtual ~StreamRequestImpl() {}
80 URLRequest* url_request() { return &url_request_; }
82 void PerformUpgrade() {
83 connect_delegate_->OnSuccess(create_helper_->stream()->Upgrade());
86 void ReportFailure() {
87 std::string failure_message;
88 if (create_helper_->stream()) {
89 failure_message = create_helper_->stream()->GetFailureMessage();
90 } else {
91 switch (url_request_.status().status()) {
92 case URLRequestStatus::SUCCESS:
93 case URLRequestStatus::IO_PENDING:
94 break;
95 case URLRequestStatus::CANCELED:
96 failure_message = "WebSocket opening handshake was canceled";
97 break;
98 case URLRequestStatus::FAILED:
99 failure_message =
100 std::string("Error in connection establishment: ") +
101 ErrorToString(url_request_.status().error());
102 break;
105 connect_delegate_->OnFailure(failure_message);
108 private:
109 // |delegate_| needs to be declared before |url_request_| so that it gets
110 // initialised first.
111 scoped_ptr<Delegate> delegate_;
113 // Deleting the StreamRequestImpl object deletes this URLRequest object,
114 // cancelling the whole connection.
115 URLRequest url_request_;
117 scoped_ptr<WebSocketStream::ConnectDelegate> connect_delegate_;
119 // Owned by the URLRequest.
120 WebSocketHandshakeStreamCreateHelper* create_helper_;
123 void Delegate::OnResponseStarted(URLRequest* request) {
124 switch (request->GetResponseCode()) {
125 case HTTP_SWITCHING_PROTOCOLS:
126 result_ = CONNECTED;
127 owner_->PerformUpgrade();
128 return;
130 case HTTP_UNAUTHORIZED:
131 case HTTP_PROXY_AUTHENTICATION_REQUIRED:
132 return;
134 default:
135 result_ = FAILED;
136 owner_->ReportFailure();
140 void Delegate::OnAuthRequired(URLRequest* request,
141 AuthChallengeInfo* auth_info) {
142 request->CancelAuth();
145 void Delegate::OnCertificateRequested(URLRequest* request,
146 SSLCertRequestInfo* cert_request_info) {
147 request->ContinueWithCertificate(NULL);
150 void Delegate::OnSSLCertificateError(URLRequest* request,
151 const SSLInfo& ssl_info,
152 bool fatal) {
153 request->Cancel();
156 void Delegate::OnReadCompleted(URLRequest* request, int bytes_read) {
157 NOTREACHED();
160 // Internal implementation of CreateAndConnectStream and
161 // CreateAndConnectStreamForTesting.
162 scoped_ptr<WebSocketStreamRequest> CreateAndConnectStreamWithCreateHelper(
163 const GURL& socket_url,
164 scoped_ptr<WebSocketHandshakeStreamCreateHelper> create_helper,
165 const url::Origin& origin,
166 URLRequestContext* url_request_context,
167 const BoundNetLog& net_log,
168 scoped_ptr<WebSocketStream::ConnectDelegate> connect_delegate) {
169 scoped_ptr<StreamRequestImpl> request(
170 new StreamRequestImpl(socket_url,
171 url_request_context,
172 connect_delegate.Pass(),
173 create_helper.get()));
174 HttpRequestHeaders headers;
175 headers.SetHeader(websockets::kUpgrade, websockets::kWebSocketLowercase);
176 headers.SetHeader(HttpRequestHeaders::kConnection, websockets::kUpgrade);
177 headers.SetHeader(HttpRequestHeaders::kOrigin, origin.string());
178 headers.SetHeader(websockets::kSecWebSocketVersion,
179 websockets::kSupportedVersion);
180 request->url_request()->SetExtraRequestHeaders(headers);
181 request->url_request()->SetUserData(
182 WebSocketHandshakeStreamBase::CreateHelper::DataKey(),
183 create_helper.release());
184 request->url_request()->SetLoadFlags(LOAD_DISABLE_CACHE |
185 LOAD_BYPASS_CACHE |
186 LOAD_DO_NOT_PROMPT_FOR_LOGIN);
187 request->url_request()->Start();
188 return request.PassAs<WebSocketStreamRequest>();
191 } // namespace
193 WebSocketStreamRequest::~WebSocketStreamRequest() {}
195 WebSocketStream::WebSocketStream() {}
196 WebSocketStream::~WebSocketStream() {}
198 WebSocketStream::ConnectDelegate::~ConnectDelegate() {}
200 scoped_ptr<WebSocketStreamRequest> WebSocketStream::CreateAndConnectStream(
201 const GURL& socket_url,
202 const std::vector<std::string>& requested_subprotocols,
203 const url::Origin& origin,
204 URLRequestContext* url_request_context,
205 const BoundNetLog& net_log,
206 scoped_ptr<ConnectDelegate> connect_delegate) {
207 scoped_ptr<WebSocketHandshakeStreamCreateHelper> create_helper(
208 new WebSocketHandshakeStreamCreateHelper(connect_delegate.get(),
209 requested_subprotocols));
210 return CreateAndConnectStreamWithCreateHelper(socket_url,
211 create_helper.Pass(),
212 origin,
213 url_request_context,
214 net_log,
215 connect_delegate.Pass());
218 // This is declared in websocket_test_util.h.
219 scoped_ptr<WebSocketStreamRequest> CreateAndConnectStreamForTesting(
220 const GURL& socket_url,
221 scoped_ptr<WebSocketHandshakeStreamCreateHelper> create_helper,
222 const url::Origin& origin,
223 URLRequestContext* url_request_context,
224 const BoundNetLog& net_log,
225 scoped_ptr<WebSocketStream::ConnectDelegate> connect_delegate) {
226 return CreateAndConnectStreamWithCreateHelper(socket_url,
227 create_helper.Pass(),
228 origin,
229 url_request_context,
230 net_log,
231 connect_delegate.Pass());
234 } // namespace net