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. 4 5#include "base/command_line.h" 6#include "base/path_service.h" 7#include "base/strings/string_util.h" 8#include "base/strings/stringprintf.h" 9#include "base/strings/utf_string_conversions.h" 10#include "chrome/browser/chrome_notification_types.h" 11#include "chrome/browser/ui/browser.h" 12#include "chrome/browser/ui/login/login_prompt.h" 13#include "chrome/browser/ui/tabs/tab_strip_model.h" 14#include "chrome/common/chrome_paths.h" 15#include "chrome/common/chrome_switches.h" 16#include "chrome/common/pref_names.h" 17#include "chrome/test/base/in_process_browser_test.h" 18#include "chrome/test/base/ui_test_utils.h" 19#include "content/public/browser/notification_details.h" 20#include "content/public/browser/notification_source.h" 21#include "content/public/browser/web_contents.h" 22#include "content/public/browser/web_contents_observer.h" 23#include "content/public/test/browser_test_utils.h" 24#include "net/base/test_data_directory.h" 25#include "net/test/spawned_test_server/spawned_test_server.h" 26 27namespace { 28 29// PAC script that sends all requests to an invalid proxy server. 30const base::FilePath::CharType kPACScript[] = FILE_PATH_LITERAL( 31 "bad_server.pac"); 32 33// Verify kPACScript is installed as the PAC script. 34void VerifyProxyScript(Browser* browser) { 35 ui_test_utils::NavigateToURL(browser, GURL("http://google.com")); 36 37 // Verify we get the ERR_PROXY_CONNECTION_FAILED screen. 38 bool result = false; 39 EXPECT_TRUE(content::ExecuteScriptAndExtractBool( 40 browser->tab_strip_model()->GetActiveWebContents(), 41 "var textContent = document.body.textContent;" 42 "var hasError = textContent.indexOf('ERR_PROXY_CONNECTION_FAILED') >= 0;" 43 "domAutomationController.send(hasError);", 44 &result)); 45 EXPECT_TRUE(result); 46} 47 48// This class observes chrome::NOTIFICATION_AUTH_NEEDED and supplies 49// the credential which is required by the test proxy server. 50// "foo:bar" is the required username and password for our test proxy server. 51class LoginPromptObserver : public content::NotificationObserver { 52 public: 53 LoginPromptObserver() : auth_handled_(false) {} 54 55 virtual void Observe(int type, 56 const content::NotificationSource& source, 57 const content::NotificationDetails& details) OVERRIDE { 58 if (type == chrome::NOTIFICATION_AUTH_NEEDED) { 59 LoginNotificationDetails* login_details = 60 content::Details<LoginNotificationDetails>(details).ptr(); 61 // |login_details->handler()| is the associated LoginHandler object. 62 // SetAuth() will close the login dialog. 63 login_details->handler()->SetAuth(base::ASCIIToUTF16("foo"), 64 base::ASCIIToUTF16("bar")); 65 auth_handled_ = true; 66 } 67 } 68 69 bool auth_handled() const { return auth_handled_; } 70 71 private: 72 bool auth_handled_; 73 74 DISALLOW_COPY_AND_ASSIGN(LoginPromptObserver); 75}; 76 77class ProxyBrowserTest : public InProcessBrowserTest { 78 public: 79 ProxyBrowserTest() 80 : proxy_server_(net::SpawnedTestServer::TYPE_BASIC_AUTH_PROXY, 81 net::SpawnedTestServer::kLocalhost, 82 base::FilePath()) { 83 } 84 85 virtual void SetUp() OVERRIDE { 86 ASSERT_TRUE(proxy_server_.Start()); 87 InProcessBrowserTest::SetUp(); 88 } 89 90 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 91 command_line->AppendSwitchASCII(switches::kProxyServer, 92 proxy_server_.host_port_pair().ToString()); 93 } 94 95 protected: 96 net::SpawnedTestServer proxy_server_; 97 98 private: 99 100 DISALLOW_COPY_AND_ASSIGN(ProxyBrowserTest); 101}; 102 103#if defined(OS_CHROMEOS) 104// We bypass manually installed proxy for localhost on chromeos. 105#define MAYBE_BasicAuthWSConnect DISABLED_BasicAuthWSConnect 106#else 107#define MAYBE_BasicAuthWSConnect BasicAuthWSConnect 108#endif 109// Test that the browser can establish a WebSocket connection via a proxy 110// that requires basic authentication. 111IN_PROC_BROWSER_TEST_F(ProxyBrowserTest, MAYBE_BasicAuthWSConnect) { 112 // Launch WebSocket server. 113 net::SpawnedTestServer ws_server(net::SpawnedTestServer::TYPE_WS, 114 net::SpawnedTestServer::kLocalhost, 115 net::GetWebSocketTestDataDirectory()); 116 ASSERT_TRUE(ws_server.Start()); 117 118 content::WebContents* tab = 119 browser()->tab_strip_model()->GetActiveWebContents(); 120 content::NavigationController* controller = &tab->GetController(); 121 content::NotificationRegistrar registrar; 122 // The proxy server will request basic authentication. 123 // |observer| supplies the credential. 124 LoginPromptObserver observer; 125 registrar.Add(&observer, chrome::NOTIFICATION_AUTH_NEEDED, 126 content::Source<content::NavigationController>(controller)); 127 128 content::TitleWatcher watcher(tab, base::ASCIIToUTF16("PASS")); 129 watcher.AlsoWaitForTitle(base::ASCIIToUTF16("FAIL")); 130 131 // Visit a page that tries to establish WebSocket connection. The title 132 // of the page will be 'PASS' on success. 133 std::string scheme("http"); 134 GURL::Replacements replacements; 135 replacements.SetSchemeStr(scheme); 136 ui_test_utils::NavigateToURL( 137 browser(), 138 ws_server.GetURL("connect_check.html").ReplaceComponents(replacements)); 139 140 const base::string16 result = watcher.WaitAndGetTitle(); 141 EXPECT_TRUE(EqualsASCII(result, "PASS")); 142 EXPECT_TRUE(observer.auth_handled()); 143} 144 145// Fetch PAC script via an http:// URL. 146class HttpProxyScriptBrowserTest : public InProcessBrowserTest { 147 public: 148 HttpProxyScriptBrowserTest() 149 : http_server_(net::SpawnedTestServer::TYPE_HTTP, 150 net::SpawnedTestServer::kLocalhost, 151 base::FilePath(FILE_PATH_LITERAL("chrome/test/data"))) { 152 } 153 virtual ~HttpProxyScriptBrowserTest() {} 154 155 virtual void SetUp() OVERRIDE { 156 ASSERT_TRUE(http_server_.Start()); 157 InProcessBrowserTest::SetUp(); 158 } 159 160 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 161 base::FilePath pac_script_path(FILE_PATH_LITERAL("files")); 162 command_line->AppendSwitchASCII(switches::kProxyPacUrl, http_server_.GetURL( 163 pac_script_path.Append(kPACScript).MaybeAsASCII()).spec()); 164 } 165 166 private: 167 net::SpawnedTestServer http_server_; 168 169 DISALLOW_COPY_AND_ASSIGN(HttpProxyScriptBrowserTest); 170}; 171 172IN_PROC_BROWSER_TEST_F(HttpProxyScriptBrowserTest, Verify) { 173 VerifyProxyScript(browser()); 174} 175 176// Fetch PAC script via a file:// URL. 177class FileProxyScriptBrowserTest : public InProcessBrowserTest { 178 public: 179 FileProxyScriptBrowserTest() {} 180 virtual ~FileProxyScriptBrowserTest() {} 181 182 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 183 command_line->AppendSwitchASCII(switches::kProxyPacUrl, 184 ui_test_utils::GetTestUrl( 185 base::FilePath(base::FilePath::kCurrentDirectory), 186 base::FilePath(kPACScript)).spec()); 187 } 188 189 private: 190 DISALLOW_COPY_AND_ASSIGN(FileProxyScriptBrowserTest); 191}; 192 193IN_PROC_BROWSER_TEST_F(FileProxyScriptBrowserTest, Verify) { 194 VerifyProxyScript(browser()); 195} 196 197// Fetch PAC script via an ftp:// URL. 198class FtpProxyScriptBrowserTest : public InProcessBrowserTest { 199 public: 200 FtpProxyScriptBrowserTest() 201 : ftp_server_(net::SpawnedTestServer::TYPE_FTP, 202 net::SpawnedTestServer::kLocalhost, 203 base::FilePath(FILE_PATH_LITERAL("chrome/test/data"))) { 204 } 205 virtual ~FtpProxyScriptBrowserTest() {} 206 207 virtual void SetUp() OVERRIDE { 208 ASSERT_TRUE(ftp_server_.Start()); 209 InProcessBrowserTest::SetUp(); 210 } 211 212 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 213 base::FilePath pac_script_path(kPACScript); 214 command_line->AppendSwitchASCII( 215 switches::kProxyPacUrl, 216 ftp_server_.GetURL(pac_script_path.MaybeAsASCII()).spec()); 217 } 218 219 private: 220 net::SpawnedTestServer ftp_server_; 221 222 DISALLOW_COPY_AND_ASSIGN(FtpProxyScriptBrowserTest); 223}; 224 225IN_PROC_BROWSER_TEST_F(FtpProxyScriptBrowserTest, Verify) { 226 VerifyProxyScript(browser()); 227} 228 229// Fetch PAC script via a data: URL. 230class DataProxyScriptBrowserTest : public InProcessBrowserTest { 231 public: 232 DataProxyScriptBrowserTest() {} 233 virtual ~DataProxyScriptBrowserTest() {} 234 235 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 236 std::string contents; 237 // Read in kPACScript contents. 238 ASSERT_TRUE(base::ReadFileToString(ui_test_utils::GetTestFilePath( 239 base::FilePath(base::FilePath::kCurrentDirectory), 240 base::FilePath(kPACScript)), 241 &contents)); 242 command_line->AppendSwitchASCII(switches::kProxyPacUrl, 243 std::string("data:,") + contents); 244 } 245 246 private: 247 DISALLOW_COPY_AND_ASSIGN(DataProxyScriptBrowserTest); 248}; 249 250IN_PROC_BROWSER_TEST_F(DataProxyScriptBrowserTest, Verify) { 251 VerifyProxyScript(browser()); 252} 253 254} // namespace 255