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 "chrome/test/ppapi/ppapi_test.h"
7 #include "base/command_line.h"
8 #include "base/file_util.h"
9 #include "base/path_service.h"
10 #include "base/strings/string_util.h"
11 #include "base/strings/stringprintf.h"
12 #include "chrome/browser/chrome_notification_types.h"
13 #include "chrome/browser/content_settings/host_content_settings_map.h"
14 #include "chrome/browser/infobars/confirm_infobar_delegate.h"
15 #include "chrome/browser/infobars/infobar.h"
16 #include "chrome/browser/profiles/profile.h"
17 #include "chrome/browser/ui/browser.h"
18 #include "chrome/browser/ui/tabs/tab_strip_model.h"
19 #include "chrome/common/chrome_paths.h"
20 #include "chrome/common/chrome_switches.h"
21 #include "chrome/test/base/test_switches.h"
22 #include "chrome/test/base/ui_test_utils.h"
23 #include "content/public/browser/dom_operation_notification_details.h"
24 #include "content/public/browser/notification_service.h"
25 #include "content/public/browser/web_contents.h"
26 #include "net/base/net_util.h"
27 #include "net/base/test_data_directory.h"
28 #include "ppapi/shared_impl/ppapi_switches.h"
29 #include "ui/gl/gl_switches.h"
31 using content::DomOperationNotificationDetails
;
32 using content::RenderViewHost
;
34 #if defined(DISABLE_NACL)
35 #define RETURN_IF_NO_NACL() do { \
36 LOG(WARNING) << "This test always passes with disable_nacl=1."; \
39 #define RETURN_IF_NO_NACL() do { } while (0)
44 // Platform-specific filename relative to the chrome executable.
46 const wchar_t library_name
[] = L
"ppapi_tests.dll";
47 #elif defined(OS_MACOSX)
48 const char library_name
[] = "ppapi_tests.plugin";
49 #elif defined(OS_POSIX)
50 const char library_name
[] = "libppapi_tests.so";
53 void AddPrivateSwitches(CommandLine
* command_line
) {
54 // For TestRequestOSFileHandle.
55 command_line
->AppendSwitch(switches::kUnlimitedStorage
);
56 command_line
->AppendSwitchASCII(switches::kAllowNaClFileHandleAPI
,
62 PPAPITestMessageHandler::PPAPITestMessageHandler() {
65 TestMessageHandler::MessageResponse
PPAPITestMessageHandler::HandleMessage(
66 const std::string
& json
) {
68 base::TrimString(json
, "\"", &trimmed
);
75 void PPAPITestMessageHandler::Reset() {
76 TestMessageHandler::Reset();
80 PPAPITestBase::InfoBarObserver::InfoBarObserver(PPAPITestBase
* test_base
)
81 : test_base_(test_base
),
82 expecting_infobar_(false),
83 should_accept_(false) {
84 registrar_
.Add(this, chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_ADDED
,
85 content::NotificationService::AllSources());
88 PPAPITestBase::InfoBarObserver::~InfoBarObserver() {
89 EXPECT_FALSE(expecting_infobar_
) << "Missing an expected infobar";
92 void PPAPITestBase::InfoBarObserver::ExpectInfoBarAndAccept(
94 ASSERT_FALSE(expecting_infobar_
);
95 expecting_infobar_
= true;
96 should_accept_
= should_accept
;
99 void PPAPITestBase::InfoBarObserver::Observe(
101 const content::NotificationSource
& source
,
102 const content::NotificationDetails
& details
) {
103 ASSERT_EQ(chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_ADDED
, type
);
104 // It's not safe to remove the infobar here, since other observers (e.g. the
105 // InfoBarContainer) may still need to access it. Instead, post a task to
106 // do all necessary infobar manipulation as soon as this call stack returns.
107 base::MessageLoop::current()->PostTask(
108 FROM_HERE
, base::Bind(&InfoBarObserver::VerifyInfoBarState
,
109 base::Unretained(this)));
112 void PPAPITestBase::InfoBarObserver::VerifyInfoBarState() {
113 content::WebContents
* web_contents
=
114 test_base_
->browser()->tab_strip_model()->GetActiveWebContents();
115 ASSERT_TRUE(web_contents
!= NULL
);
116 InfoBarService
* infobar_service
=
117 InfoBarService::FromWebContents(web_contents
);
118 ASSERT_TRUE(infobar_service
!= NULL
);
120 EXPECT_EQ(expecting_infobar_
? 1U : 0U, infobar_service
->infobar_count());
121 if (!expecting_infobar_
)
123 expecting_infobar_
= false;
125 InfoBar
* infobar
= infobar_service
->infobar_at(0);
126 ConfirmInfoBarDelegate
* delegate
=
127 infobar
->delegate()->AsConfirmInfoBarDelegate();
128 ASSERT_TRUE(delegate
!= NULL
);
134 infobar_service
->RemoveInfoBar(infobar
);
137 PPAPITestBase::PPAPITestBase() {
140 void PPAPITestBase::SetUp() {
142 InProcessBrowserTest::SetUp();
145 void PPAPITestBase::SetUpCommandLine(CommandLine
* command_line
) {
146 // The test sends us the result via a cookie.
147 command_line
->AppendSwitch(switches::kEnableFileCookies
);
149 // Some stuff is hung off of the testing interface which is not enabled
151 command_line
->AppendSwitch(switches::kEnablePepperTesting
);
153 // Smooth scrolling confuses the scrollbar test.
154 command_line
->AppendSwitch(switches::kDisableSmoothScrolling
);
157 void PPAPITestBase::SetUpOnMainThread() {
158 // Always allow access to the PPAPI broker.
159 browser()->profile()->GetHostContentSettingsMap()->SetDefaultContentSetting(
160 CONTENT_SETTINGS_TYPE_PPAPI_BROKER
, CONTENT_SETTING_ALLOW
);
163 GURL
PPAPITestBase::GetTestFileUrl(const std::string
& test_case
) {
164 base::FilePath test_path
;
165 EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT
, &test_path
));
166 test_path
= test_path
.Append(FILE_PATH_LITERAL("ppapi"));
167 test_path
= test_path
.Append(FILE_PATH_LITERAL("tests"));
168 test_path
= test_path
.Append(FILE_PATH_LITERAL("test_case.html"));
170 // Sanity check the file name.
171 EXPECT_TRUE(base::PathExists(test_path
));
173 GURL test_url
= net::FilePathToFileURL(test_path
);
175 GURL::Replacements replacements
;
176 std::string query
= BuildQuery(std::string(), test_case
);
177 replacements
.SetQuery(query
.c_str(), url_parse::Component(0, query
.size()));
178 return test_url
.ReplaceComponents(replacements
);
181 void PPAPITestBase::RunTest(const std::string
& test_case
) {
182 GURL url
= GetTestFileUrl(test_case
);
186 void PPAPITestBase::RunTestAndReload(const std::string
& test_case
) {
187 GURL url
= GetTestFileUrl(test_case
);
189 // If that passed, we simply run the test again, which navigates again.
193 void PPAPITestBase::RunTestViaHTTP(const std::string
& test_case
) {
194 base::FilePath document_root
;
195 ASSERT_TRUE(ui_test_utils::GetRelativeBuildDirectory(&document_root
));
196 base::FilePath http_document_root
;
197 ASSERT_TRUE(ui_test_utils::GetRelativeBuildDirectory(&http_document_root
));
198 net::SpawnedTestServer
http_server(net::SpawnedTestServer::TYPE_HTTP
,
199 net::SpawnedTestServer::kLocalhost
,
201 ASSERT_TRUE(http_server
.Start());
202 RunTestURL(GetTestURL(http_server
, test_case
, std::string()));
205 void PPAPITestBase::RunTestWithSSLServer(const std::string
& test_case
) {
206 base::FilePath http_document_root
;
207 ASSERT_TRUE(ui_test_utils::GetRelativeBuildDirectory(&http_document_root
));
208 net::SpawnedTestServer
http_server(net::SpawnedTestServer::TYPE_HTTP
,
209 net::SpawnedTestServer::kLocalhost
,
211 net::SpawnedTestServer
ssl_server(net::SpawnedTestServer::TYPE_HTTPS
,
212 net::BaseTestServer::SSLOptions(),
214 // Start the servers in parallel.
215 ASSERT_TRUE(http_server
.StartInBackground());
216 ASSERT_TRUE(ssl_server
.StartInBackground());
217 // Wait until they are both finished before continuing.
218 ASSERT_TRUE(http_server
.BlockUntilStarted());
219 ASSERT_TRUE(ssl_server
.BlockUntilStarted());
221 uint16_t port
= ssl_server
.host_port_pair().port();
222 RunTestURL(GetTestURL(http_server
,
224 base::StringPrintf("ssl_server_port=%d", port
)));
227 void PPAPITestBase::RunTestWithWebSocketServer(const std::string
& test_case
) {
228 base::FilePath http_document_root
;
229 ASSERT_TRUE(ui_test_utils::GetRelativeBuildDirectory(&http_document_root
));
230 net::SpawnedTestServer
http_server(net::SpawnedTestServer::TYPE_HTTP
,
231 net::SpawnedTestServer::kLocalhost
,
233 net::SpawnedTestServer
ws_server(net::SpawnedTestServer::TYPE_WS
,
234 net::SpawnedTestServer::kLocalhost
,
235 net::GetWebSocketTestDataDirectory());
236 // Start the servers in parallel.
237 ASSERT_TRUE(http_server
.StartInBackground());
238 ASSERT_TRUE(ws_server
.StartInBackground());
239 // Wait until they are both finished before continuing.
240 ASSERT_TRUE(http_server
.BlockUntilStarted());
241 ASSERT_TRUE(ws_server
.BlockUntilStarted());
243 std::string host
= ws_server
.host_port_pair().HostForURL();
244 uint16_t port
= ws_server
.host_port_pair().port();
245 RunTestURL(GetTestURL(http_server
,
248 "websocket_host=%s&websocket_port=%d",
253 void PPAPITestBase::RunTestIfAudioOutputAvailable(
254 const std::string
& test_case
) {
258 void PPAPITestBase::RunTestViaHTTPIfAudioOutputAvailable(
259 const std::string
& test_case
) {
260 RunTestViaHTTP(test_case
);
263 std::string
PPAPITestBase::StripPrefixes(const std::string
& test_name
) {
264 const char* const prefixes
[] = {
265 "FAILS_", "FLAKY_", "DISABLED_", "SLOW_" };
266 for (size_t i
= 0; i
< sizeof(prefixes
)/sizeof(prefixes
[0]); ++i
)
267 if (test_name
.find(prefixes
[i
]) == 0)
268 return test_name
.substr(strlen(prefixes
[i
]));
272 void PPAPITestBase::RunTestURL(const GURL
& test_url
) {
273 #if defined(OS_WIN) && defined(USE_ASH)
274 // PPAPITests are broken in Ash browser tests (http://crbug.com/263548).
275 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests
)) {
276 LOG(WARNING
) << "PPAPITests are disabled for Ash browser tests.";
281 // See comment above TestingInstance in ppapi/test/testing_instance.h.
282 // Basically it sends messages using the DOM automation controller. The
283 // value of "..." means it's still working and we should continue to wait,
284 // any other value indicates completion (in this case it will start with
285 // "PASS" or "FAIL"). This keeps us from timing out on waits for long tests.
286 PPAPITestMessageHandler handler
;
287 JavascriptTestObserver
observer(
288 browser()->tab_strip_model()->GetActiveWebContents(),
291 ui_test_utils::NavigateToURL(browser(), test_url
);
293 ASSERT_TRUE(observer
.Run()) << handler
.error_message();
294 EXPECT_STREQ("PASS", handler
.message().c_str());
297 GURL
PPAPITestBase::GetTestURL(
298 const net::SpawnedTestServer
& http_server
,
299 const std::string
& test_case
,
300 const std::string
& extra_params
) {
301 std::string query
= BuildQuery("files/test_case.html?", test_case
);
302 if (!extra_params
.empty())
303 query
= base::StringPrintf("%s&%s", query
.c_str(), extra_params
.c_str());
305 return http_server
.GetURL(query
);
308 PPAPITest::PPAPITest() : in_process_(true) {
311 void PPAPITest::SetUpCommandLine(CommandLine
* command_line
) {
312 PPAPITestBase::SetUpCommandLine(command_line
);
314 // Append the switch to register the pepper plugin.
315 // library name = <out dir>/<test_name>.<library_extension>
316 // MIME type = application/x-ppapi-<test_name>
317 base::FilePath plugin_dir
;
318 EXPECT_TRUE(PathService::Get(base::DIR_MODULE
, &plugin_dir
));
320 base::FilePath plugin_lib
= plugin_dir
.Append(library_name
);
321 EXPECT_TRUE(base::PathExists(plugin_lib
));
322 base::FilePath::StringType pepper_plugin
= plugin_lib
.value();
323 pepper_plugin
.append(FILE_PATH_LITERAL(";application/x-ppapi-tests"));
324 command_line
->AppendSwitchNative(switches::kRegisterPepperPlugins
,
326 command_line
->AppendSwitchASCII(switches::kAllowNaClSocketAPI
, "127.0.0.1");
329 command_line
->AppendSwitch(switches::kPpapiInProcess
);
332 std::string
PPAPITest::BuildQuery(const std::string
& base
,
333 const std::string
& test_case
){
334 return base::StringPrintf("%stestcase=%s", base
.c_str(), test_case
.c_str());
337 void PPAPIPrivateTest::SetUpCommandLine(CommandLine
* command_line
) {
338 PPAPITest::SetUpCommandLine(command_line
);
339 AddPrivateSwitches(command_line
);
342 OutOfProcessPPAPITest::OutOfProcessPPAPITest() {
346 void OutOfProcessPPAPITest::SetUpCommandLine(CommandLine
* command_line
) {
347 PPAPITest::SetUpCommandLine(command_line
);
348 command_line
->AppendSwitch(switches::kUseFakeDeviceForMediaStream
);
349 command_line
->AppendSwitch(switches::kUseFakeUIForMediaStream
);
352 void OutOfProcessPPAPIPrivateTest::SetUpCommandLine(CommandLine
* command_line
) {
353 OutOfProcessPPAPITest::SetUpCommandLine(command_line
);
354 AddPrivateSwitches(command_line
);
357 void PPAPINaClTest::SetUpCommandLine(CommandLine
* command_line
) {
359 PPAPITestBase::SetUpCommandLine(command_line
);
361 base::FilePath plugin_lib
;
362 EXPECT_TRUE(PathService::Get(chrome::FILE_NACL_PLUGIN
, &plugin_lib
));
363 EXPECT_TRUE(base::PathExists(plugin_lib
));
365 // Enable running (non-portable) NaCl outside of the Chrome web store.
366 command_line
->AppendSwitch(switches::kEnableNaCl
);
367 command_line
->AppendSwitchASCII(switches::kAllowNaClSocketAPI
, "127.0.0.1");
368 command_line
->AppendSwitch(switches::kUseFakeDeviceForMediaStream
);
369 command_line
->AppendSwitch(switches::kUseFakeUIForMediaStream
);
372 void PPAPINaClTest::RunTest(const std::string
& test_case
) {
374 PPAPITestBase::RunTest(test_case
);
377 void PPAPINaClTest::RunTestAndReload(const std::string
& test_case
) {
379 PPAPITestBase::RunTestAndReload(test_case
);
382 void PPAPINaClTest::RunTestViaHTTP(const std::string
& test_case
) {
384 PPAPITestBase::RunTestViaHTTP(test_case
);
387 void PPAPINaClTest::RunTestWithSSLServer(const std::string
& test_case
) {
389 PPAPITestBase::RunTestWithSSLServer(test_case
);
392 void PPAPINaClTest::RunTestWithWebSocketServer(const std::string
& test_case
) {
394 PPAPITestBase::RunTestWithWebSocketServer(test_case
);
397 void PPAPINaClTest::RunTestIfAudioOutputAvailable(
398 const std::string
& test_case
) {
400 PPAPITestBase::RunTestIfAudioOutputAvailable(test_case
);
403 void PPAPINaClTest::RunTestViaHTTPIfAudioOutputAvailable(
404 const std::string
& test_case
) {
406 PPAPITestBase::RunTestViaHTTPIfAudioOutputAvailable(test_case
);
409 // Append the correct mode and testcase string
410 std::string
PPAPINaClNewlibTest::BuildQuery(const std::string
& base
,
411 const std::string
& test_case
) {
412 return base::StringPrintf("%smode=nacl_newlib&testcase=%s", base
.c_str(),
416 void PPAPIPrivateNaClNewlibTest::SetUpCommandLine(CommandLine
* command_line
) {
417 PPAPINaClNewlibTest::SetUpCommandLine(command_line
);
418 AddPrivateSwitches(command_line
);
421 // Append the correct mode and testcase string
422 std::string
PPAPINaClGLibcTest::BuildQuery(const std::string
& base
,
423 const std::string
& test_case
) {
424 return base::StringPrintf("%smode=nacl_glibc&testcase=%s", base
.c_str(),
428 void PPAPIPrivateNaClGLibcTest::SetUpCommandLine(CommandLine
* command_line
) {
429 PPAPINaClGLibcTest::SetUpCommandLine(command_line
);
430 AddPrivateSwitches(command_line
);
433 // Append the correct mode and testcase string
434 std::string
PPAPINaClPNaClTest::BuildQuery(const std::string
& base
,
435 const std::string
& test_case
) {
436 return base::StringPrintf("%smode=nacl_pnacl&testcase=%s", base
.c_str(),
440 void PPAPIPrivateNaClPNaClTest::SetUpCommandLine(CommandLine
* command_line
) {
441 PPAPINaClPNaClTest::SetUpCommandLine(command_line
);
442 AddPrivateSwitches(command_line
);
445 void PPAPINaClTestDisallowedSockets::SetUpCommandLine(
446 CommandLine
* command_line
) {
447 PPAPITestBase::SetUpCommandLine(command_line
);
449 base::FilePath plugin_lib
;
450 EXPECT_TRUE(PathService::Get(chrome::FILE_NACL_PLUGIN
, &plugin_lib
));
451 EXPECT_TRUE(base::PathExists(plugin_lib
));
453 // Enable running (non-portable) NaCl outside of the Chrome web store.
454 command_line
->AppendSwitch(switches::kEnableNaCl
);
457 // Append the correct mode and testcase string
458 std::string
PPAPINaClTestDisallowedSockets::BuildQuery(
459 const std::string
& base
,
460 const std::string
& test_case
) {
461 return base::StringPrintf("%smode=nacl_newlib&testcase=%s", base
.c_str(),
465 void PPAPIBrokerInfoBarTest::SetUpOnMainThread() {
466 // The default content setting for the PPAPI broker is ASK. We purposefully
467 // don't call PPAPITestBase::SetUpOnMainThread() to keep it that way.