Adding instrumentation to locate the source of jankiness
[chromium-blink-merge.git] / chrome / browser / net / websocket_browsertest.cc
blob9adf29a963151de06aff23b7236c9febd5067d20
1 // Copyright (c) 2012 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 <string>
7 #include "base/strings/string_util.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "chrome/browser/chrome_notification_types.h"
10 #include "chrome/browser/ui/browser.h"
11 #include "chrome/browser/ui/login/login_prompt.h"
12 #include "chrome/browser/ui/login/login_prompt_test_utils.h"
13 #include "chrome/browser/ui/tabs/tab_strip_model.h"
14 #include "chrome/test/base/in_process_browser_test.h"
15 #include "chrome/test/base/ui_test_utils.h"
16 #include "content/public/browser/navigation_controller.h"
17 #include "content/public/browser/notification_details.h"
18 #include "content/public/browser/notification_registrar.h"
19 #include "content/public/browser/notification_source.h"
20 #include "content/public/browser/web_contents.h"
21 #include "content/public/test/browser_test_utils.h"
22 #include "net/base/test_data_directory.h"
23 #include "net/test/spawned_test_server/spawned_test_server.h"
24 #include "url/gurl.h"
26 namespace {
28 class WebSocketBrowserTest : public InProcessBrowserTest {
29 public:
30 WebSocketBrowserTest()
31 : ws_server_(net::SpawnedTestServer::TYPE_WS,
32 net::SpawnedTestServer::kLocalhost,
33 net::GetWebSocketTestDataDirectory()),
34 wss_server_(net::SpawnedTestServer::TYPE_WSS,
35 SSLOptions(SSLOptions::CERT_OK),
36 net::GetWebSocketTestDataDirectory()) {}
38 protected:
39 void NavigateToHTTP(const std::string& path) {
40 // Visit a HTTP page for testing.
41 std::string scheme("http");
42 GURL::Replacements replacements;
43 replacements.SetSchemeStr(scheme);
44 ui_test_utils::NavigateToURL(
45 browser(), ws_server_.GetURL(path).ReplaceComponents(replacements));
48 void NavigateToHTTPS(const std::string& path) {
49 // Visit a HTTPS page for testing.
50 std::string scheme("https");
51 GURL::Replacements replacements;
52 replacements.SetSchemeStr(scheme);
53 ui_test_utils::NavigateToURL(
54 browser(), wss_server_.GetURL(path).ReplaceComponents(replacements));
57 // Prepare the title watcher.
58 virtual void SetUpOnMainThread() override {
59 watcher_.reset(new content::TitleWatcher(
60 browser()->tab_strip_model()->GetActiveWebContents(),
61 base::ASCIIToUTF16("PASS")));
62 watcher_->AlsoWaitForTitle(base::ASCIIToUTF16("FAIL"));
65 virtual void TearDownOnMainThread() override { watcher_.reset(); }
67 std::string WaitAndGetTitle() {
68 return base::UTF16ToUTF8(watcher_->WaitAndGetTitle());
71 net::SpawnedTestServer ws_server_;
72 net::SpawnedTestServer wss_server_;
74 private:
75 typedef net::SpawnedTestServer::SSLOptions SSLOptions;
76 scoped_ptr<content::TitleWatcher> watcher_;
78 DISALLOW_COPY_AND_ASSIGN(WebSocketBrowserTest);
81 // Framework for tests using the connect_to.html page served by a separate HTTP
82 // server.
83 class WebSocketBrowserConnectToTest : public WebSocketBrowserTest {
84 protected:
85 WebSocketBrowserConnectToTest()
86 : http_server_(net::SpawnedTestServer::TYPE_HTTP,
87 net::SpawnedTestServer::kLocalhost,
88 net::GetWebSocketTestDataDirectory()) {}
90 // The title watcher and HTTP server are set up automatically by the test
91 // framework. Each test case still needs to configure and start the
92 // WebSocket server(s) it needs.
93 virtual void SetUpOnMainThread() override {
94 WebSocketBrowserTest::SetUpOnMainThread();
95 ASSERT_TRUE(http_server_.StartInBackground());
98 // Supply a ws: or wss: URL to connect to.
99 void ConnectTo(GURL url) {
100 ASSERT_TRUE(http_server_.BlockUntilStarted());
101 std::string query("url=" + url.spec());
102 GURL::Replacements replacements;
103 replacements.SetQueryStr(query);
104 ui_test_utils::NavigateToURL(browser(),
105 http_server_.GetURL("files/connect_to.html")
106 .ReplaceComponents(replacements));
109 private:
110 net::SpawnedTestServer http_server_;
113 // Automatically fill in any login prompts that appear with the supplied
114 // credentials.
115 class AutoLogin : public content::NotificationObserver {
116 public:
117 AutoLogin(const std::string& username,
118 const std::string& password,
119 content::NavigationController* navigation_controller)
120 : username_(base::UTF8ToUTF16(username)),
121 password_(base::UTF8ToUTF16(password)),
122 logged_in_(false) {
123 registrar_.Add(
124 this,
125 chrome::NOTIFICATION_AUTH_NEEDED,
126 content::Source<content::NavigationController>(navigation_controller));
129 // NotificationObserver implementation
130 virtual void Observe(int type,
131 const content::NotificationSource& source,
132 const content::NotificationDetails& details) override {
133 DCHECK_EQ(chrome::NOTIFICATION_AUTH_NEEDED, type);
134 scoped_refptr<LoginHandler> login_handler =
135 content::Details<LoginNotificationDetails>(details)->handler();
136 login_handler->SetAuth(username_, password_);
137 logged_in_ = true;
140 bool logged_in() const { return logged_in_; }
142 private:
143 const base::string16 username_;
144 const base::string16 password_;
145 bool logged_in_;
147 content::NotificationRegistrar registrar_;
149 DISALLOW_COPY_AND_ASSIGN(AutoLogin);
152 // Test that the browser can handle a WebSocket frame split into multiple TCP
153 // segments.
154 IN_PROC_BROWSER_TEST_F(WebSocketBrowserTest, WebSocketSplitSegments) {
155 // Launch a WebSocket server.
156 ASSERT_TRUE(ws_server_.Start());
158 NavigateToHTTP("split_packet_check.html");
160 EXPECT_EQ("PASS", WaitAndGetTitle());
163 IN_PROC_BROWSER_TEST_F(WebSocketBrowserTest, SecureWebSocketSplitRecords) {
164 // Launch a secure WebSocket server.
165 ASSERT_TRUE(wss_server_.Start());
167 NavigateToHTTPS("split_packet_check.html");
169 EXPECT_EQ("PASS", WaitAndGetTitle());
172 IN_PROC_BROWSER_TEST_F(WebSocketBrowserTest, SendCloseFrameWhenTabIsClosed) {
173 // Launch a WebSocket server.
174 ASSERT_TRUE(ws_server_.Start());
177 // Create a new tab, establish a WebSocket connection and close the tab.
178 content::WebContents* tab =
179 browser()->tab_strip_model()->GetActiveWebContents();
180 content::WebContents* new_tab = content::WebContents::Create(
181 content::WebContents::CreateParams(tab->GetBrowserContext()));
182 browser()->tab_strip_model()->AppendWebContents(new_tab, true);
183 ASSERT_EQ(new_tab, browser()->tab_strip_model()->GetWebContentsAt(1));
185 content::TitleWatcher connected_title_watcher(
186 new_tab, base::ASCIIToUTF16("CONNECTED"));
187 connected_title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16("CLOSED"));
188 NavigateToHTTP("counted_connection.html");
189 const base::string16 result = connected_title_watcher.WaitAndGetTitle();
190 EXPECT_TRUE(EqualsASCII(result, "CONNECTED"));
192 content::WebContentsDestroyedWatcher destroyed_watcher(new_tab);
193 browser()->tab_strip_model()->CloseWebContentsAt(1, 0);
194 destroyed_watcher.Wait();
197 NavigateToHTTP("count_connection.html");
198 EXPECT_EQ("PASS", WaitAndGetTitle());
201 IN_PROC_BROWSER_TEST_F(WebSocketBrowserTest, WebSocketBasicAuthInHTTPURL) {
202 // Launch a basic-auth-protected WebSocket server.
203 ws_server_.set_websocket_basic_auth(true);
204 ASSERT_TRUE(ws_server_.Start());
206 // Open connect_check.html via HTTP with credentials in the URL.
207 std::string scheme("http");
208 GURL::Replacements replacements;
209 replacements.SetSchemeStr(scheme);
210 ui_test_utils::NavigateToURL(
211 browser(),
212 ws_server_.GetURLWithUserAndPassword("connect_check.html", "test", "test")
213 .ReplaceComponents(replacements));
215 EXPECT_EQ("PASS", WaitAndGetTitle());
218 IN_PROC_BROWSER_TEST_F(WebSocketBrowserTest, WebSocketBasicAuthInHTTPSURL) {
219 // Launch a basic-auth-protected secure WebSocket server.
220 wss_server_.set_websocket_basic_auth(true);
221 ASSERT_TRUE(wss_server_.Start());
223 // Open connect_check.html via HTTPS with credentials in the URL.
224 std::string scheme("https");
225 GURL::Replacements replacements;
226 replacements.SetSchemeStr(scheme);
227 ui_test_utils::NavigateToURL(
228 browser(),
229 wss_server_.GetURLWithUserAndPassword(
230 "connect_check.html", "test", "test")
231 .ReplaceComponents(replacements));
233 EXPECT_EQ("PASS", WaitAndGetTitle());
236 // This test verifies that login details entered by the user into the login
237 // prompt to authenticate the main page are re-used for WebSockets from the same
238 // origin.
239 IN_PROC_BROWSER_TEST_F(WebSocketBrowserTest,
240 ReuseMainPageBasicAuthCredentialsForWebSocket) {
241 // Launch a basic-auth-protected WebSocket server.
242 ws_server_.set_websocket_basic_auth(true);
243 ASSERT_TRUE(ws_server_.Start());
245 content::NavigationController* navigation_controller =
246 &browser()->tab_strip_model()->GetActiveWebContents()->GetController();
247 AutoLogin auto_login("test", "test", navigation_controller);
249 WindowedAuthNeededObserver auth_needed_waiter(navigation_controller);
250 NavigateToHTTP("connect_check.html");
251 auth_needed_waiter.Wait();
253 EXPECT_TRUE(auto_login.logged_in());
254 EXPECT_EQ("PASS", WaitAndGetTitle());
257 IN_PROC_BROWSER_TEST_F(WebSocketBrowserConnectToTest,
258 WebSocketBasicAuthInWSURL) {
259 // Launch a basic-auth-protected WebSocket server.
260 ws_server_.set_websocket_basic_auth(true);
261 ASSERT_TRUE(ws_server_.Start());
263 ConnectTo(ws_server_.GetURLWithUserAndPassword(
264 "echo-with-no-extension", "test", "test"));
266 EXPECT_EQ("PASS", WaitAndGetTitle());
269 IN_PROC_BROWSER_TEST_F(WebSocketBrowserConnectToTest,
270 WebSocketBasicAuthInWSURLBadCreds) {
271 // Launch a basic-auth-protected WebSocket server.
272 ws_server_.set_websocket_basic_auth(true);
273 ASSERT_TRUE(ws_server_.Start());
275 ConnectTo(ws_server_.GetURLWithUserAndPassword(
276 "echo-with-no-extension", "wrong-user", "wrong-password"));
278 EXPECT_EQ("FAIL", WaitAndGetTitle());
281 IN_PROC_BROWSER_TEST_F(WebSocketBrowserConnectToTest,
282 WebSocketBasicAuthNoCreds) {
283 // Launch a basic-auth-protected WebSocket server.
284 ws_server_.set_websocket_basic_auth(true);
285 ASSERT_TRUE(ws_server_.Start());
287 ConnectTo(ws_server_.GetURL("echo-with-no-extension"));
289 EXPECT_EQ("FAIL", WaitAndGetTitle());
292 // HTTPS connection limits should not be applied to wss:. This is only tested
293 // for secure connections here because the unencrypted case is tested in the
294 // Blink layout tests, and browser tests are expensive to run.
295 IN_PROC_BROWSER_TEST_F(WebSocketBrowserTest, SSLConnectionLimit) {
296 ASSERT_TRUE(wss_server_.Start());
298 NavigateToHTTPS("multiple-connections.html");
300 EXPECT_EQ("PASS", WaitAndGetTitle());
303 } // namespace