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.
6 #include "base/file_path.h"
7 #include "base/logging.h"
8 #include "base/path_service.h"
9 #include "base/stringprintf.h"
10 #include "base/string_util.h"
11 #include "base/sys_info.h"
12 #include "base/test/test_timeouts.h"
13 #include "base/utf_string_conversions.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/test_utils.h"
20 #include "content/shell/shell.h"
21 #include "content/shell/shell_content_browser_client.h"
22 #include "content/shell/shell_resource_dispatcher_host_delegate.h"
23 #include "content/test/content_browser_test_utils.h"
24 #include "content/test/layout_browsertest.h"
25 #include "googleurl/src/gurl.h"
26 #include "net/base/test_data_directory.h"
27 #include "net/test/test_server.h"
31 class WorkerLayoutTest
: public InProcessBrowserLayoutTest
{
33 WorkerLayoutTest() : InProcessBrowserLayoutTest(
34 FilePath(), FilePath().AppendASCII("fast").AppendASCII("workers")) {
38 // Crashy, http://crbug.com/35965.
39 // Flaky, http://crbug.com/36555.
40 IN_PROC_BROWSER_TEST_F(WorkerLayoutTest
, DISABLED_WorkerClonePort
) {
41 RunLayoutTest("worker-cloneport.html");
44 // http://crbug.com/101996 (started flaking with WebKit roll 98537:98582).
45 IN_PROC_BROWSER_TEST_F(WorkerLayoutTest
, WorkerContextMultiPort
) {
46 RunLayoutTest("worker-context-multi-port.html");
49 IN_PROC_BROWSER_TEST_F(WorkerLayoutTest
, WorkerMessagePort
) {
50 RunLayoutTest("worker-messageport.html");
53 IN_PROC_BROWSER_TEST_F(WorkerLayoutTest
, WorkerMessagePortGC
) {
54 RunLayoutTest("worker-messageport-gc.html");
57 // http://crbug.com/101996 (started flaking with WebKit roll 98537:98582).
58 IN_PROC_BROWSER_TEST_F(WorkerLayoutTest
, WorkerMultiPort
) {
59 RunLayoutTest("worker-multi-port.html");
63 // SharedWorkerFastLayoutTests
65 IN_PROC_BROWSER_TEST_F(WorkerLayoutTest
, SharedWorkerFastConstructor
) {
66 RunLayoutTest("shared-worker-constructor.html");
69 IN_PROC_BROWSER_TEST_F(WorkerLayoutTest
, SharedWorkerFastContextGC
) {
70 RunLayoutTest("shared-worker-context-gc.html");
73 IN_PROC_BROWSER_TEST_F(WorkerLayoutTest
, SharedWorkerFastEventListener
) {
74 RunLayoutTest("shared-worker-event-listener.html");
77 IN_PROC_BROWSER_TEST_F(WorkerLayoutTest
, SharedWorkerFastException
) {
78 RunLayoutTest("shared-worker-exception.html");
81 IN_PROC_BROWSER_TEST_F(WorkerLayoutTest
, SharedWorkerFastGC
) {
82 RunLayoutTest("shared-worker-gc.html");
85 IN_PROC_BROWSER_TEST_F(WorkerLayoutTest
, SharedWorkerFastInIframe
) {
86 RunLayoutTest("shared-worker-in-iframe.html");
89 IN_PROC_BROWSER_TEST_F(WorkerLayoutTest
, SharedWorkerFastLoadError
) {
90 RunLayoutTest("shared-worker-load-error.html");
93 IN_PROC_BROWSER_TEST_F(WorkerLayoutTest
, SharedWorkerFastLocation
) {
94 RunLayoutTest("shared-worker-location.html");
97 IN_PROC_BROWSER_TEST_F(WorkerLayoutTest
, SharedWorkerFastName
) {
98 RunLayoutTest("shared-worker-name.html");
101 IN_PROC_BROWSER_TEST_F(WorkerLayoutTest
, SharedWorkerFastNavigator
) {
102 RunLayoutTest("shared-worker-navigator.html");
105 IN_PROC_BROWSER_TEST_F(WorkerLayoutTest
,
106 SharedWorkerFastReplaceGlobalConstructor
) {
107 RunLayoutTest("shared-worker-replace-global-constructor.html");
110 IN_PROC_BROWSER_TEST_F(WorkerLayoutTest
, SharedWorkerFastReplaceSelf
) {
111 RunLayoutTest("shared-worker-replace-self.html");
114 IN_PROC_BROWSER_TEST_F(WorkerLayoutTest
, SharedWorkerFastScriptError
) {
115 RunLayoutTest("shared-worker-script-error.html");
118 IN_PROC_BROWSER_TEST_F(WorkerLayoutTest
, SharedWorkerFastShared
) {
119 RunLayoutTest("shared-worker-shared.html");
122 IN_PROC_BROWSER_TEST_F(WorkerLayoutTest
, SharedWorkerFastSimple
) {
123 RunLayoutTest("shared-worker-simple.html");
126 class MessagePortTest
: public InProcessBrowserLayoutTest
{
128 MessagePortTest() : InProcessBrowserLayoutTest(
129 FilePath(), FilePath().AppendASCII("fast").AppendASCII("events")) {
133 // Flaky, http://crbug.com/34996.
134 IN_PROC_BROWSER_TEST_F(MessagePortTest
, Tests
) {
135 static const char* kLayoutTestFiles
[] = {
136 "message-channel-gc.html",
137 "message-channel-gc-2.html",
138 "message-channel-gc-3.html",
139 "message-channel-gc-4.html",
141 "message-port-clone.html",
142 "message-port-constructor-for-deleted-document.html",
143 "message-port-deleted-document.html",
144 "message-port-deleted-frame.html",
145 "message-port-inactive-document.html",
146 "message-port-multi.html",
147 "message-port-no-wrapper.html",
148 // Only works with run-webkit-tests --leaks.
149 // "message-channel-listener-circular-ownership.html",
152 for (size_t i
= 0; i
< arraysize(kLayoutTestFiles
); ++i
)
153 RunLayoutTest(kLayoutTestFiles
[i
]);
157 class WorkerHttpLayoutTest
: public InProcessBrowserLayoutTest
{
159 // The resources for these tests hardcode 8000, so must use that here. If
160 // multiple tests which use it run in parallel, then the test will fail but
161 // it'll run again at the end in serial and pass.
162 WorkerHttpLayoutTest() : InProcessBrowserLayoutTest(
163 FilePath().AppendASCII("http").AppendASCII("tests"),
164 FilePath().AppendASCII("workers"),
169 // http://crbug.com/16934
170 IN_PROC_BROWSER_TEST_F(WorkerHttpLayoutTest
, DISABLED_Tests
) {
171 static const char* kLayoutTestFiles
[] = {
172 "shared-worker-importScripts.html",
173 "shared-worker-redirect.html",
174 "text-encoding.html",
176 // Fails on the mac (and linux?):
177 // http://code.google.com/p/chromium/issues/detail?id=22599
178 "worker-importScripts.html",
180 "worker-redirect.html",
183 for (size_t i
= 0; i
< arraysize(kLayoutTestFiles
); ++i
)
184 RunHttpLayoutTest(kLayoutTestFiles
[i
]);
187 class WorkerXHRHttpLayoutTest
: public InProcessBrowserLayoutTest
{
189 WorkerXHRHttpLayoutTest() : InProcessBrowserLayoutTest(
190 FilePath().AppendASCII("http").AppendASCII("tests"),
191 FilePath().AppendASCII("xmlhttprequest").AppendASCII("workers"),
196 IN_PROC_BROWSER_TEST_F(WorkerXHRHttpLayoutTest
, Tests
) {
197 static const char* kLayoutTestFiles
[] = {
198 // worker thread count never drops to zero.
199 // http://crbug.com/150565
200 // "abort-exception-assert.html",
202 // Fails on the mac (and linux?):
203 // http://code.google.com/p/chromium/issues/detail?id=22599
206 // These tests (and the shared-worker versions below) are disabled due to
207 // limitations in lighttpd (doesn't handle all of the HTTP methods).
208 // "methods-async.html",
211 "shared-worker-close.html",
212 // Disabled due to limitations in lighttpd (does not handle methods other
213 // than GET/PUT/POST).
214 // "shared-worker-methods-async.html",
215 // "shared-worker-methods.html",
216 "shared-worker-xhr-file-not-found.html",
218 "xmlhttprequest-file-not-found.html"
221 for (size_t i
= 0; i
< arraysize(kLayoutTestFiles
); ++i
)
222 RunHttpLayoutTest(kLayoutTestFiles
[i
]);
225 class WorkerTest
: public ContentBrowserTest
{
229 GURL
GetTestURL(const std::string
& test_case
, const std::string
& query
) {
230 FilePath test_file_path
= GetTestFilePath(
231 "workers", test_case
.c_str());
232 return GetFileUrlWithQuery(test_file_path
, query
);
235 void RunTest(Shell
* window
,
236 const std::string
& test_case
,
237 const std::string
& query
) {
238 GURL url
= GetTestURL(test_case
, query
);
239 const string16 expected_title
= ASCIIToUTF16("OK");
240 TitleWatcher
title_watcher(window
->web_contents(), expected_title
);
241 NavigateToURL(window
, url
);
242 string16 final_title
= title_watcher
.WaitAndGetTitle();
243 EXPECT_EQ(expected_title
, final_title
);
246 void RunTest(const std::string
& test_case
, const std::string
& query
) {
247 RunTest(shell(), test_case
, query
);
250 static void CountWorkerProcesses(int *cur_process_count
) {
251 *cur_process_count
= 0;
252 for (WorkerProcessHostIterator iter
; !iter
.Done(); ++iter
)
253 (*cur_process_count
)++;
254 BrowserThread::PostTask(
255 BrowserThread::UI
, FROM_HERE
, MessageLoop::QuitClosure());
258 bool WaitForWorkerProcessCount(int count
) {
259 int cur_process_count
;
260 for (int i
= 0; i
< 100; ++i
) {
261 BrowserThread::PostTask(
262 BrowserThread::IO
, FROM_HERE
,
263 base::Bind(&CountWorkerProcesses
, &cur_process_count
));
266 if (cur_process_count
== count
)
269 // Sometimes the worker processes can take a while to shut down on the
270 // bots, so use a longer timeout period to avoid spurious failures.
271 base::PlatformThread::Sleep(TestTimeouts::action_max_timeout() / 100);
274 EXPECT_EQ(cur_process_count
, count
);
278 static void QuitUIMessageLoop(base::Callback
<void()> callback
) {
279 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
, callback
);
282 void NavigateAndWaitForAuth(const GURL
& url
) {
283 ShellContentBrowserClient
* browser_client
=
284 static_cast<ShellContentBrowserClient
*>(GetContentClient()->browser());
285 scoped_refptr
<MessageLoopRunner
> runner
= new MessageLoopRunner();
286 browser_client
->resource_dispatcher_host_delegate()->
287 set_login_request_callback(
288 base::Bind(&QuitUIMessageLoop
, runner
->QuitClosure()));
289 shell()->LoadURL(url
);
294 IN_PROC_BROWSER_TEST_F(WorkerTest
, SingleWorker
) {
295 RunTest("single_worker.html", "");
298 IN_PROC_BROWSER_TEST_F(WorkerTest
, MultipleWorkers
) {
299 RunTest("multi_worker.html", "");
302 IN_PROC_BROWSER_TEST_F(WorkerTest
, SingleSharedWorker
) {
303 RunTest("single_worker.html", "shared=true");
306 // http://crbug.com/96435
307 IN_PROC_BROWSER_TEST_F(WorkerTest
, MultipleSharedWorkers
) {
308 RunTest("multi_worker.html", "shared=true");
311 // Incognito windows should not share workers with non-incognito windows
312 // http://crbug.com/30021
313 IN_PROC_BROWSER_TEST_F(WorkerTest
, IncognitoSharedWorkers
) {
314 // Load a non-incognito tab and have it create a shared worker
315 RunTest("incognito_worker.html", "");
317 // Incognito worker should not share with non-incognito
318 RunTest(CreateOffTheRecordBrowser(), "incognito_worker.html", "");
321 // Make sure that auth dialog is displayed from worker context.
322 // http://crbug.com/33344
323 IN_PROC_BROWSER_TEST_F(WorkerTest
, WorkerHttpAuth
) {
324 ASSERT_TRUE(test_server()->Start());
325 GURL url
= test_server()->GetURL("files/workers/worker_auth.html");
327 NavigateAndWaitForAuth(url
);
330 // Make sure that auth dialog is displayed from shared worker context.
331 // http://crbug.com/33344
332 IN_PROC_BROWSER_TEST_F(WorkerTest
, SharedWorkerHttpAuth
) {
333 ASSERT_TRUE(test_server()->Start());
334 GURL url
= test_server()->GetURL("files/workers/shared_worker_auth.html");
335 NavigateAndWaitForAuth(url
);
338 #if defined(OS_LINUX) || defined(OS_CHROMEOS)
339 // This test is flaky inside the Linux SUID sandbox.
340 // http://crbug.com/130116
341 IN_PROC_BROWSER_TEST_F(WorkerTest
, DISABLED_LimitPerPage
) {
343 IN_PROC_BROWSER_TEST_F(WorkerTest
, LimitPerPage
) {
345 int max_workers_per_tab
= WorkerServiceImpl::kMaxWorkersPerTabWhenSeparate
;
346 std::string query
= StringPrintf("?count=%d", max_workers_per_tab
+ 1);
348 GURL url
= GetTestURL("many_shared_workers.html", query
);
349 NavigateToURL(shell(), url
);
350 ASSERT_TRUE(WaitForWorkerProcessCount(max_workers_per_tab
));
353 #if defined(OS_LINUX) || defined(OS_CHROMEOS)
354 // This test is flaky inside the Linux SUID sandbox.
355 // http://crbug.com/130116
356 IN_PROC_BROWSER_TEST_F(WorkerTest
, DISABLED_LimitTotal
) {
358 // http://crbug.com/36800
359 IN_PROC_BROWSER_TEST_F(WorkerTest
, LimitTotal
) {
361 if (base::SysInfo::AmountOfPhysicalMemoryMB() < 8192) {
362 LOG(INFO
) << "WorkerTest.LimitTotal not running because it needs 8 GB RAM.";
366 int max_workers_per_tab
= WorkerServiceImpl::kMaxWorkersPerTabWhenSeparate
;
367 int total_workers
= WorkerServiceImpl::kMaxWorkersWhenSeparate
;
369 std::string query
= StringPrintf("?count=%d", max_workers_per_tab
);
370 GURL url
= GetTestURL("many_shared_workers.html", query
);
371 NavigateToURL(shell(), GURL(url
.spec() + StringPrintf("&client_id=0")));
373 // Adding 1 so that we cause some workers to be queued.
374 int tab_count
= (total_workers
/ max_workers_per_tab
) + 1;
375 for (int i
= 1; i
< tab_count
; ++i
) {
377 CreateBrowser(), GURL(url
.spec() + StringPrintf("&client_id=%d", i
)));
380 // Check that we didn't create more than the max number of workers.
381 ASSERT_TRUE(WaitForWorkerProcessCount(total_workers
));
383 // Now close a page and check that the queued workers were started.
384 url
= GURL(GetTestUrl("google", "google.html"));
385 NavigateToURL(shell(), url
);
387 ASSERT_TRUE(WaitForWorkerProcessCount(total_workers
));
390 // Flaky, http://crbug.com/59786.
391 IN_PROC_BROWSER_TEST_F(WorkerTest
, WorkerClose
) {
392 RunTest("worker_close.html", "");
393 ASSERT_TRUE(WaitForWorkerProcessCount(0));
396 // Flaky, http://crbug.com/70861.
397 IN_PROC_BROWSER_TEST_F(WorkerTest
, QueuedSharedWorkerShutdown
) {
398 // Tests to make sure that queued shared workers are started up when shared
399 // workers shut down.
400 int max_workers_per_tab
= WorkerServiceImpl::kMaxWorkersPerTabWhenSeparate
;
401 std::string query
= StringPrintf("?count=%d", max_workers_per_tab
);
402 RunTest("queued_shared_worker_shutdown.html", query
);
403 ASSERT_TRUE(WaitForWorkerProcessCount(max_workers_per_tab
));
406 // Flaky, http://crbug.com/69881.
407 // Sometimes triggers
408 // Check failed: message_ports_[message_port_id].queued_messages.empty().
409 IN_PROC_BROWSER_TEST_F(WorkerTest
, DISABLED_MultipleTabsQueuedSharedWorker
) {
410 // Tests to make sure that only one instance of queued shared workers are
411 // started up even when those instances are on multiple tabs.
412 int max_workers_per_tab
= WorkerServiceImpl::kMaxWorkersPerTabWhenSeparate
;
413 std::string query
= StringPrintf("?count=%d", max_workers_per_tab
+ 1);
414 GURL url
= GetTestURL("many_shared_workers.html", query
);
415 NavigateToURL(shell(), url
);
416 ASSERT_TRUE(WaitForWorkerProcessCount(max_workers_per_tab
));
418 // Create same set of workers in new tab (leaves one worker queued from this
420 url
= GetTestURL("many_shared_workers.html", query
);
421 NavigateToURL(CreateBrowser(), url
);
422 ASSERT_TRUE(WaitForWorkerProcessCount(max_workers_per_tab
));
424 // Now shutdown one of the shared workers - this will fire both queued
425 // workers, but only one instance should be started.
426 url
= GetTestURL("shutdown_shared_worker.html", "?id=0");
427 NavigateToURL(CreateBrowser(), url
);
428 ASSERT_TRUE(WaitForWorkerProcessCount(max_workers_per_tab
));
431 // Flaky: http://crbug.com/48148
432 IN_PROC_BROWSER_TEST_F(WorkerTest
, DISABLED_QueuedSharedWorkerStartedFromOtherTab
) {
433 // Tests to make sure that queued shared workers are started up when
434 // an instance is launched from another tab.
435 int max_workers_per_tab
= WorkerServiceImpl::kMaxWorkersPerTabWhenSeparate
;
436 std::string query
= StringPrintf("?count=%d", max_workers_per_tab
+ 1);
437 GURL url
= GetTestURL("many_shared_workers.html", query
);
438 NavigateToURL(shell(), url
);
439 ASSERT_TRUE(WaitForWorkerProcessCount(max_workers_per_tab
));
441 // First window has hit its limit. Now launch second window which creates
442 // the same worker that was queued in the first window, to ensure it gets
443 // connected to the first window too.
444 query
= StringPrintf("?id=%d", max_workers_per_tab
);
445 url
= GetTestURL("single_shared_worker.html", query
);
446 NavigateToURL(CreateBrowser(), url
);
448 ASSERT_TRUE(WaitForWorkerProcessCount(max_workers_per_tab
+ 1));
451 IN_PROC_BROWSER_TEST_F(WorkerTest
, WebSocketSharedWorker
) {
452 // Launch WebSocket server.
453 net::TestServer
ws_server(net::TestServer::TYPE_WS
,
454 net::TestServer::kLocalhost
,
455 net::GetWebSocketTestDataDirectory());
456 ASSERT_TRUE(ws_server
.Start());
458 // Generate test URL.
459 std::string
scheme("http");
460 GURL::Replacements replacements
;
461 replacements
.SetSchemeStr(scheme
);
462 GURL url
= ws_server
.GetURL(
463 "websocket_shared_worker.html").ReplaceComponents(replacements
);
466 Shell
* window
= shell();
467 const string16 expected_title
= ASCIIToUTF16("OK");
468 TitleWatcher
title_watcher(window
->web_contents(), expected_title
);
469 NavigateToURL(window
, url
);
470 string16 final_title
= title_watcher
.WaitAndGetTitle();
471 EXPECT_EQ(expected_title
, final_title
);
474 } // namespace content