| OLD | NEW |
| (Empty) |
| 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/bind.h" | |
| 6 #include "base/files/file_path.h" | |
| 7 #include "base/logging.h" | |
| 8 #include "base/path_service.h" | |
| 9 #include "base/strings/string_util.h" | |
| 10 #include "base/strings/stringprintf.h" | |
| 11 #include "base/strings/utf_string_conversions.h" | |
| 12 #include "base/sys_info.h" | |
| 13 #include "base/test/test_timeouts.h" | |
| 14 #include "content/browser/worker_host/worker_process_host.h" | |
| 15 #include "content/browser/worker_host/worker_service_impl.h" | |
| 16 #include "content/public/browser/browser_thread.h" | |
| 17 #include "content/public/common/content_paths.h" | |
| 18 #include "content/public/test/browser_test_utils.h" | |
| 19 #include "content/public/test/content_browser_test.h" | |
| 20 #include "content/public/test/content_browser_test_utils.h" | |
| 21 #include "content/public/test/test_utils.h" | |
| 22 #include "content/shell/browser/shell.h" | |
| 23 #include "content/shell/browser/shell_content_browser_client.h" | |
| 24 #include "content/shell/browser/shell_resource_dispatcher_host_delegate.h" | |
| 25 #include "net/base/test_data_directory.h" | |
| 26 #include "net/test/spawned_test_server/spawned_test_server.h" | |
| 27 #include "url/gurl.h" | |
| 28 | |
| 29 namespace content { | |
| 30 | |
| 31 class WorkerTest : public ContentBrowserTest { | |
| 32 public: | |
| 33 WorkerTest() {} | |
| 34 | |
| 35 GURL GetTestURL(const std::string& test_case, const std::string& query) { | |
| 36 base::FilePath test_file_path = GetTestFilePath( | |
| 37 "workers", test_case.c_str()); | |
| 38 return GetFileUrlWithQuery(test_file_path, query); | |
| 39 } | |
| 40 | |
| 41 void RunTest(Shell* window, | |
| 42 const std::string& test_case, | |
| 43 const std::string& query) { | |
| 44 GURL url = GetTestURL(test_case, query); | |
| 45 const base::string16 expected_title = base::ASCIIToUTF16("OK"); | |
| 46 TitleWatcher title_watcher(window->web_contents(), expected_title); | |
| 47 NavigateToURL(window, url); | |
| 48 base::string16 final_title = title_watcher.WaitAndGetTitle(); | |
| 49 EXPECT_EQ(expected_title, final_title); | |
| 50 } | |
| 51 | |
| 52 void RunTest(const std::string& test_case, const std::string& query) { | |
| 53 RunTest(shell(), test_case, query); | |
| 54 } | |
| 55 | |
| 56 static void CountWorkerProcesses(int *cur_process_count) { | |
| 57 *cur_process_count = 0; | |
| 58 for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) | |
| 59 (*cur_process_count)++; | |
| 60 BrowserThread::PostTask( | |
| 61 BrowserThread::UI, FROM_HERE, base::MessageLoop::QuitClosure()); | |
| 62 } | |
| 63 | |
| 64 bool WaitForWorkerProcessCount(int count) { | |
| 65 int cur_process_count; | |
| 66 for (int i = 0; i < 100; ++i) { | |
| 67 BrowserThread::PostTask( | |
| 68 BrowserThread::IO, FROM_HERE, | |
| 69 base::Bind(&CountWorkerProcesses, &cur_process_count)); | |
| 70 | |
| 71 RunMessageLoop(); | |
| 72 if (cur_process_count == count) | |
| 73 return true; | |
| 74 | |
| 75 // Sometimes the worker processes can take a while to shut down on the | |
| 76 // bots, so use a longer timeout period to avoid spurious failures. | |
| 77 base::PlatformThread::Sleep(TestTimeouts::action_max_timeout() / 100); | |
| 78 } | |
| 79 | |
| 80 EXPECT_EQ(cur_process_count, count); | |
| 81 return false; | |
| 82 } | |
| 83 | |
| 84 static void QuitUIMessageLoop(base::Callback<void()> callback) { | |
| 85 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback); | |
| 86 } | |
| 87 | |
| 88 void NavigateAndWaitForAuth(const GURL& url) { | |
| 89 ShellContentBrowserClient* browser_client = | |
| 90 ShellContentBrowserClient::Get(); | |
| 91 scoped_refptr<MessageLoopRunner> runner = new MessageLoopRunner(); | |
| 92 browser_client->resource_dispatcher_host_delegate()-> | |
| 93 set_login_request_callback( | |
| 94 base::Bind(&QuitUIMessageLoop, runner->QuitClosure())); | |
| 95 shell()->LoadURL(url); | |
| 96 runner->Run(); | |
| 97 } | |
| 98 }; | |
| 99 | |
| 100 IN_PROC_BROWSER_TEST_F(WorkerTest, SingleWorker) { | |
| 101 RunTest("single_worker.html", std::string()); | |
| 102 } | |
| 103 | |
| 104 IN_PROC_BROWSER_TEST_F(WorkerTest, MultipleWorkers) { | |
| 105 RunTest("multi_worker.html", std::string()); | |
| 106 } | |
| 107 | |
| 108 IN_PROC_BROWSER_TEST_F(WorkerTest, SingleSharedWorker) { | |
| 109 RunTest("single_worker.html", "shared=true"); | |
| 110 } | |
| 111 | |
| 112 // http://crbug.com/96435 | |
| 113 IN_PROC_BROWSER_TEST_F(WorkerTest, MultipleSharedWorkers) { | |
| 114 RunTest("multi_worker.html", "shared=true"); | |
| 115 } | |
| 116 | |
| 117 // Incognito windows should not share workers with non-incognito windows | |
| 118 // http://crbug.com/30021 | |
| 119 IN_PROC_BROWSER_TEST_F(WorkerTest, IncognitoSharedWorkers) { | |
| 120 // Load a non-incognito tab and have it create a shared worker | |
| 121 RunTest("incognito_worker.html", std::string()); | |
| 122 | |
| 123 // Incognito worker should not share with non-incognito | |
| 124 RunTest(CreateOffTheRecordBrowser(), "incognito_worker.html", std::string()); | |
| 125 } | |
| 126 | |
| 127 // Make sure that auth dialog is displayed from worker context. | |
| 128 // http://crbug.com/33344 | |
| 129 IN_PROC_BROWSER_TEST_F(WorkerTest, WorkerHttpAuth) { | |
| 130 ASSERT_TRUE(test_server()->Start()); | |
| 131 GURL url = test_server()->GetURL("files/workers/worker_auth.html"); | |
| 132 | |
| 133 NavigateAndWaitForAuth(url); | |
| 134 } | |
| 135 | |
| 136 // Make sure that auth dialog is displayed from shared worker context. | |
| 137 // http://crbug.com/33344 | |
| 138 IN_PROC_BROWSER_TEST_F(WorkerTest, SharedWorkerHttpAuth) { | |
| 139 ASSERT_TRUE(test_server()->Start()); | |
| 140 GURL url = test_server()->GetURL("files/workers/shared_worker_auth.html"); | |
| 141 NavigateAndWaitForAuth(url); | |
| 142 } | |
| 143 | |
| 144 #if defined(OS_LINUX) | |
| 145 // This test is flaky inside the Linux SUID sandbox. | |
| 146 // http://crbug.com/130116 | |
| 147 IN_PROC_BROWSER_TEST_F(WorkerTest, DISABLED_LimitPerPage) { | |
| 148 #else | |
| 149 IN_PROC_BROWSER_TEST_F(WorkerTest, LimitPerPage) { | |
| 150 #endif | |
| 151 // There is no limitation of SharedWorker if EmbeddedSharedWorker is enabled. | |
| 152 if (WorkerService::EmbeddedSharedWorkerEnabled()) | |
| 153 return; | |
| 154 int max_workers_per_tab = WorkerServiceImpl::kMaxWorkersPerFrameWhenSeparate; | |
| 155 std::string query = base::StringPrintf("?count=%d", max_workers_per_tab + 1); | |
| 156 | |
| 157 GURL url = GetTestURL("many_shared_workers.html", query); | |
| 158 NavigateToURL(shell(), url); | |
| 159 ASSERT_TRUE(WaitForWorkerProcessCount(max_workers_per_tab)); | |
| 160 } | |
| 161 | |
| 162 | |
| 163 #if defined(OS_LINUX) || defined(OS_MACOSX) | |
| 164 // This test is flaky inside the Linux SUID sandbox: http://crbug.com/130116 | |
| 165 // Also flaky on Mac: http://crbug.com/295193 | |
| 166 IN_PROC_BROWSER_TEST_F(WorkerTest, DISABLED_LimitTotal) { | |
| 167 #else | |
| 168 // http://crbug.com/36800 | |
| 169 IN_PROC_BROWSER_TEST_F(WorkerTest, LimitTotal) { | |
| 170 #endif | |
| 171 // There is no limitation of SharedWorker if EmbeddedSharedWorker is enabled. | |
| 172 if (WorkerService::EmbeddedSharedWorkerEnabled()) | |
| 173 return; | |
| 174 if (base::SysInfo::AmountOfPhysicalMemoryMB() < 8192) { | |
| 175 VLOG(0) << "WorkerTest.LimitTotal not running because it needs 8 GB RAM."; | |
| 176 return; | |
| 177 } | |
| 178 | |
| 179 int max_workers_per_tab = WorkerServiceImpl::kMaxWorkersPerFrameWhenSeparate; | |
| 180 int total_workers = WorkerServiceImpl::kMaxWorkersWhenSeparate; | |
| 181 | |
| 182 std::string query = base::StringPrintf("?count=%d", max_workers_per_tab); | |
| 183 GURL url = GetTestURL("many_shared_workers.html", query); | |
| 184 NavigateToURL(shell(), | |
| 185 GURL(url.spec() + base::StringPrintf("&client_id=0"))); | |
| 186 | |
| 187 // Adding 1 so that we cause some workers to be queued. | |
| 188 int tab_count = (total_workers / max_workers_per_tab) + 1; | |
| 189 for (int i = 1; i < tab_count; ++i) { | |
| 190 NavigateToURL( | |
| 191 CreateBrowser(), | |
| 192 GURL(url.spec() + base::StringPrintf("&client_id=%d", i))); | |
| 193 } | |
| 194 | |
| 195 // Check that we didn't create more than the max number of workers. | |
| 196 ASSERT_TRUE(WaitForWorkerProcessCount(total_workers)); | |
| 197 | |
| 198 // Now close a page and check that the queued workers were started. | |
| 199 url = GURL(GetTestUrl("google", "google.html")); | |
| 200 NavigateToURL(shell(), url); | |
| 201 | |
| 202 ASSERT_TRUE(WaitForWorkerProcessCount(total_workers)); | |
| 203 } | |
| 204 | |
| 205 // Flaky, http://crbug.com/59786. | |
| 206 IN_PROC_BROWSER_TEST_F(WorkerTest, WorkerClose) { | |
| 207 RunTest("worker_close.html", std::string()); | |
| 208 ASSERT_TRUE(WaitForWorkerProcessCount(0)); | |
| 209 } | |
| 210 | |
| 211 // Flaky, http://crbug.com/70861. | |
| 212 // Times out regularly on Windows debug bots. See http://crbug.com/212339 . | |
| 213 // Times out on Mac as well. | |
| 214 IN_PROC_BROWSER_TEST_F(WorkerTest, DISABLED_QueuedSharedWorkerShutdown) { | |
| 215 // Tests to make sure that queued shared workers are started up when shared | |
| 216 // workers shut down. | |
| 217 int max_workers_per_tab = WorkerServiceImpl::kMaxWorkersPerFrameWhenSeparate; | |
| 218 std::string query = base::StringPrintf("?count=%d", max_workers_per_tab); | |
| 219 RunTest("queued_shared_worker_shutdown.html", query); | |
| 220 ASSERT_TRUE(WaitForWorkerProcessCount(max_workers_per_tab)); | |
| 221 } | |
| 222 | |
| 223 // Flaky, http://crbug.com/69881. | |
| 224 // Sometimes triggers | |
| 225 // Check failed: message_ports_[message_port_id].queued_messages.empty(). | |
| 226 IN_PROC_BROWSER_TEST_F(WorkerTest, DISABLED_MultipleTabsQueuedSharedWorker) { | |
| 227 // Tests to make sure that only one instance of queued shared workers are | |
| 228 // started up even when those instances are on multiple tabs. | |
| 229 int max_workers_per_tab = WorkerServiceImpl::kMaxWorkersPerFrameWhenSeparate; | |
| 230 std::string query = base::StringPrintf("?count=%d", max_workers_per_tab + 1); | |
| 231 GURL url = GetTestURL("many_shared_workers.html", query); | |
| 232 NavigateToURL(shell(), url); | |
| 233 ASSERT_TRUE(WaitForWorkerProcessCount(max_workers_per_tab)); | |
| 234 | |
| 235 // Create same set of workers in new tab (leaves one worker queued from this | |
| 236 // tab). | |
| 237 url = GetTestURL("many_shared_workers.html", query); | |
| 238 NavigateToURL(CreateBrowser(), url); | |
| 239 ASSERT_TRUE(WaitForWorkerProcessCount(max_workers_per_tab)); | |
| 240 | |
| 241 // Now shutdown one of the shared workers - this will fire both queued | |
| 242 // workers, but only one instance should be started. | |
| 243 url = GetTestURL("shutdown_shared_worker.html", "?id=0"); | |
| 244 NavigateToURL(CreateBrowser(), url); | |
| 245 ASSERT_TRUE(WaitForWorkerProcessCount(max_workers_per_tab)); | |
| 246 } | |
| 247 | |
| 248 // Flaky: http://crbug.com/48148 | |
| 249 IN_PROC_BROWSER_TEST_F(WorkerTest, DISABLED_QueuedSharedWorkerStartedFromOtherTa
b) { | |
| 250 // Tests to make sure that queued shared workers are started up when | |
| 251 // an instance is launched from another tab. | |
| 252 int max_workers_per_tab = WorkerServiceImpl::kMaxWorkersPerFrameWhenSeparate; | |
| 253 std::string query = base::StringPrintf("?count=%d", max_workers_per_tab + 1); | |
| 254 GURL url = GetTestURL("many_shared_workers.html", query); | |
| 255 NavigateToURL(shell(), url); | |
| 256 ASSERT_TRUE(WaitForWorkerProcessCount(max_workers_per_tab)); | |
| 257 | |
| 258 // First window has hit its limit. Now launch second window which creates | |
| 259 // the same worker that was queued in the first window, to ensure it gets | |
| 260 // connected to the first window too. | |
| 261 query = base::StringPrintf("?id=%d", max_workers_per_tab); | |
| 262 url = GetTestURL("single_shared_worker.html", query); | |
| 263 NavigateToURL(CreateBrowser(), url); | |
| 264 | |
| 265 ASSERT_TRUE(WaitForWorkerProcessCount(max_workers_per_tab + 1)); | |
| 266 } | |
| 267 | |
| 268 IN_PROC_BROWSER_TEST_F(WorkerTest, WebSocketSharedWorker) { | |
| 269 // Launch WebSocket server. | |
| 270 net::SpawnedTestServer ws_server(net::SpawnedTestServer::TYPE_WS, | |
| 271 net::SpawnedTestServer::kLocalhost, | |
| 272 net::GetWebSocketTestDataDirectory()); | |
| 273 ASSERT_TRUE(ws_server.Start()); | |
| 274 | |
| 275 // Generate test URL. | |
| 276 std::string scheme("http"); | |
| 277 GURL::Replacements replacements; | |
| 278 replacements.SetSchemeStr(scheme); | |
| 279 GURL url = ws_server.GetURL( | |
| 280 "websocket_shared_worker.html").ReplaceComponents(replacements); | |
| 281 | |
| 282 // Run test. | |
| 283 Shell* window = shell(); | |
| 284 const base::string16 expected_title = base::ASCIIToUTF16("OK"); | |
| 285 TitleWatcher title_watcher(window->web_contents(), expected_title); | |
| 286 NavigateToURL(window, url); | |
| 287 base::string16 final_title = title_watcher.WaitAndGetTitle(); | |
| 288 EXPECT_EQ(expected_title, final_title); | |
| 289 } | |
| 290 | |
| 291 IN_PROC_BROWSER_TEST_F(WorkerTest, PassMessagePortToSharedWorker) { | |
| 292 RunTest("pass_messageport_to_sharedworker.html", ""); | |
| 293 } | |
| 294 | |
| 295 IN_PROC_BROWSER_TEST_F(WorkerTest, | |
| 296 PassMessagePortToSharedWorkerDontWaitForConnect) { | |
| 297 RunTest("pass_messageport_to_sharedworker_dont_wait_for_connect.html", ""); | |
| 298 } | |
| 299 | |
| 300 } // namespace content | |
| OLD | NEW |