• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 The Chromium Embedded Framework Authors. All rights
2 // reserved. Use of this source code is governed by a BSD-style license that
3 // can be found in the LICENSE file.
4 
5 #include "include/base/cef_build.h"
6 #include "include/cef_config.h"
7 
8 #if defined(OS_LINUX) && defined(CEF_X11)
9 #include <X11/Xlib.h>
10 // Definitions conflict with gtest.
11 #undef None
12 #undef Bool
13 #endif
14 
15 #if defined(OS_POSIX)
16 #include <unistd.h>
17 #endif
18 
19 #include "include/base/cef_callback.h"
20 #include "include/cef_app.h"
21 #include "include/cef_task.h"
22 #include "include/cef_thread.h"
23 #include "include/cef_waitable_event.h"
24 #include "include/wrapper/cef_closure_task.h"
25 #include "include/wrapper/cef_helpers.h"
26 #include "tests/ceftests/test_handler.h"
27 #include "tests/ceftests/test_server.h"
28 #include "tests/ceftests/test_suite.h"
29 #include "tests/shared/browser/client_app_browser.h"
30 #include "tests/shared/browser/main_message_loop_external_pump.h"
31 #include "tests/shared/browser/main_message_loop_std.h"
32 #include "tests/shared/common/client_app_other.h"
33 #include "tests/shared/renderer/client_app_renderer.h"
34 
35 #if defined(OS_MAC)
36 #include "include/wrapper/cef_library_loader.h"
37 #endif
38 
39 // When generating projects with CMake the CEF_USE_SANDBOX value will be defined
40 // automatically if using the required compiler version. Pass -DUSE_SANDBOX=OFF
41 // to the CMake command-line to disable use of the sandbox.
42 #if defined(OS_WIN) && defined(CEF_USE_SANDBOX)
43 #include "include/cef_sandbox_win.h"
44 
45 // The cef_sandbox.lib static library may not link successfully with all VS
46 // versions.
47 #pragma comment(lib, "cef_sandbox.lib")
48 #endif
49 
50 namespace {
51 
QuitMessageLoop()52 void QuitMessageLoop() {
53   CEF_REQUIRE_UI_THREAD();
54   client::MainMessageLoop* message_loop = client::MainMessageLoop::Get();
55   if (message_loop)
56     message_loop->Quit();
57   else
58     CefQuitMessageLoop();
59 }
60 
sleep(int64 ms)61 void sleep(int64 ms) {
62 #if defined(OS_WIN)
63   Sleep(ms);
64 #elif defined(OS_POSIX)
65   usleep(ms * 1000);
66 #else
67 #error Unsupported platform
68 #endif
69 }
70 
71 // Called on the test thread.
RunTestsOnTestThread()72 void RunTestsOnTestThread() {
73   // Run the test suite.
74   CefTestSuite::GetInstance()->Run();
75 
76   // Wait for all browsers to exit.
77   while (TestHandler::HasBrowser())
78     sleep(100);
79 
80   // Wait for the test server to stop, and then quit the CEF message loop.
81   test_server::Stop(base::BindOnce(QuitMessageLoop));
82 }
83 
84 // Called on the UI thread.
ContinueOnUIThread(CefRefPtr<CefTaskRunner> test_task_runner)85 void ContinueOnUIThread(CefRefPtr<CefTaskRunner> test_task_runner) {
86   // Run the test suite on the test thread.
87   test_task_runner->PostTask(
88       CefCreateClosureTask(base::BindOnce(&RunTestsOnTestThread)));
89 }
90 
91 #if defined(OS_LINUX) && defined(CEF_X11)
XErrorHandlerImpl(Display * display,XErrorEvent * event)92 int XErrorHandlerImpl(Display* display, XErrorEvent* event) {
93   LOG(WARNING) << "X error received: "
94                << "type " << event->type << ", "
95                << "serial " << event->serial << ", "
96                << "error_code " << static_cast<int>(event->error_code) << ", "
97                << "request_code " << static_cast<int>(event->request_code)
98                << ", "
99                << "minor_code " << static_cast<int>(event->minor_code);
100   return 0;
101 }
102 
XIOErrorHandlerImpl(Display * display)103 int XIOErrorHandlerImpl(Display* display) {
104   return 0;
105 }
106 #endif  // defined(OS_LINUX) && defined(CEF_X11)
107 
108 }  // namespace
109 
main(int argc,char * argv[])110 int main(int argc, char* argv[]) {
111 #if defined(OS_MAC)
112   // Load the CEF framework library at runtime instead of linking directly
113   // as required by the macOS sandbox implementation.
114   CefScopedLibraryLoader library_loader;
115   if (!library_loader.LoadInMain())
116     return 1;
117 #endif
118 
119   // Create the singleton test suite object.
120   CefTestSuite test_suite(argc, argv);
121 
122 #if defined(OS_WIN)
123   if (test_suite.command_line()->HasSwitch("enable-high-dpi-support")) {
124     // Enable High-DPI support on Windows 7 and newer.
125     CefEnableHighDPISupport();
126   }
127 
128   CefMainArgs main_args(::GetModuleHandle(nullptr));
129 #else
130   CefMainArgs main_args(argc, argv);
131 #endif
132 
133   void* windows_sandbox_info = nullptr;
134 
135 #if defined(OS_WIN) && defined(CEF_USE_SANDBOX)
136   // Manages the life span of the sandbox information object.
137   CefScopedSandboxInfo scoped_sandbox;
138   windows_sandbox_info = scoped_sandbox.sandbox_info();
139 #endif
140 
141   // Create a ClientApp of the correct type.
142   CefRefPtr<CefApp> app;
143   client::ClientApp::ProcessType process_type =
144       client::ClientApp::GetProcessType(test_suite.command_line());
145   if (process_type == client::ClientApp::BrowserProcess) {
146     app = new client::ClientAppBrowser();
147 #if !defined(OS_MAC)
148   } else if (process_type == client::ClientApp::RendererProcess ||
149              process_type == client::ClientApp::ZygoteProcess) {
150     app = new client::ClientAppRenderer();
151   } else if (process_type == client::ClientApp::OtherProcess) {
152     app = new client::ClientAppOther();
153   }
154 
155   // Execute the secondary process, if any.
156   int exit_code = CefExecuteProcess(main_args, app, windows_sandbox_info);
157   if (exit_code >= 0)
158     return exit_code;
159 #else
160   } else {
161     // On OS X this executable is only used for the main process.
162     NOTREACHED();
163   }
164 #endif
165 
166   CefSettings settings;
167 
168 #if !defined(CEF_USE_SANDBOX)
169   settings.no_sandbox = true;
170 #endif
171 
172   client::ClientAppBrowser::PopulateSettings(test_suite.command_line(),
173                                              settings);
174   test_suite.GetSettings(settings);
175 
176 #if defined(OS_MAC)
177   // Platform-specific initialization.
178   extern void PlatformInit();
179   PlatformInit();
180 #endif
181 
182 #if defined(OS_LINUX) && defined(CEF_X11)
183   // Install xlib error handlers so that the application won't be terminated
184   // on non-fatal errors.
185   XSetErrorHandler(XErrorHandlerImpl);
186   XSetIOErrorHandler(XIOErrorHandlerImpl);
187 #endif
188 
189   // Create the MessageLoop.
190   std::unique_ptr<client::MainMessageLoop> message_loop;
191   if (!settings.multi_threaded_message_loop) {
192     if (settings.external_message_pump)
193       message_loop = client::MainMessageLoopExternalPump::Create();
194     else
195       message_loop.reset(new client::MainMessageLoopStd);
196   }
197 
198   // Initialize CEF.
199   CefInitialize(main_args, settings, app, windows_sandbox_info);
200 
201   // Initialize the testing framework.
202   test_suite.InitMainProcess();
203 
204   int retval;
205 
206   if (settings.multi_threaded_message_loop) {
207     // Run the test suite on the main thread.
208     retval = test_suite.Run();
209 
210     // Wait for the test server to stop.
211     CefRefPtr<CefWaitableEvent> event =
212         CefWaitableEvent::CreateWaitableEvent(true, false);
213     test_server::Stop(base::BindOnce(&CefWaitableEvent::Signal, event));
214     event->Wait();
215   } else {
216     // Create and start the test thread.
217     CefRefPtr<CefThread> thread = CefThread::CreateThread("test_thread");
218     if (!thread)
219       return 1;
220 
221     // Start the tests from the UI thread so that any pending UI tasks get a
222     // chance to execute first.
223     CefPostTask(TID_UI,
224                 base::BindOnce(&ContinueOnUIThread, thread->GetTaskRunner()));
225 
226     // Run the CEF message loop.
227     message_loop->Run();
228 
229     // The test suite has completed.
230     retval = test_suite.retval();
231 
232     // Terminate the test thread.
233     thread->Stop();
234     thread = nullptr;
235   }
236 
237   // Shut down CEF.
238   CefShutdown();
239 
240   test_suite.DeleteTempDirectories();
241 
242   // Destroy the MessageLoop.
243   message_loop.reset(nullptr);
244 
245 #if defined(OS_MAC)
246   // Platform-specific cleanup.
247   extern void PlatformCleanup();
248   PlatformCleanup();
249 #endif
250 
251   return retval;
252 }
253