• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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 <string>
6 #include <vector>
7 
8 #include "base/memory/ref_counted.h"
9 #include "base/string_split.h"
10 #include "base/string_util.h"
11 #include "googleurl/src/gurl.h"
12 #include "net/base/cookie_policy.h"
13 #include "net/base/cookie_store.h"
14 #include "net/base/net_errors.h"
15 #include "net/base/sys_addrinfo.h"
16 #include "net/base/transport_security_state.h"
17 #include "net/socket_stream/socket_stream.h"
18 #include "net/url_request/url_request_context.h"
19 #include "net/websockets/websocket_job.h"
20 #include "net/websockets/websocket_throttle.h"
21 #include "testing/gtest/include/gtest/gtest.h"
22 #include "testing/gmock/include/gmock/gmock.h"
23 #include "testing/platform_test.h"
24 
25 namespace net {
26 
27 class MockSocketStream : public SocketStream {
28  public:
MockSocketStream(const GURL & url,SocketStream::Delegate * delegate)29   MockSocketStream(const GURL& url, SocketStream::Delegate* delegate)
30       : SocketStream(url, delegate) {}
~MockSocketStream()31   virtual ~MockSocketStream() {}
32 
Connect()33   virtual void Connect() {}
SendData(const char * data,int len)34   virtual bool SendData(const char* data, int len) {
35     sent_data_ += std::string(data, len);
36     return true;
37   }
38 
Close()39   virtual void Close() {}
RestartWithAuth(const string16 & username,const string16 & password)40   virtual void RestartWithAuth(
41       const string16& username, const string16& password) {}
DetachDelegate()42   virtual void DetachDelegate() {
43     delegate_ = NULL;
44   }
45 
sent_data() const46   const std::string& sent_data() const {
47     return sent_data_;
48   }
49 
50  private:
51   std::string sent_data_;
52 };
53 
54 class MockSocketStreamDelegate : public SocketStream::Delegate {
55  public:
MockSocketStreamDelegate()56   MockSocketStreamDelegate()
57       : amount_sent_(0) {}
~MockSocketStreamDelegate()58   virtual ~MockSocketStreamDelegate() {}
59 
OnConnected(SocketStream * socket,int max_pending_send_allowed)60   virtual void OnConnected(SocketStream* socket, int max_pending_send_allowed) {
61   }
OnSentData(SocketStream * socket,int amount_sent)62   virtual void OnSentData(SocketStream* socket, int amount_sent) {
63     amount_sent_ += amount_sent;
64   }
OnReceivedData(SocketStream * socket,const char * data,int len)65   virtual void OnReceivedData(SocketStream* socket,
66                               const char* data, int len) {
67     received_data_ += std::string(data, len);
68   }
OnClose(SocketStream * socket)69   virtual void OnClose(SocketStream* socket) {
70   }
71 
amount_sent() const72   size_t amount_sent() const { return amount_sent_; }
received_data() const73   const std::string& received_data() const { return received_data_; }
74 
75  private:
76   int amount_sent_;
77   std::string received_data_;
78 };
79 
80 class MockCookieStore : public CookieStore {
81  public:
82   struct Entry {
83     GURL url;
84     std::string cookie_line;
85     CookieOptions options;
86   };
MockCookieStore()87   MockCookieStore() {}
88 
SetCookieWithOptions(const GURL & url,const std::string & cookie_line,const CookieOptions & options)89   virtual bool SetCookieWithOptions(const GURL& url,
90                                     const std::string& cookie_line,
91                                     const CookieOptions& options) {
92     Entry entry;
93     entry.url = url;
94     entry.cookie_line = cookie_line;
95     entry.options = options;
96     entries_.push_back(entry);
97     return true;
98   }
GetCookiesWithOptions(const GURL & url,const CookieOptions & options)99   virtual std::string GetCookiesWithOptions(const GURL& url,
100                                             const CookieOptions& options) {
101     std::string result;
102     for (size_t i = 0; i < entries_.size(); i++) {
103       Entry &entry = entries_[i];
104       if (url == entry.url) {
105         if (!result.empty()) {
106           result += "; ";
107         }
108         result += entry.cookie_line;
109       }
110     }
111     return result;
112   }
DeleteCookie(const GURL & url,const std::string & cookie_name)113   virtual void DeleteCookie(const GURL& url,
114                             const std::string& cookie_name) {}
GetCookieMonster()115   virtual CookieMonster* GetCookieMonster() { return NULL; }
116 
entries() const117   const std::vector<Entry>& entries() const { return entries_; }
118 
119  private:
120   friend class base::RefCountedThreadSafe<MockCookieStore>;
~MockCookieStore()121   virtual ~MockCookieStore() {}
122 
123   std::vector<Entry> entries_;
124 };
125 
126 class MockCookiePolicy : public CookiePolicy {
127  public:
MockCookiePolicy()128   MockCookiePolicy() : allow_all_cookies_(true) {}
~MockCookiePolicy()129   virtual ~MockCookiePolicy() {}
130 
set_allow_all_cookies(bool allow_all_cookies)131   void set_allow_all_cookies(bool allow_all_cookies) {
132     allow_all_cookies_ = allow_all_cookies;
133   }
134 
CanGetCookies(const GURL & url,const GURL & first_party_for_cookies) const135   virtual int CanGetCookies(const GURL& url,
136                             const GURL& first_party_for_cookies) const {
137     if (allow_all_cookies_)
138       return OK;
139     return ERR_ACCESS_DENIED;
140   }
141 
CanSetCookie(const GURL & url,const GURL & first_party_for_cookies,const std::string & cookie_line) const142   virtual int CanSetCookie(const GURL& url,
143                            const GURL& first_party_for_cookies,
144                            const std::string& cookie_line) const {
145     if (allow_all_cookies_)
146       return OK;
147     return ERR_ACCESS_DENIED;
148   }
149 
150  private:
151   bool allow_all_cookies_;
152 };
153 
154 class MockURLRequestContext : public URLRequestContext {
155  public:
MockURLRequestContext(CookieStore * cookie_store,CookiePolicy * cookie_policy)156   MockURLRequestContext(CookieStore* cookie_store,
157                         CookiePolicy* cookie_policy) {
158     set_cookie_store(cookie_store);
159     set_cookie_policy(cookie_policy);
160     transport_security_state_ = new TransportSecurityState();
161     set_transport_security_state(transport_security_state_.get());
162     TransportSecurityState::DomainState state;
163     state.expiry = base::Time::Now() + base::TimeDelta::FromSeconds(1000);
164     transport_security_state_->EnableHost("upgrademe.com", state);
165   }
166 
167  private:
168   friend class base::RefCountedThreadSafe<MockURLRequestContext>;
~MockURLRequestContext()169   virtual ~MockURLRequestContext() {}
170 
171   scoped_refptr<TransportSecurityState> transport_security_state_;
172 };
173 
174 class WebSocketJobTest : public PlatformTest {
175  public:
SetUp()176   virtual void SetUp() {
177     cookie_store_ = new MockCookieStore;
178     cookie_policy_.reset(new MockCookiePolicy);
179     context_ = new MockURLRequestContext(
180         cookie_store_.get(), cookie_policy_.get());
181   }
TearDown()182   virtual void TearDown() {
183     cookie_store_ = NULL;
184     cookie_policy_.reset();
185     context_ = NULL;
186     websocket_ = NULL;
187     socket_ = NULL;
188   }
189  protected:
InitWebSocketJob(const GURL & url,MockSocketStreamDelegate * delegate)190   void InitWebSocketJob(const GURL& url, MockSocketStreamDelegate* delegate) {
191     websocket_ = new WebSocketJob(delegate);
192     socket_ = new MockSocketStream(url, websocket_.get());
193     websocket_->InitSocketStream(socket_.get());
194     websocket_->set_context(context_.get());
195     websocket_->state_ = WebSocketJob::CONNECTING;
196     struct addrinfo addr;
197     memset(&addr, 0, sizeof(struct addrinfo));
198     addr.ai_family = AF_INET;
199     addr.ai_addrlen = sizeof(struct sockaddr_in);
200     struct sockaddr_in sa_in;
201     memset(&sa_in, 0, sizeof(struct sockaddr_in));
202     memcpy(&sa_in.sin_addr, "\x7f\0\0\1", 4);
203     addr.ai_addr = reinterpret_cast<sockaddr*>(&sa_in);
204     addr.ai_next = NULL;
205     websocket_->addresses_.Copy(&addr, true);
206     WebSocketThrottle::GetInstance()->PutInQueue(websocket_);
207   }
GetWebSocketJobState()208   WebSocketJob::State GetWebSocketJobState() {
209     return websocket_->state_;
210   }
CloseWebSocketJob()211   void CloseWebSocketJob() {
212     if (websocket_->socket_) {
213       websocket_->socket_->DetachDelegate();
214       WebSocketThrottle::GetInstance()->RemoveFromQueue(websocket_);
215     }
216     websocket_->state_ = WebSocketJob::CLOSED;
217     websocket_->delegate_ = NULL;
218     websocket_->socket_ = NULL;
219   }
GetSocket(SocketStreamJob * job)220   SocketStream* GetSocket(SocketStreamJob* job) {
221     return job->socket_.get();
222   }
223 
224   scoped_refptr<MockCookieStore> cookie_store_;
225   scoped_ptr<MockCookiePolicy> cookie_policy_;
226   scoped_refptr<MockURLRequestContext> context_;
227   scoped_refptr<WebSocketJob> websocket_;
228   scoped_refptr<MockSocketStream> socket_;
229 };
230 
TEST_F(WebSocketJobTest,SimpleHandshake)231 TEST_F(WebSocketJobTest, SimpleHandshake) {
232   GURL url("ws://example.com/demo");
233   MockSocketStreamDelegate delegate;
234   InitWebSocketJob(url, &delegate);
235 
236   static const char* kHandshakeRequestMessage =
237       "GET /demo HTTP/1.1\r\n"
238       "Host: example.com\r\n"
239       "Connection: Upgrade\r\n"
240       "Sec-WebSocket-Key2: 12998 5 Y3 1  .P00\r\n"
241       "Sec-WebSocket-Protocol: sample\r\n"
242       "Upgrade: WebSocket\r\n"
243       "Sec-WebSocket-Key1: 4 @1  46546xW%0l 1 5\r\n"
244       "Origin: http://example.com\r\n"
245       "\r\n"
246       "^n:ds[4U";
247 
248   bool sent = websocket_->SendData(kHandshakeRequestMessage,
249                                    strlen(kHandshakeRequestMessage));
250   EXPECT_TRUE(sent);
251   MessageLoop::current()->RunAllPending();
252   EXPECT_EQ(kHandshakeRequestMessage, socket_->sent_data());
253   EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
254   websocket_->OnSentData(socket_.get(), strlen(kHandshakeRequestMessage));
255   EXPECT_EQ(strlen(kHandshakeRequestMessage), delegate.amount_sent());
256 
257   const char kHandshakeResponseMessage[] =
258       "HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
259       "Upgrade: WebSocket\r\n"
260       "Connection: Upgrade\r\n"
261       "Sec-WebSocket-Origin: http://example.com\r\n"
262       "Sec-WebSocket-Location: ws://example.com/demo\r\n"
263       "Sec-WebSocket-Protocol: sample\r\n"
264       "\r\n"
265       "8jKS'y:G*Co,Wxa-";
266 
267   websocket_->OnReceivedData(socket_.get(),
268                              kHandshakeResponseMessage,
269                              strlen(kHandshakeResponseMessage));
270   MessageLoop::current()->RunAllPending();
271   EXPECT_EQ(kHandshakeResponseMessage, delegate.received_data());
272   EXPECT_EQ(WebSocketJob::OPEN, GetWebSocketJobState());
273   CloseWebSocketJob();
274 }
275 
TEST_F(WebSocketJobTest,SlowHandshake)276 TEST_F(WebSocketJobTest, SlowHandshake) {
277   GURL url("ws://example.com/demo");
278   MockSocketStreamDelegate delegate;
279   InitWebSocketJob(url, &delegate);
280 
281   static const char* kHandshakeRequestMessage =
282       "GET /demo HTTP/1.1\r\n"
283       "Host: example.com\r\n"
284       "Connection: Upgrade\r\n"
285       "Sec-WebSocket-Key2: 12998 5 Y3 1  .P00\r\n"
286       "Sec-WebSocket-Protocol: sample\r\n"
287       "Upgrade: WebSocket\r\n"
288       "Sec-WebSocket-Key1: 4 @1  46546xW%0l 1 5\r\n"
289       "Origin: http://example.com\r\n"
290       "\r\n"
291       "^n:ds[4U";
292 
293   bool sent = websocket_->SendData(kHandshakeRequestMessage,
294                                    strlen(kHandshakeRequestMessage));
295   EXPECT_TRUE(sent);
296   // We assume request is sent in one data chunk (from WebKit)
297   // We don't support streaming request.
298   MessageLoop::current()->RunAllPending();
299   EXPECT_EQ(kHandshakeRequestMessage, socket_->sent_data());
300   EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
301   websocket_->OnSentData(socket_.get(), strlen(kHandshakeRequestMessage));
302   EXPECT_EQ(strlen(kHandshakeRequestMessage), delegate.amount_sent());
303 
304   const char kHandshakeResponseMessage[] =
305       "HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
306       "Upgrade: WebSocket\r\n"
307       "Connection: Upgrade\r\n"
308       "Sec-WebSocket-Origin: http://example.com\r\n"
309       "Sec-WebSocket-Location: ws://example.com/demo\r\n"
310       "Sec-WebSocket-Protocol: sample\r\n"
311       "\r\n"
312       "8jKS'y:G*Co,Wxa-";
313 
314   std::vector<std::string> lines;
315   base::SplitString(kHandshakeResponseMessage, '\n', &lines);
316   for (size_t i = 0; i < lines.size() - 2; i++) {
317     std::string line = lines[i] + "\r\n";
318     SCOPED_TRACE("Line: " + line);
319     websocket_->OnReceivedData(socket_,
320                                line.c_str(),
321                                line.size());
322     MessageLoop::current()->RunAllPending();
323     EXPECT_TRUE(delegate.received_data().empty());
324     EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
325   }
326   websocket_->OnReceivedData(socket_.get(), "\r\n", 2);
327   MessageLoop::current()->RunAllPending();
328   EXPECT_TRUE(delegate.received_data().empty());
329   EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
330   websocket_->OnReceivedData(socket_.get(), "8jKS'y:G*Co,Wxa-", 16);
331   EXPECT_EQ(kHandshakeResponseMessage, delegate.received_data());
332   EXPECT_EQ(WebSocketJob::OPEN, GetWebSocketJobState());
333   CloseWebSocketJob();
334 }
335 
TEST_F(WebSocketJobTest,HandshakeWithCookie)336 TEST_F(WebSocketJobTest, HandshakeWithCookie) {
337   GURL url("ws://example.com/demo");
338   GURL cookieUrl("http://example.com/demo");
339   CookieOptions cookie_options;
340   cookie_store_->SetCookieWithOptions(
341       cookieUrl, "CR-test=1", cookie_options);
342   cookie_options.set_include_httponly();
343   cookie_store_->SetCookieWithOptions(
344       cookieUrl, "CR-test-httponly=1", cookie_options);
345 
346   MockSocketStreamDelegate delegate;
347   InitWebSocketJob(url, &delegate);
348 
349   static const char* kHandshakeRequestMessage =
350       "GET /demo HTTP/1.1\r\n"
351       "Host: example.com\r\n"
352       "Connection: Upgrade\r\n"
353       "Sec-WebSocket-Key2: 12998 5 Y3 1  .P00\r\n"
354       "Sec-WebSocket-Protocol: sample\r\n"
355       "Upgrade: WebSocket\r\n"
356       "Sec-WebSocket-Key1: 4 @1  46546xW%0l 1 5\r\n"
357       "Origin: http://example.com\r\n"
358       "Cookie: WK-test=1\r\n"
359       "\r\n"
360       "^n:ds[4U";
361 
362   static const char* kHandshakeRequestExpected =
363       "GET /demo HTTP/1.1\r\n"
364       "Host: example.com\r\n"
365       "Connection: Upgrade\r\n"
366       "Sec-WebSocket-Key2: 12998 5 Y3 1  .P00\r\n"
367       "Sec-WebSocket-Protocol: sample\r\n"
368       "Upgrade: WebSocket\r\n"
369       "Sec-WebSocket-Key1: 4 @1  46546xW%0l 1 5\r\n"
370       "Origin: http://example.com\r\n"
371       "Cookie: CR-test=1; CR-test-httponly=1\r\n"
372       "\r\n"
373       "^n:ds[4U";
374 
375   bool sent = websocket_->SendData(kHandshakeRequestMessage,
376                                    strlen(kHandshakeRequestMessage));
377   EXPECT_TRUE(sent);
378   MessageLoop::current()->RunAllPending();
379   EXPECT_EQ(kHandshakeRequestExpected, socket_->sent_data());
380   EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
381   websocket_->OnSentData(socket_, strlen(kHandshakeRequestExpected));
382   EXPECT_EQ(strlen(kHandshakeRequestMessage), delegate.amount_sent());
383 
384   const char kHandshakeResponseMessage[] =
385       "HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
386       "Upgrade: WebSocket\r\n"
387       "Connection: Upgrade\r\n"
388       "Sec-WebSocket-Origin: http://example.com\r\n"
389       "Sec-WebSocket-Location: ws://example.com/demo\r\n"
390       "Sec-WebSocket-Protocol: sample\r\n"
391       "Set-Cookie: CR-set-test=1\r\n"
392       "\r\n"
393       "8jKS'y:G*Co,Wxa-";
394 
395   static const char* kHandshakeResponseExpected =
396       "HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
397       "Upgrade: WebSocket\r\n"
398       "Connection: Upgrade\r\n"
399       "Sec-WebSocket-Origin: http://example.com\r\n"
400       "Sec-WebSocket-Location: ws://example.com/demo\r\n"
401       "Sec-WebSocket-Protocol: sample\r\n"
402       "\r\n"
403       "8jKS'y:G*Co,Wxa-";
404 
405   websocket_->OnReceivedData(socket_.get(),
406                              kHandshakeResponseMessage,
407                              strlen(kHandshakeResponseMessage));
408   MessageLoop::current()->RunAllPending();
409   EXPECT_EQ(kHandshakeResponseExpected, delegate.received_data());
410   EXPECT_EQ(WebSocketJob::OPEN, GetWebSocketJobState());
411 
412   EXPECT_EQ(3U, cookie_store_->entries().size());
413   EXPECT_EQ(cookieUrl, cookie_store_->entries()[0].url);
414   EXPECT_EQ("CR-test=1", cookie_store_->entries()[0].cookie_line);
415   EXPECT_EQ(cookieUrl, cookie_store_->entries()[1].url);
416   EXPECT_EQ("CR-test-httponly=1", cookie_store_->entries()[1].cookie_line);
417   EXPECT_EQ(cookieUrl, cookie_store_->entries()[2].url);
418   EXPECT_EQ("CR-set-test=1", cookie_store_->entries()[2].cookie_line);
419 
420   CloseWebSocketJob();
421 }
422 
TEST_F(WebSocketJobTest,HandshakeWithCookieButNotAllowed)423 TEST_F(WebSocketJobTest, HandshakeWithCookieButNotAllowed) {
424   GURL url("ws://example.com/demo");
425   GURL cookieUrl("http://example.com/demo");
426   CookieOptions cookie_options;
427   cookie_store_->SetCookieWithOptions(
428       cookieUrl, "CR-test=1", cookie_options);
429   cookie_options.set_include_httponly();
430   cookie_store_->SetCookieWithOptions(
431       cookieUrl, "CR-test-httponly=1", cookie_options);
432   cookie_policy_->set_allow_all_cookies(false);
433 
434   MockSocketStreamDelegate delegate;
435   InitWebSocketJob(url, &delegate);
436 
437   static const char* kHandshakeRequestMessage =
438       "GET /demo HTTP/1.1\r\n"
439       "Host: example.com\r\n"
440       "Connection: Upgrade\r\n"
441       "Sec-WebSocket-Key2: 12998 5 Y3 1  .P00\r\n"
442       "Sec-WebSocket-Protocol: sample\r\n"
443       "Upgrade: WebSocket\r\n"
444       "Sec-WebSocket-Key1: 4 @1  46546xW%0l 1 5\r\n"
445       "Origin: http://example.com\r\n"
446       "Cookie: WK-test=1\r\n"
447       "\r\n"
448       "^n:ds[4U";
449 
450   static const char* kHandshakeRequestExpected =
451       "GET /demo HTTP/1.1\r\n"
452       "Host: example.com\r\n"
453       "Connection: Upgrade\r\n"
454       "Sec-WebSocket-Key2: 12998 5 Y3 1  .P00\r\n"
455       "Sec-WebSocket-Protocol: sample\r\n"
456       "Upgrade: WebSocket\r\n"
457       "Sec-WebSocket-Key1: 4 @1  46546xW%0l 1 5\r\n"
458       "Origin: http://example.com\r\n"
459       "\r\n"
460       "^n:ds[4U";
461 
462   bool sent = websocket_->SendData(kHandshakeRequestMessage,
463                                    strlen(kHandshakeRequestMessage));
464   EXPECT_TRUE(sent);
465   MessageLoop::current()->RunAllPending();
466   EXPECT_EQ(kHandshakeRequestExpected, socket_->sent_data());
467   EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
468   websocket_->OnSentData(socket_, strlen(kHandshakeRequestExpected));
469   EXPECT_EQ(strlen(kHandshakeRequestMessage), delegate.amount_sent());
470 
471   const char kHandshakeResponseMessage[] =
472       "HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
473       "Upgrade: WebSocket\r\n"
474       "Connection: Upgrade\r\n"
475       "Sec-WebSocket-Origin: http://example.com\r\n"
476       "Sec-WebSocket-Location: ws://example.com/demo\r\n"
477       "Sec-WebSocket-Protocol: sample\r\n"
478       "Set-Cookie: CR-set-test=1\r\n"
479       "\r\n"
480       "8jKS'y:G*Co,Wxa-";
481 
482   static const char* kHandshakeResponseExpected =
483       "HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
484       "Upgrade: WebSocket\r\n"
485       "Connection: Upgrade\r\n"
486       "Sec-WebSocket-Origin: http://example.com\r\n"
487       "Sec-WebSocket-Location: ws://example.com/demo\r\n"
488       "Sec-WebSocket-Protocol: sample\r\n"
489       "\r\n"
490       "8jKS'y:G*Co,Wxa-";
491 
492   websocket_->OnReceivedData(socket_.get(),
493                              kHandshakeResponseMessage,
494                              strlen(kHandshakeResponseMessage));
495   MessageLoop::current()->RunAllPending();
496   EXPECT_EQ(kHandshakeResponseExpected, delegate.received_data());
497   EXPECT_EQ(WebSocketJob::OPEN, GetWebSocketJobState());
498 
499   EXPECT_EQ(2U, cookie_store_->entries().size());
500   EXPECT_EQ(cookieUrl, cookie_store_->entries()[0].url);
501   EXPECT_EQ("CR-test=1", cookie_store_->entries()[0].cookie_line);
502   EXPECT_EQ(cookieUrl, cookie_store_->entries()[1].url);
503   EXPECT_EQ("CR-test-httponly=1", cookie_store_->entries()[1].cookie_line);
504 
505   CloseWebSocketJob();
506 }
507 
TEST_F(WebSocketJobTest,HSTSUpgrade)508 TEST_F(WebSocketJobTest, HSTSUpgrade) {
509   GURL url("ws://upgrademe.com/");
510   MockSocketStreamDelegate delegate;
511   scoped_refptr<SocketStreamJob> job = SocketStreamJob::CreateSocketStreamJob(
512       url, &delegate, *context_.get());
513   EXPECT_TRUE(GetSocket(job.get())->is_secure());
514   job->DetachDelegate();
515 
516   url = GURL("ws://donotupgrademe.com/");
517   job = SocketStreamJob::CreateSocketStreamJob(
518       url, &delegate, *context_.get());
519   EXPECT_FALSE(GetSocket(job.get())->is_secure());
520   job->DetachDelegate();
521 }
522 
523 }  // namespace net
524