• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "chrome/test/ppapi/ppapi_test.h"
6 
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"
30 
31 using content::DomOperationNotificationDetails;
32 using content::RenderViewHost;
33 
34 namespace {
35 
36 // Platform-specific filename relative to the chrome executable.
37 #if defined(OS_WIN)
38 const wchar_t library_name[] = L"ppapi_tests.dll";
39 #elif defined(OS_MACOSX)
40 const char library_name[] = "ppapi_tests.plugin";
41 #elif defined(OS_POSIX)
42 const char library_name[] = "libppapi_tests.so";
43 #endif
44 
45 }  // namespace
46 
PPAPITestMessageHandler()47 PPAPITestMessageHandler::PPAPITestMessageHandler() {
48 }
49 
HandleMessage(const std::string & json)50 TestMessageHandler::MessageResponse PPAPITestMessageHandler::HandleMessage(
51     const std::string& json) {
52   std::string trimmed;
53   base::TrimString(json, "\"", &trimmed);
54   if (trimmed == "...")
55     return CONTINUE;
56   message_ = trimmed;
57   return DONE;
58 }
59 
Reset()60 void PPAPITestMessageHandler::Reset() {
61   TestMessageHandler::Reset();
62   message_.clear();
63 }
64 
InfoBarObserver(PPAPITestBase * test_base)65 PPAPITestBase::InfoBarObserver::InfoBarObserver(PPAPITestBase* test_base)
66     : test_base_(test_base),
67       expecting_infobar_(false),
68       should_accept_(false) {
69   registrar_.Add(this, chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_ADDED,
70                  content::NotificationService::AllSources());
71 }
72 
~InfoBarObserver()73 PPAPITestBase::InfoBarObserver::~InfoBarObserver() {
74   EXPECT_FALSE(expecting_infobar_) << "Missing an expected infobar";
75 }
76 
ExpectInfoBarAndAccept(bool should_accept)77 void PPAPITestBase::InfoBarObserver::ExpectInfoBarAndAccept(
78     bool should_accept) {
79   ASSERT_FALSE(expecting_infobar_);
80   expecting_infobar_ = true;
81   should_accept_ = should_accept;
82 }
83 
Observe(int type,const content::NotificationSource & source,const content::NotificationDetails & details)84 void PPAPITestBase::InfoBarObserver::Observe(
85     int type,
86     const content::NotificationSource& source,
87     const content::NotificationDetails& details) {
88   ASSERT_EQ(chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_ADDED, type);
89   // It's not safe to remove the infobar here, since other observers (e.g. the
90   // InfoBarContainer) may still need to access it.  Instead, post a task to
91   // do all necessary infobar manipulation as soon as this call stack returns.
92   base::MessageLoop::current()->PostTask(
93       FROM_HERE, base::Bind(&InfoBarObserver::VerifyInfoBarState,
94                             base::Unretained(this)));
95 }
96 
VerifyInfoBarState()97 void PPAPITestBase::InfoBarObserver::VerifyInfoBarState() {
98   content::WebContents* web_contents =
99       test_base_->browser()->tab_strip_model()->GetActiveWebContents();
100   ASSERT_TRUE(web_contents != NULL);
101   InfoBarService* infobar_service =
102       InfoBarService::FromWebContents(web_contents);
103   ASSERT_TRUE(infobar_service != NULL);
104 
105   EXPECT_EQ(expecting_infobar_ ? 1U : 0U, infobar_service->infobar_count());
106   if (!expecting_infobar_)
107     return;
108   expecting_infobar_ = false;
109 
110   InfoBar* infobar = infobar_service->infobar_at(0);
111   ConfirmInfoBarDelegate* delegate =
112       infobar->delegate()->AsConfirmInfoBarDelegate();
113   ASSERT_TRUE(delegate != NULL);
114   if (should_accept_)
115     delegate->Accept();
116   else
117     delegate->Cancel();
118 
119   infobar_service->RemoveInfoBar(infobar);
120 }
121 
PPAPITestBase()122 PPAPITestBase::PPAPITestBase() {
123 }
124 
SetUpCommandLine(CommandLine * command_line)125 void PPAPITestBase::SetUpCommandLine(CommandLine* command_line) {
126   // The test sends us the result via a cookie.
127   command_line->AppendSwitch(switches::kEnableFileCookies);
128 
129   // Some stuff is hung off of the testing interface which is not enabled
130   // by default.
131   command_line->AppendSwitch(switches::kEnablePepperTesting);
132 
133   // Smooth scrolling confuses the scrollbar test.
134   command_line->AppendSwitch(switches::kDisableSmoothScrolling);
135 
136   // For TestRequestOSFileHandle.
137   command_line->AppendSwitch(switches::kUnlimitedStorage);
138   command_line->AppendSwitchASCII(switches::kAllowNaClFileHandleAPI,
139                                   "127.0.0.1");
140 }
141 
SetUpOnMainThread()142 void PPAPITestBase::SetUpOnMainThread() {
143   // Always allow access to the PPAPI broker.
144   browser()->profile()->GetHostContentSettingsMap()->SetDefaultContentSetting(
145       CONTENT_SETTINGS_TYPE_PPAPI_BROKER, CONTENT_SETTING_ALLOW);
146 }
147 
GetTestFileUrl(const std::string & test_case)148 GURL PPAPITestBase::GetTestFileUrl(const std::string& test_case) {
149   base::FilePath test_path;
150   EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &test_path));
151   test_path = test_path.Append(FILE_PATH_LITERAL("ppapi"));
152   test_path = test_path.Append(FILE_PATH_LITERAL("tests"));
153   test_path = test_path.Append(FILE_PATH_LITERAL("test_case.html"));
154 
155   // Sanity check the file name.
156   EXPECT_TRUE(base::PathExists(test_path));
157 
158   GURL test_url = net::FilePathToFileURL(test_path);
159 
160   GURL::Replacements replacements;
161   std::string query = BuildQuery(std::string(), test_case);
162   replacements.SetQuery(query.c_str(), url_parse::Component(0, query.size()));
163   return test_url.ReplaceComponents(replacements);
164 }
165 
RunTest(const std::string & test_case)166 void PPAPITestBase::RunTest(const std::string& test_case) {
167   GURL url = GetTestFileUrl(test_case);
168   RunTestURL(url);
169 }
170 
RunTestAndReload(const std::string & test_case)171 void PPAPITestBase::RunTestAndReload(const std::string& test_case) {
172   GURL url = GetTestFileUrl(test_case);
173   RunTestURL(url);
174   // If that passed, we simply run the test again, which navigates again.
175   RunTestURL(url);
176 }
177 
RunTestViaHTTP(const std::string & test_case)178 void PPAPITestBase::RunTestViaHTTP(const std::string& test_case) {
179   base::FilePath document_root;
180   ASSERT_TRUE(ui_test_utils::GetRelativeBuildDirectory(&document_root));
181   base::FilePath http_document_root;
182   ASSERT_TRUE(ui_test_utils::GetRelativeBuildDirectory(&http_document_root));
183   net::SpawnedTestServer http_server(net::SpawnedTestServer::TYPE_HTTP,
184                                      net::SpawnedTestServer::kLocalhost,
185                                      document_root);
186   ASSERT_TRUE(http_server.Start());
187   RunTestURL(GetTestURL(http_server, test_case, std::string()));
188 }
189 
RunTestWithSSLServer(const std::string & test_case)190 void PPAPITestBase::RunTestWithSSLServer(const std::string& test_case) {
191   base::FilePath http_document_root;
192   ASSERT_TRUE(ui_test_utils::GetRelativeBuildDirectory(&http_document_root));
193   net::SpawnedTestServer http_server(net::SpawnedTestServer::TYPE_HTTP,
194                                      net::SpawnedTestServer::kLocalhost,
195                                      http_document_root);
196   net::SpawnedTestServer ssl_server(net::SpawnedTestServer::TYPE_HTTPS,
197                                     net::BaseTestServer::SSLOptions(),
198                                     http_document_root);
199   // Start the servers in parallel.
200   ASSERT_TRUE(http_server.StartInBackground());
201   ASSERT_TRUE(ssl_server.StartInBackground());
202   // Wait until they are both finished before continuing.
203   ASSERT_TRUE(http_server.BlockUntilStarted());
204   ASSERT_TRUE(ssl_server.BlockUntilStarted());
205 
206   uint16_t port = ssl_server.host_port_pair().port();
207   RunTestURL(GetTestURL(http_server,
208                         test_case,
209                         base::StringPrintf("ssl_server_port=%d", port)));
210 }
211 
RunTestWithWebSocketServer(const std::string & test_case)212 void PPAPITestBase::RunTestWithWebSocketServer(const std::string& test_case) {
213   base::FilePath http_document_root;
214   ASSERT_TRUE(ui_test_utils::GetRelativeBuildDirectory(&http_document_root));
215   net::SpawnedTestServer http_server(net::SpawnedTestServer::TYPE_HTTP,
216                                      net::SpawnedTestServer::kLocalhost,
217                                      http_document_root);
218   net::SpawnedTestServer ws_server(net::SpawnedTestServer::TYPE_WS,
219                                    net::SpawnedTestServer::kLocalhost,
220                                    net::GetWebSocketTestDataDirectory());
221   // Start the servers in parallel.
222   ASSERT_TRUE(http_server.StartInBackground());
223   ASSERT_TRUE(ws_server.StartInBackground());
224   // Wait until they are both finished before continuing.
225   ASSERT_TRUE(http_server.BlockUntilStarted());
226   ASSERT_TRUE(ws_server.BlockUntilStarted());
227 
228   std::string host = ws_server.host_port_pair().HostForURL();
229   uint16_t port = ws_server.host_port_pair().port();
230   RunTestURL(GetTestURL(http_server,
231                         test_case,
232                         base::StringPrintf(
233                             "websocket_host=%s&websocket_port=%d",
234                             host.c_str(),
235                             port)));
236 }
237 
RunTestIfAudioOutputAvailable(const std::string & test_case)238 void PPAPITestBase::RunTestIfAudioOutputAvailable(
239     const std::string& test_case) {
240   RunTest(test_case);
241 }
242 
RunTestViaHTTPIfAudioOutputAvailable(const std::string & test_case)243 void PPAPITestBase::RunTestViaHTTPIfAudioOutputAvailable(
244     const std::string& test_case) {
245   RunTestViaHTTP(test_case);
246 }
247 
StripPrefixes(const std::string & test_name)248 std::string PPAPITestBase::StripPrefixes(const std::string& test_name) {
249   const char* const prefixes[] = {
250       "FAILS_", "FLAKY_", "DISABLED_", "SLOW_" };
251   for (size_t i = 0; i < sizeof(prefixes)/sizeof(prefixes[0]); ++i)
252     if (test_name.find(prefixes[i]) == 0)
253       return test_name.substr(strlen(prefixes[i]));
254   return test_name;
255 }
256 
RunTestURL(const GURL & test_url)257 void PPAPITestBase::RunTestURL(const GURL& test_url) {
258 #if defined(OS_WIN) && defined(USE_ASH)
259   // PPAPITests are broken in Ash browser tests (http://crbug.com/263548).
260   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests)) {
261     LOG(WARNING) << "PPAPITests are disabled for Ash browser tests.";
262     return;
263   }
264 #endif
265 
266   // See comment above TestingInstance in ppapi/test/testing_instance.h.
267   // Basically it sends messages using the DOM automation controller. The
268   // value of "..." means it's still working and we should continue to wait,
269   // any other value indicates completion (in this case it will start with
270   // "PASS" or "FAIL"). This keeps us from timing out on waits for long tests.
271   PPAPITestMessageHandler handler;
272   JavascriptTestObserver observer(
273       browser()->tab_strip_model()->GetActiveWebContents()->GetRenderViewHost(),
274       &handler);
275 
276   ui_test_utils::NavigateToURL(browser(), test_url);
277 
278   ASSERT_TRUE(observer.Run()) << handler.error_message();
279   EXPECT_STREQ("PASS", handler.message().c_str());
280 }
281 
GetTestURL(const net::SpawnedTestServer & http_server,const std::string & test_case,const std::string & extra_params)282 GURL PPAPITestBase::GetTestURL(
283     const net::SpawnedTestServer& http_server,
284     const std::string& test_case,
285     const std::string& extra_params) {
286   std::string query = BuildQuery("files/test_case.html?", test_case);
287   if (!extra_params.empty())
288     query = base::StringPrintf("%s&%s", query.c_str(), extra_params.c_str());
289 
290   return http_server.GetURL(query);
291 }
292 
PPAPITest()293 PPAPITest::PPAPITest() : in_process_(true) {
294 }
295 
SetUpCommandLine(CommandLine * command_line)296 void PPAPITest::SetUpCommandLine(CommandLine* command_line) {
297   PPAPITestBase::SetUpCommandLine(command_line);
298 
299   // Append the switch to register the pepper plugin.
300   // library name = <out dir>/<test_name>.<library_extension>
301   // MIME type = application/x-ppapi-<test_name>
302   base::FilePath plugin_dir;
303   EXPECT_TRUE(PathService::Get(base::DIR_MODULE, &plugin_dir));
304 
305   base::FilePath plugin_lib = plugin_dir.Append(library_name);
306   EXPECT_TRUE(base::PathExists(plugin_lib));
307   base::FilePath::StringType pepper_plugin = plugin_lib.value();
308   pepper_plugin.append(FILE_PATH_LITERAL(";application/x-ppapi-tests"));
309   command_line->AppendSwitchNative(switches::kRegisterPepperPlugins,
310                                    pepper_plugin);
311   command_line->AppendSwitchASCII(switches::kAllowNaClSocketAPI, "127.0.0.1");
312 
313   if (in_process_)
314     command_line->AppendSwitch(switches::kPpapiInProcess);
315 }
316 
BuildQuery(const std::string & base,const std::string & test_case)317 std::string PPAPITest::BuildQuery(const std::string& base,
318                                   const std::string& test_case){
319   return base::StringPrintf("%stestcase=%s", base.c_str(), test_case.c_str());
320 }
321 
OutOfProcessPPAPITest()322 OutOfProcessPPAPITest::OutOfProcessPPAPITest() {
323   in_process_ = false;
324 }
325 
SetUpCommandLine(CommandLine * command_line)326 void OutOfProcessPPAPITest::SetUpCommandLine(CommandLine* command_line) {
327   PPAPITest::SetUpCommandLine(command_line);
328   command_line->AppendSwitch(switches::kUseFakeDeviceForMediaStream);
329   command_line->AppendSwitch(switches::kUseFakeUIForMediaStream);
330 }
331 
SetUpCommandLine(CommandLine * command_line)332 void PPAPINaClTest::SetUpCommandLine(CommandLine* command_line) {
333   PPAPITestBase::SetUpCommandLine(command_line);
334 
335   base::FilePath plugin_lib;
336   EXPECT_TRUE(PathService::Get(chrome::FILE_NACL_PLUGIN, &plugin_lib));
337   EXPECT_TRUE(base::PathExists(plugin_lib));
338 
339   // Enable running (non-portable) NaCl outside of the Chrome web store.
340   command_line->AppendSwitch(switches::kEnableNaCl);
341   command_line->AppendSwitchASCII(switches::kAllowNaClSocketAPI, "127.0.0.1");
342   command_line->AppendSwitch(switches::kUseFakeDeviceForMediaStream);
343   command_line->AppendSwitch(switches::kUseFakeUIForMediaStream);
344 }
345 
346 // Append the correct mode and testcase string
BuildQuery(const std::string & base,const std::string & test_case)347 std::string PPAPINaClNewlibTest::BuildQuery(const std::string& base,
348                                             const std::string& test_case) {
349   return base::StringPrintf("%smode=nacl_newlib&testcase=%s", base.c_str(),
350                             test_case.c_str());
351 }
352 
353 // Append the correct mode and testcase string
BuildQuery(const std::string & base,const std::string & test_case)354 std::string PPAPINaClGLibcTest::BuildQuery(const std::string& base,
355                                            const std::string& test_case) {
356   return base::StringPrintf("%smode=nacl_glibc&testcase=%s", base.c_str(),
357                             test_case.c_str());
358 }
359 
360 // Append the correct mode and testcase string
BuildQuery(const std::string & base,const std::string & test_case)361 std::string PPAPINaClPNaClTest::BuildQuery(const std::string& base,
362                                            const std::string& test_case) {
363   return base::StringPrintf("%smode=nacl_pnacl&testcase=%s", base.c_str(),
364                             test_case.c_str());
365 }
366 
SetUpCommandLine(CommandLine * command_line)367 void PPAPINaClTestDisallowedSockets::SetUpCommandLine(
368     CommandLine* command_line) {
369   PPAPITestBase::SetUpCommandLine(command_line);
370 
371   base::FilePath plugin_lib;
372   EXPECT_TRUE(PathService::Get(chrome::FILE_NACL_PLUGIN, &plugin_lib));
373   EXPECT_TRUE(base::PathExists(plugin_lib));
374 
375   // Enable running (non-portable) NaCl outside of the Chrome web store.
376   command_line->AppendSwitch(switches::kEnableNaCl);
377 }
378 
379 // Append the correct mode and testcase string
BuildQuery(const std::string & base,const std::string & test_case)380 std::string PPAPINaClTestDisallowedSockets::BuildQuery(
381     const std::string& base,
382     const std::string& test_case) {
383   return base::StringPrintf("%smode=nacl_newlib&testcase=%s", base.c_str(),
384                             test_case.c_str());
385 }
386 
SetUpOnMainThread()387 void PPAPIBrokerInfoBarTest::SetUpOnMainThread() {
388   // The default content setting for the PPAPI broker is ASK. We purposefully
389   // don't call PPAPITestBase::SetUpOnMainThread() to keep it that way.
390 }
391